From a22e4cfb8b1ebe069de605f4a749e593c10ee880 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Sat, 7 Feb 2026 14:41:29 -0800 Subject: [PATCH] remove ivanm-dfinity-razer and uber-loaner host references Both hosts are long dead. Removes their CSS files, taffybar host config entries, and synergy aliases. Co-Authored-By: Claude Opus 4.6 --- .../config/taffybar/ivanm-dfinity-razer.css | 211 -------- dotfiles/config/taffybar/taffybar.hs | 511 ++++++++++-------- dotfiles/config/taffybar/uber-loaner.css | 203 ------- dotfiles/synergy.conf | 3 - 4 files changed, 271 insertions(+), 657 deletions(-) delete mode 100644 dotfiles/config/taffybar/ivanm-dfinity-razer.css delete mode 100644 dotfiles/config/taffybar/uber-loaner.css diff --git a/dotfiles/config/taffybar/ivanm-dfinity-razer.css b/dotfiles/config/taffybar/ivanm-dfinity-razer.css deleted file mode 100644 index f8d03490..00000000 --- a/dotfiles/config/taffybar/ivanm-dfinity-razer.css +++ /dev/null @@ -1,211 +0,0 @@ -@define-color transparent rgba(0.0, 0.0, 0.0, 0.0); -@define-color white #FFFFFF; -@define-color black #000000; -@define-color taffy-blue #0c7cd5; - -@define-color active-window-color @white; -@define-color urgent-window-color @taffy-blue; -@define-color font-color @white; -@define-color menu-background-color @white; -@define-color menu-font-color @black; - -/* Top level styling */ - -.taffy-window * { - font-family: "Noto Sans", sans-serif; - font-size: 10pt; - color: @font-color; -} - -.taffy-box { - border-color: @white; - border-style: solid; - border-radius: 0px; -} - -.inner-pad { - padding: 3px; -} - -.contents { - padding: 1px; - transition: border-color .5s, background-color .5s, border-style 3s; - border-radius: 6px; - /* This transparent border is needed because we will run in to sizing issues - without it because we only check sizing one time. */ - border-color: @transparent; - border-width: 2px; - border-style: solid; -} - -/* Workspaces styling */ - -.workspace-label { - padding-right: 3px; - padding-left: 2px; - font-size: 10pt; -} - -.active .contents { - background-color: rgba(0.0, 0.0, 0.0, 0.2); - border-color: @font-color; - border-style: solid; -} - -.visible .contents { - background-color: rgba(0.0, 0.0, 0.0, 0.2); - border-style: dotted; - border-color: @font-color; -} - -.window-icon-container { - transition: opacity .5s, box-shadow .5s, background-color .5s; - opacity: 1; - border-radius: 5px; -} - -/* This gives space for the box-shadow (they look like underlines) that follow. - This will actually affect all widgets, (not just the workspace icons), but - that is what we want since we want the icons to look the same. */ -.auto-size-image, .sni-tray { - padding: 0px; -} - -.window-icon-container.active { - background-color: @font-color; -} - -.window-icon-container.urgent { -} - -.window-icon-container.inactive .window-icon { - padding: 0px; -} - -.window-icon-container.minimized .window-icon { - opacity: .3; -} - -.window-icon { - opacity: 1; - transition: opacity .5s; -} - -/* Button styling */ - -.taffy-window button { - all: initial; - background-color: @transparent; - border-width: 0px; - border-radius: 0px; -} - -.taffy-window button:checked, .taffy-window button:hover .Contents:hover { - box-shadow: inset 0 -3px @taffy-blue; -} - -/* Menu styling */ - -/* The ".taffy-window" prefixed selectors are needed because if they aren't present, - the top level .Taffybar selector takes precedence */ -.taffy-window menuitem *, menuitem * { - color: @menu-font-color; -} - -/* Force an opaque background for menus, regardless of the system GTK theme. */ -.taffy-window menu, menu, -.taffy-window menu.background, menu.background, -.taffy-window .menu, .menu, -.taffy-window .menu.background, .menu.background, -GtkMenu, GtkMenu.background { - background-color: @menu-background-color; - background-image: none; - border: 1px solid rgba(0, 0, 0, 0.20); - padding: 4px 0px; -} - -.taffy-window menu, menu { - background-color: @menu-background-color; - background-image: none; -} - -/* Some themes apply transparency to the menu's toplevel popup window. */ -window.popup, window.popup.background, -window.menu, window.menu.background, -.menu, .menu.background { - background-color: @menu-background-color; - background-image: none; -} - -window.popup *, window.menu * { - background-color: @menu-background-color; - background-image: none; -} - -window.popup decoration, window.menu decoration { - background-color: @menu-background-color; - background-image: none; -} - -.taffy-window menuitem, menuitem { - background-color: @menu-background-color; -} - -menu menuitem, GtkMenu menuitem, .menu menuitem { - background-color: @menu-background-color; -} - -.taffy-window menuitem:hover, menuitem:hover { - background-color: @taffy-blue; -} - -menu menuitem:hover, GtkMenu menuitem:hover, .menu menuitem:hover { - background-color: @taffy-blue; -} - -window.popup menuitem:hover *, window.menu menuitem:hover * { - background-color: @taffy-blue; -} - -menu *, GtkMenu *, .menu * { - background-color: @menu-background-color; - background-image: none; -} - -menu menuitem:hover *, GtkMenu menuitem:hover *, .menu menuitem:hover * { - background-color: @taffy-blue; -} - -.taffy-window menuitem:hover > label, menuitem:hover > label { - color: @menu-font-color; -} - -/* Some menus (notably a few StatusNotifierItem menus) are rendered as popovers - containing modelbuttons instead of menuitems. */ -popover, popover.background, popover > contents { - background-color: @menu-background-color; - background-image: none; - border: 1px solid rgba(0, 0, 0, 0.20); -} - -popover modelbutton, popover modelbutton * { - background-color: @menu-background-color; - color: @menu-font-color; -} - -popover modelbutton:hover { - background-color: @taffy-blue; -} - -popover modelbutton:hover > label { - color: @menu-font-color; -} - -popover * { - background-color: @menu-background-color; - background-image: none; -} - -popover modelbutton:hover * { - background-color: @taffy-blue; -} diff --git a/dotfiles/config/taffybar/taffybar.hs b/dotfiles/config/taffybar/taffybar.hs index f84fcef2..b1be3a9b 100644 --- a/dotfiles/config/taffybar/taffybar.hs +++ b/dotfiles/config/taffybar/taffybar.hs @@ -1,118 +1,76 @@ +{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} -{-# LANGUAGE DataKinds #-} -module Main where -import Control.Exception.Base -import Control.Monad -import Control.Monad.IO.Class -import Control.Monad.Trans.Class -import Control.Monad.Trans.Reader -import qualified Data.ByteString.Char8 as BS -import Data.List -import Data.List.Split +module Main (main) where + +import Control.Monad (guard, when) +import Control.Monad.IO.Class (MonadIO, liftIO) +import Data.Int (Int32) +import Data.List (nub) import qualified Data.Map as M -import Data.Maybe -import qualified Data.Text -import Data.Time +import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe) +import Data.Text (Text) +import qualified Data.Text as T import qualified GI.GdkPixbuf.Objects.Pixbuf as Gdk import qualified GI.Gtk as Gtk -import qualified GI.Gtk.Objects.Overlay as Gtk -import Network.HostName -import System.Directory -import System.Environment -import System.Environment.XDG.BaseDir -import System.FilePath.Posix -import System.IO -import System.Log.Handler.Simple -import System.Log.Logger -import System.Process -import System.Taffybar -import System.Taffybar.Context (Backend(..), TaffyIO, appendHook, detectBackend) +import Network.HostName (getHostName) +import System.Directory (doesPathExist) +import System.Environment (lookupEnv, setEnv, unsetEnv) +import System.Environment.XDG.BaseDir (getUserConfigFile) +import System.FilePath.Posix (()) +import System.Log.Logger (Priority (..), getLogger, logM, saveGlobalLogger, setLevel) +import System.Taffybar (startTaffybar) +import System.Taffybar.Context (Backend (BackendWayland, BackendX11), TaffyIO, detectBackend) import System.Taffybar.DBus import System.Taffybar.DBus.Toggle -import System.Taffybar.Hooks -import System.Taffybar.Information.CPU -import System.Taffybar.Information.EWMHDesktopInfo -import System.Taffybar.Information.Memory +import System.Taffybar.Information.EWMHDesktopInfo (WorkspaceId (..)) import System.Taffybar.Information.X11DesktopInfo import System.Taffybar.SimpleConfig -import System.Taffybar.Util +import System.Taffybar.Util (getPixbufFromFilePath, (<|||>), maybeTCombine) import System.Taffybar.Widget -import System.Taffybar.Widget.Generic.Icon -import System.Taffybar.Widget.Generic.PollingGraph -import System.Taffybar.Widget.Generic.PollingLabel +import qualified System.Taffybar.Widget.HyprlandWorkspaces as Hyprland import qualified System.Taffybar.Widget.NetworkManager as NetworkManager import qualified System.Taffybar.Widget.PulseAudio as PulseAudio import System.Taffybar.Widget.SNITray ( sniTrayNew , sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt ) -import System.Taffybar.Widget.Util -import qualified System.Taffybar.Widget.HyprlandWorkspaces as Hyprland +import System.Taffybar.Widget.Util (buildContentsBox, loadPixbufByName, widgetSetClassGI) import qualified System.Taffybar.Widget.Workspaces as X11Workspaces import System.Taffybar.WindowIcon (pixBufFromColor) -import Text.Printf -import Text.Read hiding (lift) -import Data.Int (Int32) -setClassAndBoundingBoxes :: MonadIO m => Data.Text.Text -> Gtk.Widget -> m Gtk.Widget -setClassAndBoundingBoxes klass = buildContentsBox >=> flip widgetSetClassGI klass +-- | Wrap the widget in a "TaffyBox" (via 'buildContentsBox') and add a CSS class. +decorateWithClassAndBox :: MonadIO m => Text -> Gtk.Widget -> m Gtk.Widget +decorateWithClassAndBox klass widget = do + boxed <- buildContentsBox widget + widgetSetClassGI boxed klass -deocrateWithSetClassAndBoxes :: MonadIO m => Data.Text.Text -> m Gtk.Widget -> m Gtk.Widget -deocrateWithSetClassAndBoxes klass builder = builder >>= setClassAndBoundingBoxes klass +decorateWithClassAndBoxM :: MonadIO m => Text -> m Gtk.Widget -> m Gtk.Widget +decorateWithClassAndBoxM klass builder = + builder >>= decorateWithClassAndBox klass -mkRGBA (r, g, b, a) = (r/256, g/256, b/256, a/256) -blue = mkRGBA (42, 99, 140, 256) -yellow1 = mkRGBA (242, 163, 54, 256) -yellow2 = mkRGBA (254, 204, 83, 256) -yellow3 = mkRGBA (227, 134, 18, 256) -red = mkRGBA (210, 77, 37, 256) +-- ** X11 Workspaces -myGraphConfig = - defaultGraphConfig - { graphPadding = 0 - , graphBorderWidth = 0 - , graphWidth = 75 - , graphBackgroundColor = (0.0, 0.0, 0.0, 0.0) - } +x11FullWorkspaceNames :: X11Property [(WorkspaceId, String)] +x11FullWorkspaceNames = + go <$> readAsListOfString Nothing "_NET_DESKTOP_FULL_NAMES" + where + go = zip [WorkspaceId i | i <- [0 ..]] -netCfg = myGraphConfig - { graphDataColors = [yellow1, yellow2] - , graphLabel = Just "net" - } - -memCfg = myGraphConfig - { graphDataColors = [(0.129, 0.588, 0.953, 1)] - , graphLabel = Just "mem" - } - -cpuCfg = myGraphConfig - { graphDataColors = [red, (1, 0, 1, 0.5)] - , graphLabel = Just "cpu" - } - -memCallback :: IO [Double] -memCallback = do - mi <- parseMeminfo - return [memoryUsedRatio mi] - -cpuCallback = do - (_, systemLoad, totalLoad) <- cpuLoad - return [totalLoad, systemLoad] - -getFullWorkspaceNames :: X11Property [(WorkspaceId, String)] -getFullWorkspaceNames = go <$> readAsListOfString Nothing "_NET_DESKTOP_FULL_NAMES" - where go = zip [WorkspaceId i | i <- [0..]] - -workspaceNamesLabelSetter workspace = +x11WorkspaceLabelSetter :: X11Workspaces.Workspace -> X11Workspaces.WorkspacesIO String +x11WorkspaceLabelSetter workspace = remapNSP . fromMaybe "" . lookup (X11Workspaces.workspaceIdx workspace) <$> - liftX11Def [] getFullWorkspaceNames - where remapNSP "NSP" = "S" - remapNSP n = n + liftX11Def [] x11FullWorkspaceNames + where + remapNSP "NSP" = "S" + remapNSP n = n -enableLogger logger level = do - logger <- getLogger logger +-- ** Logging + +enableLogger :: String -> Priority -> IO () +enableLogger loggerName level = do + logger <- getLogger loggerName saveGlobalLogger $ setLevel level logger -- Systemd --user's manager environment can be stale across logins (e.g. still @@ -149,48 +107,34 @@ detectBackendRobust = do when (isJust mHyprSig) $ unsetEnv "HYPRLAND_INSTANCE_SIGNATURE" when (mSessionType == Just "wayland") $ setEnv "XDG_SESSION_TYPE" "x11" - case () of - _ | waylandOk -> pure BackendWayland - | maybe False (not . null) mDisplay -> pure BackendX11 - | otherwise -> detectBackend + let x11Ok = maybe False (not . null) mDisplay + if waylandOk + then pure BackendWayland + else if x11Ok + then pure BackendX11 + else detectBackend -logDebug = do - global <- getLogger "" - saveGlobalLogger $ setLevel DEBUG global - logger3 <- getLogger "System.Taffybar" - saveGlobalLogger $ setLevel DEBUG logger3 - logger <- getLogger "System.Taffybar.Widget.Generic.AutoSizeImage" - saveGlobalLogger $ setLevel DEBUG logger - logger2 <- getLogger "StatusNotifier.Tray" - saveGlobalLogger $ setLevel DEBUG logger2 - -- workspacesLogger <- getLogger "System.Taffybar.Widget.Workspaces" - -- saveGlobalLogger $ setLevel WARNING workspacesLogger - -- logDebug - -- logM "What" WARNING "Why" - -- enableLogger "System.Taffybar.Widget.Util" DEBUG - -- enableLogger "System.Taffybar.Information.XDG.DesktopEntry" DEBUG - -- enableLogger "System.Taffybar.WindowIcon" DEBUG - -- enableLogger "System.Taffybar.Widget.Generic.PollingLabel" DEBUG +-- ** Hyprland Icon Finding -iconRemap :: [(Data.Text.Text, [Data.Text.Text])] +iconRemap :: [(Text, [Text])] iconRemap = [ ("spotify", ["spotify-client", "spotify"]) ] -iconRemapMap :: M.Map Data.Text.Text [Data.Text.Text] +iconRemapMap :: M.Map Text [Text] iconRemapMap = - M.fromList [ (Data.Text.toLower k, v) | (k, v) <- iconRemap ] + M.fromList [ (T.toLower k, v) | (k, v) <- iconRemap ] -lookupIconRemap :: Data.Text.Text -> [Data.Text.Text] -lookupIconRemap name = fromMaybe [] $ M.lookup (Data.Text.toLower name) iconRemapMap +lookupIconRemap :: Text -> [Text] +lookupIconRemap name = fromMaybe [] $ M.lookup (T.toLower name) iconRemapMap -iconNameVariants :: Data.Text.Text -> [Data.Text.Text] +iconNameVariants :: Text -> [Text] iconNameVariants raw = - let lower = Data.Text.toLower raw - stripped = fromMaybe lower (Data.Text.stripSuffix ".desktop" lower) + let lower = T.toLower raw + stripped = fromMaybe lower (T.stripSuffix ".desktop" lower) suffixes = ["-gtk", "-client", "-desktop"] stripSuffixes name = - let variants = mapMaybe (`Data.Text.stripSuffix` name) suffixes + let variants = mapMaybe (`T.stripSuffix` name) suffixes in nub $ variants ++ [name] baseNames = stripSuffixes stripped ++ [raw] toDash c @@ -201,13 +145,13 @@ iconNameVariants raw = | otherwise = c variantsFor name = let dotted = - case Data.Text.splitOn "." name of + case T.splitOn "." name of [] -> name xs -> last xs - dashed = Data.Text.map toDash name - dashedDotted = Data.Text.map toDash dotted - underscored = Data.Text.map toUnderscore name - underscoredDotted = Data.Text.map toUnderscore dotted + dashed = T.map toDash name + dashedDotted = T.map toDash dotted + underscored = T.map toUnderscore name + underscoredDotted = T.map toUnderscore dotted in [dotted, dashed, dashedDotted, underscored, underscoredDotted, name] in nub $ concatMap variantsFor baseNames @@ -215,12 +159,12 @@ iconNameVariants raw = -- usually not something we want visible in the workspace widget. isSpecialHyprWorkspace :: Hyprland.HyprlandWorkspace -> Bool isSpecialHyprWorkspace ws = - let name = Data.Text.toLower $ Data.Text.pack $ Hyprland.workspaceName ws - in Data.Text.isPrefixOf "special" name || Hyprland.workspaceIdx ws < 0 + let name = T.toLower $ T.pack $ Hyprland.workspaceName ws + in T.isPrefixOf "special" name || Hyprland.workspaceIdx ws < 0 -hyprlandIconCandidates :: Hyprland.HyprlandWindow -> [Data.Text.Text] +hyprlandIconCandidates :: Hyprland.HyprlandWindow -> [Text] hyprlandIconCandidates windowData = - let baseNames = map Data.Text.pack $ catMaybes + let baseNames = map T.pack $ catMaybes [ Hyprland.windowClass windowData , Hyprland.windowInitialClass windowData ] @@ -229,17 +173,18 @@ hyprlandIconCandidates windowData = baseExpanded = concatMap iconNameVariants baseNames in nub (remappedExpanded ++ baseExpanded) -isPathCandidate :: Data.Text.Text -> Bool +isPathCandidate :: Text -> Bool isPathCandidate name = - Data.Text.isInfixOf "/" name || - any (`Data.Text.isSuffixOf` name) [".png", ".svg", ".xpm"] + T.isInfixOf "/" name || + any (`T.isSuffixOf` name) [".png", ".svg", ".xpm"] +hyprlandIconFromCandidate :: Int32 -> Text -> TaffyIO (Maybe Gdk.Pixbuf) hyprlandIconFromCandidate size name | isPathCandidate name = - liftIO $ getPixbufFromFilePath (Data.Text.unpack name) + liftIO $ getPixbufFromFilePath (T.unpack name) | otherwise = maybeTCombine - (Hyprland.getWindowIconFromDesktopEntryByAppId size (Data.Text.unpack name)) + (Hyprland.getWindowIconFromDesktopEntryByAppId size (T.unpack name)) (liftIO $ loadPixbufByName size name) hyprlandManualIconGetter :: Hyprland.HyprlandWindowIconPixbufGetter @@ -274,124 +219,210 @@ hyprlandFallbackIcon :: Hyprland.HyprlandWindowIconPixbufGetter hyprlandFallbackIcon size _ = fallbackIconPixbuf size +-- ** Host Overrides + +defaultCssFiles :: [FilePath] +defaultCssFiles = ["palette.css", "taffybar.css"] + +cssFilesByHostname :: [(String, [FilePath])] cssFilesByHostname = - [ ("uber-loaner", ["palette.css", "uber-loaner.css"]) - , ("imalison-home", ["palette.css", "taffybar.css"]) - , ("ivanm-dfinity-razer", ["palette.css", "taffybar.css"]) + [ ("imalison-home", ["palette.css", "taffybar.css"]) , ("ryzen-shine", ["palette.css", "taffybar.css"]) , ("stevie-nixos", ["palette.css", "taffybar.css"]) ] +laptopHosts :: [String] +laptopHosts = + [ "adell" + , "stevie-nixos" + , "strixi-minaj" + , "jay-lenovo" + ] + +cssFilesForHost :: String -> [FilePath] +cssFilesForHost hostName = + fromMaybe defaultCssFiles $ lookup hostName cssFilesByHostname + +-- ** Widgets + +audioWidget :: TaffyIO Gtk.Widget +audioWidget = + decorateWithClassAndBoxM "audio" PulseAudio.pulseAudioLabelNew + +networkWidget :: TaffyIO Gtk.Widget +networkWidget = + decorateWithClassAndBoxM "network" NetworkManager.networkManagerWifiLabelNew + +layoutWidget :: TaffyIO Gtk.Widget +layoutWidget = + decorateWithClassAndBoxM "layout" (layoutNew defaultLayoutConfig) + +windowsWidget :: TaffyIO Gtk.Widget +windowsWidget = + decorateWithClassAndBoxM "windows" (windowsNew defaultWindowsConfig) + +x11WorkspacesWidget :: TaffyIO Gtk.Widget +x11WorkspacesWidget = + flip widgetSetClassGI "workspaces" =<< + X11Workspaces.workspacesNew + X11Workspaces.defaultWorkspacesConfig + { X11Workspaces.minIcons = 1 + , X11Workspaces.getWindowIconPixbuf = + X11Workspaces.scaledWindowIconPixbufGetter $ + X11Workspaces.getWindowIconPixbufFromChrome <|||> + X11Workspaces.unscaledDefaultGetWindowIconPixbuf <|||> + (\size _ -> fallbackIconPixbuf size) + , X11Workspaces.widgetGap = 0 + , X11Workspaces.showWorkspaceFn = X11Workspaces.hideEmpty + , X11Workspaces.updateRateLimitMicroseconds = 100000 + , X11Workspaces.labelSetter = x11WorkspaceLabelSetter + , X11Workspaces.widgetBuilder = X11Workspaces.buildLabelOverlayController + } + +-- | Like 'buildWorkspaceIconLabelOverlay' but lets you choose the corner. +buildAlignedOverlay :: + Gtk.Align -> Gtk.Align -> Gtk.Widget -> Gtk.Widget -> TaffyIO Gtk.Widget +buildAlignedOverlay halign valign iconsWidget labelWidget = liftIO $ do + base <- buildContentsBox iconsWidget + ebox <- Gtk.eventBoxNew + _ <- widgetSetClassGI ebox "overlay-box" + Gtk.widgetSetHalign ebox halign + Gtk.widgetSetValign ebox valign + Gtk.containerAdd ebox labelWidget + overlayLabel <- Gtk.toWidget ebox + overlay <- Gtk.overlayNew + baseW <- Gtk.toWidget base + Gtk.containerAdd overlay baseW + Gtk.overlayAddOverlay overlay overlayLabel + Gtk.overlaySetOverlayPassThrough overlay overlayLabel True + Gtk.toWidget overlay + +hyprlandWorkspacesWidget :: TaffyIO Gtk.Widget +hyprlandWorkspacesWidget = + flip widgetSetClassGI "workspaces" =<< + Hyprland.hyprlandWorkspacesNew + Hyprland.defaultHyprlandWorkspacesConfig + { Hyprland.widgetGap = 0 + , Hyprland.minIcons = 1 + , Hyprland.widgetBuilder = buildAlignedOverlay Gtk.AlignStart Gtk.AlignEnd + -- Don't show Hyprland "special:*" workspaces. + , Hyprland.showWorkspaceFn = + \ws -> + Hyprland.workspaceState ws /= X11Workspaces.Empty && + not (isSpecialHyprWorkspace ws) + , Hyprland.getWindowIconPixbuf = + hyprlandManualIconGetter <|||> + Hyprland.defaultHyprlandGetWindowIconPixbuf <|||> + hyprlandFallbackIcon + } + +clockWidget :: TaffyIO Gtk.Widget +clockWidget = + decorateWithClassAndBoxM + "clock" + ( textClockNewWith + defaultClockConfig + { clockUpdateStrategy = RoundedTargetInterval 60 0.0 + , clockFormatString = "%a %b %_d, 🕑%I:%M %p" + } + ) + +mprisWidget :: TaffyIO Gtk.Widget +mprisWidget = + mpris2NewWithConfig + MPRIS2Config + { mprisWidgetWrapper = decorateWithClassAndBox "mpris" + , updatePlayerWidget = + simplePlayerWidget + defaultPlayerConfig + { setNowPlayingLabel = playingText 20 20 + } + } + +batteryIconWidget :: TaffyIO Gtk.Widget +batteryIconWidget = + decorateWithClassAndBoxM "battery-icon" batteryIconNew + +batteryTextWidget :: TaffyIO Gtk.Widget +batteryTextWidget = + decorateWithClassAndBoxM "battery-text" (textBatteryNew "$percentage$%") + +batteryWidgets :: [TaffyIO Gtk.Widget] +batteryWidgets = [batteryIconWidget, batteryTextWidget] + +-- Note: end widgets are packed with Gtk.boxPackEnd; list order is right-to-left. +batteryEndWidgets :: [TaffyIO Gtk.Widget] +batteryEndWidgets = reverse batteryWidgets + +backlightWidget :: TaffyIO Gtk.Widget +backlightWidget = + decorateWithClassAndBoxM + "backlight" + ( backlightLabelNewChanWith + defaultBacklightWidgetConfig + { backlightFormat = "☀ $percent$%" + , backlightUnknownFormat = "☀ n/a" + , backlightTooltipFormat = + Just "Device: $device$\nBrightness: $brightness$/$max$ ($percent$%)" + } + ) + +sniTrayWidget :: TaffyIO Gtk.Widget +sniTrayWidget = + decorateWithClassAndBoxM + "sni-tray" + sniTrayNew + +-- ** Layout + +startWidgetsForBackend :: Backend -> [TaffyIO Gtk.Widget] +startWidgetsForBackend backend = + case backend of + BackendX11 -> [x11WorkspacesWidget, layoutWidget, windowsWidget] + -- These Wayland widgets are Hyprland-specific. + BackendWayland -> [hyprlandWorkspacesWidget] + +endWidgetsForHost :: String -> Backend -> [TaffyIO Gtk.Widget] +endWidgetsForHost hostName backend = + let tray = sniTrayWidget + baseEndWidgets = [tray, audioWidget, networkWidget, mprisWidget] + -- Keep battery widgets visually *after* the tray (i.e. further to the right). + laptopEndWidgets = + batteryEndWidgets ++ + [ tray + , audioWidget + , backlightWidget + , networkWidget + , mprisWidget + ] + in if hostName `elem` laptopHosts + then laptopEndWidgets + else baseEndWidgets + +mkSimpleTaffyConfig :: String -> Backend -> [FilePath] -> SimpleTaffyConfig +mkSimpleTaffyConfig hostName backend cssFiles = + defaultSimpleTaffyConfig + { startWidgets = startWidgetsForBackend backend + , endWidgets = endWidgetsForHost hostName backend + , barPosition = Top + , widgetSpacing = 0 + , barPadding = 4 + , barHeight = ScreenRatio $ 1 / 36 + , cssPaths = cssFiles + , centerWidgets = [clockWidget] + } + +-- ** Entry Point + +main :: IO () main = do enableLogger "Graphics.UI.GIGtkStrut" DEBUG hostName <- getHostName backend <- detectBackendRobust - let relativeFiles = fromMaybe ["palette.css", "taffybar.css"] $ lookup hostName cssFilesByHostname - cssFiles <- mapM (getUserConfigFile "taffybar") relativeFiles + cssFiles <- mapM (getUserConfigFile "taffybar") (cssFilesForHost hostName) - let myCPU = - ( deocrateWithSetClassAndBoxes "cpu" $ - pollingGraphNew cpuCfg 5 cpuCallback - ) :: TaffyIO Gtk.Widget - myMem = - ( deocrateWithSetClassAndBoxes "mem" $ - pollingGraphNew memCfg 5 memCallback - ) :: TaffyIO Gtk.Widget - myNet = - ( deocrateWithSetClassAndBoxes "net" $ - networkGraphNew netCfg Nothing - ) :: TaffyIO Gtk.Widget - myAudio = deocrateWithSetClassAndBoxes "audio" $ - PulseAudio.pulseAudioLabelNew - myNetwork = deocrateWithSetClassAndBoxes "network" $ - NetworkManager.networkManagerWifiLabelNew - myLayout = deocrateWithSetClassAndBoxes "layout" $ - layoutNew defaultLayoutConfig - myWindows = deocrateWithSetClassAndBoxes "windows" $ - windowsNew defaultWindowsConfig - myWorkspaces = - flip widgetSetClassGI "workspaces" =<< - X11Workspaces.workspacesNew X11Workspaces.defaultWorkspacesConfig - { X11Workspaces.minIcons = 1 - , X11Workspaces.getWindowIconPixbuf = - X11Workspaces.scaledWindowIconPixbufGetter $ - X11Workspaces.getWindowIconPixbufFromChrome <|||> - X11Workspaces.unscaledDefaultGetWindowIconPixbuf <|||> - (\size _ -> fallbackIconPixbuf size) - , X11Workspaces.widgetGap = 0 - , X11Workspaces.showWorkspaceFn = X11Workspaces.hideEmpty - , X11Workspaces.updateRateLimitMicroseconds = 100000 - , X11Workspaces.labelSetter = workspaceNamesLabelSetter - , X11Workspaces.widgetBuilder = X11Workspaces.buildLabelOverlayController - } - myHyprWorkspaces = - flip widgetSetClassGI "workspaces" =<< - Hyprland.hyprlandWorkspacesNew Hyprland.defaultHyprlandWorkspacesConfig - { Hyprland.widgetGap = 0 - , Hyprland.minIcons = 1 - -- Don't show Hyprland "special:*" workspaces. - , Hyprland.showWorkspaceFn = - (\ws -> Hyprland.workspaceState ws /= X11Workspaces.Empty && - not (isSpecialHyprWorkspace ws)) - , Hyprland.getWindowIconPixbuf = - hyprlandManualIconGetter <|||> - Hyprland.defaultHyprlandGetWindowIconPixbuf <|||> - hyprlandFallbackIcon - } - myClock = deocrateWithSetClassAndBoxes "clock" $ - textClockNewWith - defaultClockConfig - { clockUpdateStrategy = RoundedTargetInterval 60 0.0 - , clockFormatString = "%a %b %_d, 🕑%I:%M %p" - } - myMpris = - mpris2NewWithConfig - MPRIS2Config - { mprisWidgetWrapper = deocrateWithSetClassAndBoxes "mpris" . return - , updatePlayerWidget = - simplePlayerWidget - defaultPlayerConfig - { setNowPlayingLabel = playingText 20 20 - } - } - myBatteryIcon = deocrateWithSetClassAndBoxes "battery-icon" batteryIconNew - myBatteryText = - deocrateWithSetClassAndBoxes "battery-text" $ textBatteryNew "$percentage$%" - batteryWidgets = [ myBatteryIcon, myBatteryText ] - mySNITray = deocrateWithSetClassAndBoxes "sni-tray" $ - case backend of - BackendWayland -> sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt - BackendX11 -> sniTrayNew - baseEndWidgets = [ myAudio, myNetwork, myMpris, mySNITray ] - laptopEndWidgets = batteryWidgets ++ baseEndWidgets - x11StartWidgets = [ myWorkspaces, myLayout, myWindows ] - hyprlandStartWidgets = [ myHyprWorkspaces ] - startWidgetsForBackend = - case backend of - BackendX11 -> x11StartWidgets - -- These Wayland widgets are Hyprland-specific. - BackendWayland -> hyprlandStartWidgets - baseConfig = - defaultSimpleTaffyConfig - { startWidgets = startWidgetsForBackend - , endWidgets = baseEndWidgets - , barPosition = Top - , widgetSpacing = 0 - , barPadding = 4 - , barHeight = ScreenRatio $ 1 / 36 - , cssPaths = cssFiles - , centerWidgets = [ myClock ] - } - hostOverrides = - [ ("uber-loaner", \cfg -> cfg { endWidgets = laptopEndWidgets }) - , ("adell", \cfg -> cfg { endWidgets = laptopEndWidgets }) - , ("stevie-nixos", \cfg -> cfg { endWidgets = laptopEndWidgets }) - , ("strixi-minaj", \cfg -> cfg { endWidgets = laptopEndWidgets }) - , ("jay-lenovo", \cfg -> cfg { endWidgets = laptopEndWidgets }) - ] - simpleTaffyConfig = - fromMaybe baseConfig $ ($ baseConfig) <$> lookup hostName hostOverrides + let simpleTaffyConfig = mkSimpleTaffyConfig hostName backend cssFiles startTaffybar $ withLogServer $ withToggleServer $ diff --git a/dotfiles/config/taffybar/uber-loaner.css b/dotfiles/config/taffybar/uber-loaner.css deleted file mode 100644 index 1b97dec2..00000000 --- a/dotfiles/config/taffybar/uber-loaner.css +++ /dev/null @@ -1,203 +0,0 @@ -@define-color transparent rgba(0.0, 0.0, 0.0, 0.0); -@define-color white #FFFFFF; -@define-color black #000000; -@define-color taffy-blue #0c7cd5; - -@define-color active-window-color @white; -@define-color urgent-window-color @taffy-blue; -@define-color font-color @white; -@define-color menu-background-color @white; -@define-color menu-font-color @black; - -/* Top level styling */ - -.taffy-window * { - font-family: "Noto Sans", sans-serif; - font-size: 10pt; - color: @font-color; -} - -.taffy-box { - border-color: @white; - border-style: solid; - border-radius: 0px; -} - -.inner-pad { - padding: 1px; -} - -.contents { - padding: 1px; - transition: background-color .5s; - border-radius: 6px; -} - -/* Workspaces styling */ - -.workspace-label { - padding-right: 3px; - padding-left: 2px; - font-size: 10pt; -} - -.active .contents { - background-color: rgba(0.0, 0.0, 0.0, 0.2); -} - -.visible .contents { - background-color: rgba(0.0, 0.0, 0.0, 0.2); -} - -.window-icon-container { - transition: opacity .5s, box-shadow .5s; - opacity: 1; - border-radius: 5px; - transition: background-color 1s; -} - -/* This gives space for the box-shadow (they look like underlines) that follow. - This will actually affect all widgets, (not just the workspace icons), but - that is what we want since we want the icons to look the same. */ -.auto-size-image, .sni-tray { - padding: 1px; -} - -.window-icon-container.active { - background-color: rgba(255.0, 255.0, 255.0, 0.3); -} - -.window-icon-container.urgent { -} - -.window-icon-container.inactive .window-icon { - padding: 0px; -} - -.window-icon-container.minimized .window-icon { - opacity: .3; -} - -.window-icon { - opacity: 1; - transition: opacity .5s; -} - -/* Button styling */ - -.taffy-window button { - all: initial; - background-color: @transparent; - border-width: 0px; - border-radius: 0px; -} - -.taffy-window button:checked, .taffy-window button:hover .Contents:hover { - box-shadow: inset 0 -3px @taffy-blue; -} - -/* Menu styling */ - -/* The ".taffy-window" prefixed selectors are needed because if they aren't present, - the top level .Taffybar selector takes precedence */ -.taffy-window menuitem *, menuitem * { - color: @menu-font-color; -} - -/* Force an opaque background for menus, regardless of the system GTK theme. */ -.taffy-window menu, menu, -.taffy-window menu.background, menu.background, -.taffy-window .menu, .menu, -.taffy-window .menu.background, .menu.background, -GtkMenu, GtkMenu.background { - background-color: @menu-background-color; - background-image: none; - border: 1px solid rgba(0, 0, 0, 0.20); - padding: 4px 0px; -} - -.taffy-window menu, menu { - background-color: @menu-background-color; - background-image: none; -} - -/* Some themes apply transparency to the menu's toplevel popup window. */ -window.popup, window.popup.background, -window.menu, window.menu.background, -.menu, .menu.background { - background-color: @menu-background-color; - background-image: none; -} - -window.popup *, window.menu * { - background-color: @menu-background-color; - background-image: none; -} - -window.popup decoration, window.menu decoration { - background-color: @menu-background-color; - background-image: none; -} - -.taffy-window menuitem, menuitem { - background-color: @menu-background-color; -} - -menu menuitem, GtkMenu menuitem, .menu menuitem { - background-color: @menu-background-color; -} - -.taffy-window menuitem:hover, menuitem:hover { - background-color: @taffy-blue; -} - -menu menuitem:hover, GtkMenu menuitem:hover, .menu menuitem:hover { - background-color: @taffy-blue; -} - -window.popup menuitem:hover *, window.menu menuitem:hover * { - background-color: @taffy-blue; -} - -menu *, GtkMenu *, .menu * { - background-color: @menu-background-color; - background-image: none; -} - -menu menuitem:hover *, GtkMenu menuitem:hover *, .menu menuitem:hover * { - background-color: @taffy-blue; -} - -.taffy-window menuitem:hover > label, menuitem:hover > label { - color: @menu-font-color; -} - -/* Some menus (notably a few StatusNotifierItem menus) are rendered as popovers - containing modelbuttons instead of menuitems. */ -popover, popover.background, popover > contents { - background-color: @menu-background-color; - background-image: none; - border: 1px solid rgba(0, 0, 0, 0.20); -} - -popover modelbutton, popover modelbutton * { - background-color: @menu-background-color; - color: @menu-font-color; -} - -popover modelbutton:hover { - background-color: @taffy-blue; -} - -popover modelbutton:hover > label { - color: @menu-font-color; -} - -popover * { - background-color: @menu-background-color; - background-image: none; -} - -popover modelbutton:hover * { - background-color: @taffy-blue; -} diff --git a/dotfiles/synergy.conf b/dotfiles/synergy.conf index 1eb184d2..2b128117 100644 --- a/dotfiles/synergy.conf +++ b/dotfiles/synergy.conf @@ -15,11 +15,8 @@ section: aliases imalison-desktop imalison-home justin-bieber-creek controlling: - uber-loaner imalison-mpb-arch - imalison-uber-loaner Livien-MacbookAir - kat-uber-loaner Dean-PC imalison-mbp strixi-minaj