packages feed

taffybar 0.4.5 → 0.4.6

raw patch · 10 files changed

+127/−74 lines, 10 filesdep ~HStringTemplatedep ~dyredep ~gtkPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: HStringTemplate, dyre, gtk, time, xdg-basedir

API changes (from Hackage documentation)

+ System.Information.EWMHDesktopInfo: WSIdx :: Int -> WorkspaceIdx
+ System.Information.EWMHDesktopInfo: instance GHC.Classes.Eq System.Information.EWMHDesktopInfo.WorkspaceIdx
+ System.Information.EWMHDesktopInfo: instance GHC.Classes.Ord System.Information.EWMHDesktopInfo.WorkspaceIdx
+ System.Information.EWMHDesktopInfo: instance GHC.Read.Read System.Information.EWMHDesktopInfo.WorkspaceIdx
+ System.Information.EWMHDesktopInfo: instance GHC.Show.Show System.Information.EWMHDesktopInfo.WorkspaceIdx
+ System.Information.EWMHDesktopInfo: newtype WorkspaceIdx
+ System.Information.EWMHDesktopInfo: switchOneWorkspace :: Bool -> Int -> X11Property ()
- System.Information.EWMHDesktopInfo: getCurrentWorkspace :: X11Property Int
+ System.Information.EWMHDesktopInfo: getCurrentWorkspace :: X11Property WorkspaceIdx
- System.Information.EWMHDesktopInfo: getVisibleWorkspaces :: X11Property [Int]
+ System.Information.EWMHDesktopInfo: getVisibleWorkspaces :: X11Property [WorkspaceIdx]
- System.Information.EWMHDesktopInfo: getWorkspace :: X11Window -> X11Property Int
+ System.Information.EWMHDesktopInfo: getWorkspace :: X11Window -> X11Property WorkspaceIdx
- System.Information.EWMHDesktopInfo: getWorkspaceNames :: X11Property [String]
+ System.Information.EWMHDesktopInfo: getWorkspaceNames :: X11Property [(WorkspaceIdx, String)]
- System.Information.EWMHDesktopInfo: switchToWorkspace :: Int -> X11Property ()
+ System.Information.EWMHDesktopInfo: switchToWorkspace :: WorkspaceIdx -> X11Property ()
- System.Information.EWMHDesktopInfo: type X11WindowHandle = ((Int, String, String), X11Window)
+ System.Information.EWMHDesktopInfo: type X11WindowHandle = ((WorkspaceIdx, String, String), X11Window)

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+# 0.4.6++ * Fix a longstanding bug in loading .rc files (Peder Stray)+ * Add support for scrolling in the workspace switcher (Saksham Sharma)+ * Improve default formatting of empty workspaces in the pager (Saksham Sharma)+ * Relax gtk version bounds+ # 0.4.5   * GHC 7.10 compat
src/System/Information/EWMHDesktopInfo.hs view
@@ -22,12 +22,14 @@ module System.Information.EWMHDesktopInfo   ( X11Window      -- re-exported from X11DesktopInfo   , X11WindowHandle+  , WorkspaceIdx(..)   , withDefaultCtx -- re-exported from X11DesktopInfo   , isWindowUrgent -- re-exported from X11DesktopInfo   , getCurrentWorkspace   , getVisibleWorkspaces   , getWorkspaceNames   , switchToWorkspace+  , switchOneWorkspace   , getWindowTitle   , getWindowClass   , getActiveWindowTitle@@ -37,44 +39,67 @@   , focusWindow   ) where -import Data.List (elemIndex)+import Control.Applicative ((<$>))+import Data.Tuple (swap) import Data.Maybe (listToMaybe, mapMaybe) import System.Information.X11DesktopInfo  -- | Convenience alias for a pair of the form (props, window), where props is a -- tuple of the form (workspace index, window title, window class), and window -- is the internal ID of an open window.-type X11WindowHandle = ((Int, String, String), X11Window)+type X11WindowHandle = ((WorkspaceIdx, String, String), X11Window) +newtype WorkspaceIdx = WSIdx Int+                     deriving (Show, Read, Ord, Eq)+ noFocus :: String noFocus = "..."  -- | Retrieve the index of the current workspace in the desktop, -- starting from 0.-getCurrentWorkspace :: X11Property Int-getCurrentWorkspace = readAsInt Nothing "_NET_CURRENT_DESKTOP"+getCurrentWorkspace :: X11Property WorkspaceIdx+getCurrentWorkspace = WSIdx <$> readAsInt Nothing "_NET_CURRENT_DESKTOP"  -- | Retrieve the indexes of all currently visible workspaces -- with the active workspace at the head of the list.-getVisibleWorkspaces :: X11Property [Int]+getVisibleWorkspaces :: X11Property [WorkspaceIdx] getVisibleWorkspaces = do   vis <- getVisibleTags-  allNames <- getWorkspaceNames+  allNames <- map swap <$> getWorkspaceNames   cur <- getCurrentWorkspace-  return $ cur : mapMaybe (`elemIndex` allNames) vis+  return $ cur : mapMaybe (flip lookup allNames) vis  -- | Return a list with the names of all the workspaces currently -- available.-getWorkspaceNames :: X11Property [String]-getWorkspaceNames = readAsListOfString Nothing "_NET_DESKTOP_NAMES"+getWorkspaceNames :: X11Property [(WorkspaceIdx, String)]+getWorkspaceNames = go <$> readAsListOfString Nothing "_NET_DESKTOP_NAMES"+  where go = zip [WSIdx i | i <- [0..]]  -- | Ask the window manager to switch to the workspace with the given -- index, starting from 0.-switchToWorkspace :: Int -> X11Property ()-switchToWorkspace idx = do+switchToWorkspace :: WorkspaceIdx -> X11Property ()+switchToWorkspace (WSIdx idx) = do   cmd <- getAtom "_NET_CURRENT_DESKTOP"   sendCommandEvent cmd (fromIntegral idx) +-- | Move one workspace up or down from the current workspace+switchOneWorkspace :: Bool -> Int -> X11Property ()+switchOneWorkspace dir end = do+  cur <- getCurrentWorkspace+  switchToWorkspace $ if dir then getPrev cur end else getNext cur end++-- | Check for corner case and switch one workspace up+getPrev :: WorkspaceIdx -> Int -> WorkspaceIdx+getPrev (WSIdx idx) end+  | idx > 0 = WSIdx $ idx-1+  | otherwise = WSIdx end++-- | Check for corner case and switch one workspace down+getNext :: WorkspaceIdx -> Int -> WorkspaceIdx+getNext (WSIdx idx) end+  | idx < end = WSIdx $ idx+1+  | otherwise = WSIdx 0+ -- | Get the title of the given X11 window. getWindowTitle :: X11Window -> X11Property String getWindowTitle window = do@@ -114,8 +139,8 @@  -- | Return the index (starting from 0) of the workspace on which the -- given window is being displayed.-getWorkspace :: X11Window -> X11Property Int-getWorkspace window = readAsInt (Just window) "_NET_WM_DESKTOP"+getWorkspace :: X11Window -> X11Property WorkspaceIdx+getWorkspace window = WSIdx <$> readAsInt (Just window) "_NET_WM_DESKTOP"  -- | Ask the window manager to give focus to the given window. focusWindow :: X11Window -> X11Property ()
src/System/Taffybar.hs view
@@ -225,7 +225,7 @@   nmonitors <- screenGetNMonitors screen   allMonitorSizes <- mapM (screenGetMonitorGeometry screen) [0 .. (nmonitors - 1)] -  when (monitorNumber cfg < nmonitors) $ do+  when (monitorNumber cfg >= nmonitors) $ do     IO.hPutStrLn IO.stderr $ printf "Monitor %d is not available in the selected screen" (monitorNumber cfg)    let monitorSize = fromMaybe (allMonitorSizes !! 0) $ do@@ -261,15 +261,14 @@  taffybarMain :: TaffybarConfig -> IO () taffybarMain cfg = do-  -- Override the default GTK theme path settings.  This causes the-  -- bar (by design) to ignore the real GTK theme and just use the-  -- provided minimal theme to set the background and text colors.-  -- Users can override this default.-  defaultGtkConfig <- getDefaultConfigFile "taffybar.rc"-  userGtkConfig <- getUserConfigFile "taffybar" "taffybar.rc"-  rcSetDefaultFiles [ defaultGtkConfig, userGtkConfig ]    _ <- initGUI++  -- Load default and user gtk resources+  defaultGtkConfig <- getDefaultConfigFile "taffybar.rc"+  userGtkConfig <- getUserConfigFile "taffybar" "taffybar.rc"+  rcParse defaultGtkConfig+  rcParse userGtkConfig    Just disp <- displayGetDefault   nscreens <- displayGetNScreens disp
src/System/Taffybar/FreedesktopNotifications.hs view
@@ -113,9 +113,8 @@ -- | Apply the user's formatter and truncate the result with the -- specified maxlen. formatMessage :: NotifyState -> Notification -> String-formatMessage s = take maxlen . fmt+formatMessage s = fmt   where-    maxlen = notificationMaxLength $ noteConfig s     fmt = notificationFormatter $ noteConfig s  -- | The notificationDaemon thread looks at the notification queue.
src/System/Taffybar/Pager.hs view
@@ -82,7 +82,7 @@   , activeLayout     = escape   , activeWorkspace  = colorize "yellow" "" . wrap "[" "]" . escape   , hiddenWorkspace  = escape-  , emptyWorkspace   = escape+  , emptyWorkspace   = const ""   , visibleWorkspace = wrap "(" ")" . escape   , urgentWorkspace  = colorize "red" "yellow" . escape   , widgetSep        = " : "
src/System/Taffybar/WindowSwitcher.hs view
@@ -26,6 +26,7 @@ ) where  import Control.Monad (forM_)+import qualified Data.Map as M import Control.Monad.IO.Class ( liftIO ) import qualified Graphics.UI.Gtk as Gtk import Graphics.X11.Xlib.Extras (Event)@@ -118,7 +119,7 @@   if null handles then return () else do     wsNames <- getWorkspaceNames     forM_ handles $ \handle -> liftIO $ do-      item <- Gtk.menuItemNewWithLabel (formatEntry wsNames handle)+      item <- Gtk.menuItemNewWithLabel (formatEntry (M.fromList wsNames) handle)       _ <- Gtk.on item Gtk.buttonPressEvent $ liftIO $ do         withDefaultCtx (focusWindow $ snd handle)         return True@@ -132,13 +133,13 @@  -- | Build the name to display in the list of windows by prepending the name -- of the workspace it is currently in to the name of the window itself-formatEntry :: [String] -- ^ List of names of all available workspaces+formatEntry :: M.Map WorkspaceIdx String -- ^ List of names of all available workspaces             -> X11WindowHandle -- ^ Handle of the window to name             -> String formatEntry wsNames ((ws, wtitle, _), _) = wsName ++ ": " ++ (nonEmpty wtitle)-  where wsName = if 0 <= ws && ws < length wsNames-                 then wsNames !! ws-                 else "WS#" ++ show ws+  where+    wsName = M.findWithDefault ("WS#"++show wsN) ws wsNames+    WSIdx wsN = ws  -- | Return the given String if it's not empty, otherwise return "(nameless window)" nonEmpty :: String -> String
src/System/Taffybar/WorkspaceSwitcher.hs view
@@ -26,6 +26,7 @@   wspaceSwitcherNew ) where +import Control.Applicative import qualified Control.Concurrent.MVar as MV import Control.Monad import Control.Monad.IO.Class (MonadIO, liftIO)@@ -33,6 +34,8 @@ import qualified Graphics.UI.Gtk as Gtk import Graphics.X11.Xlib.Extras +import Prelude+ import System.Taffybar.Pager import System.Information.EWMHDesktopInfo @@ -91,17 +94,18 @@       redrawcb = redrawCallback pager deskRef switcher       urgentcb = urgentCallback cfg deskRef   subscribe pager activecb "_NET_CURRENT_DESKTOP"+  subscribe pager redrawcb "_NET_DESKTOP_NAMES"   subscribe pager redrawcb "_NET_NUMBER_OF_DESKTOPS"   subscribe pager urgentcb "WM_HINTS"    return $ Gtk.toWidget switcher  -- | List of indices of all available workspaces.-allWorkspaces :: Desktop -> [Int]-allWorkspaces desktop = [0 .. length desktop - 1]+allWorkspaces :: Desktop -> [WorkspaceIdx]+allWorkspaces desktop = map WSIdx [0 .. length desktop - 1]  -- | List of indices of all the workspaces that contain at least one window.-nonEmptyWorkspaces :: IO [Int]+nonEmptyWorkspaces :: IO [WorkspaceIdx] nonEmptyWorkspaces = withDefaultCtx $ mapM getWorkspace =<< getWindows  -- | Return a list of two-element tuples, one for every workspace,@@ -109,7 +113,7 @@ -- workspace and a String with its default (unmarked) representation. getDesktop :: Pager -> IO Desktop getDesktop pager = do-  names  <- withDefaultCtx getWorkspaceNames+  names  <- map snd <$> withDefaultCtx getWorkspaceNames   labels <- toLabels $ map (hiddenWorkspace $ config pager) names   return $ zipWith (\n l -> Workspace l n False) names labels @@ -143,9 +147,8 @@   curr <- withDefaultCtx getVisibleWorkspaces   desktop <- MV.readMVar deskRef   case curr of-    visible : _ | length desktop > visible -> do-      when (urgent (desktop !! visible)) $ do-        toggleUrgent deskRef visible False+    visible : _ | Just ws <- getWS desktop visible -> do+      when (urgent ws) $ toggleUrgent deskRef visible False       transition cfg desktop curr     _ -> return () @@ -188,33 +191,45 @@           Gtk.labelSetMarkup lbl markup           return lbl +-- | Get the workspace corresponding to the given 'WorkspaceIdx' on the given desktop+getWS :: Desktop -> WorkspaceIdx -> Maybe Workspace+getWS desktop (WSIdx idx)+  | length desktop > idx = Just (desktop !! idx)+  | otherwise            = Nothing+ -- | Build a new clickable event box containing the Label widget that -- corresponds to the given index, and add it to the given container. addButton :: Gtk.BoxClass self-          => self    -- ^ Graphical container.-          -> Desktop -- ^ List of all workspace Labels available.-          -> Int     -- ^ Index of the workspace to use.+          => self         -- ^ Graphical container.+          -> Desktop      -- ^ List of all workspace Labels available.+          -> WorkspaceIdx -- ^ Index of the workspace to use.           -> IO () addButton hbox desktop idx-  | length desktop > idx = do-    let index = desktop !! idx-        lbl = label index+  | Just ws <- getWS desktop idx = do+    let lbl = label ws     ebox <- Gtk.eventBoxNew-    Gtk.widgetSetName ebox $ name index+    Gtk.widgetSetName ebox $ name ws     Gtk.eventBoxSetVisibleWindow ebox False     _ <- Gtk.on ebox Gtk.buttonPressEvent $ switch idx+    _ <- Gtk.on ebox Gtk.scrollEvent $ do+      dir <- Gtk.eventScrollDirection+      case dir of+        Gtk.ScrollUp    -> switchOne True (length desktop - 1)+        Gtk.ScrollLeft  -> switchOne True (length desktop - 1)+        Gtk.ScrollDown  -> switchOne False (length desktop - 1)+        Gtk.ScrollRight -> switchOne False (length desktop - 1)     Gtk.containerAdd ebox lbl     Gtk.boxPackStart hbox ebox Gtk.PackNatural 0   | otherwise = return ()  -- | Re-mark all workspace labels.-transition :: PagerConfig -- ^ Configuration settings.-           -> Desktop     -- ^ All available Labels with their default values.-           -> [Int]       -- ^ Currently visible workspaces (first is active).+transition :: PagerConfig    -- ^ Configuration settings.+           -> Desktop        -- ^ All available Labels with their default values.+           -> [WorkspaceIdx] -- ^ Currently visible workspaces (first is active).            -> IO () transition cfg desktop wss = do-  nonEmpty <- fmap (filter (>=0)) nonEmptyWorkspaces-  let urgentWs = findIndices urgent desktop+  nonEmpty <- fmap (filter (>=WSIdx 0)) nonEmptyWorkspaces+  let urgentWs = map WSIdx $ findIndices urgent desktop       allWs    = (allWorkspaces desktop) \\ urgentWs       nonEmptyWs = nonEmpty \\ urgentWs   mapM_ (mark desktop $ hiddenWorkspace cfg) nonEmptyWs@@ -230,11 +245,10 @@ -- the given index. mark :: Desktop            -- ^ List of all available labels.      -> (String -> String) -- ^ Marking function.-     -> Int                -- ^ Index of the Label to modify.+     -> WorkspaceIdx       -- ^ Index of the Label to modify.      -> IO ()-mark desktop decorate idx-  | length desktop > idx = do-    let ws = desktop !! idx+mark desktop decorate wsIdx+  | Just ws <- getWS desktop wsIdx =     Gtk.postGUIAsync $ Gtk.labelSetMarkup (label ws) $ decorate' (name ws)   | otherwise = return ()   where decorate' = pad . decorate@@ -242,18 +256,24 @@               | otherwise = ' ' : m  -- | Switch to the workspace with the given index.-switch :: (MonadIO m) => Int -> m Bool+switch :: (MonadIO m) => WorkspaceIdx -> m Bool switch idx = do   liftIO $ withDefaultCtx (switchToWorkspace idx)   return True +-- | Switch to one workspace up or down given a boolean direction and the last workspace+switchOne :: (MonadIO m) => Bool -> Int -> m Bool+switchOne dir end = do+  liftIO $ withDefaultCtx (if dir then switchOneWorkspace dir end else switchOneWorkspace dir end)+  return True+ -- | Modify the Desktop inside the given IORef, so that the Workspace at the -- given index has its "urgent" flag set to the given value.-toggleUrgent :: MV.MVar Desktop -- ^ IORef to modify.-             -> Int           -- ^ Index of the Workspace to replace.+toggleUrgent :: MV.MVar Desktop -- ^ MVar to modify.+             -> WorkspaceIdx  -- ^ Index of the Workspace to replace.              -> Bool          -- ^ New value of the "urgent" flag.              -> IO ()-toggleUrgent deskRef idx isUrgent =+toggleUrgent deskRef (WSIdx idx) isUrgent =   MV.modifyMVar_ deskRef $ \desktop -> do     let ws = desktop !! idx     case length desktop > idx of
taffybar.cabal view
@@ -1,5 +1,5 @@ name: taffybar-version: 0.4.5+version: 0.4.6 synopsis: A desktop bar similar to xmobar, but with more GUI license: BSD3 license-file: LICENSE@@ -8,6 +8,7 @@ category: System build-type: Simple cabal-version: >=1.10+tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2 homepage: http://github.com/travitch/taffybar data-files: taffybar.rc extra-source-files: README.md,@@ -26,7 +27,7 @@ library   default-language: Haskell2010   build-depends: base > 3 && < 5,-                 time >= 1.4 && < 1.6,+                 time >= 1.4 && < 1.7,                  time-locale-compat >= 0.1 && < 0.2,                  old-locale,                  containers,@@ -36,13 +37,13 @@                  mtl >= 2,                  cairo,                  dbus >= 0.10.1 && < 1.0,-                 gtk >= 0.12.1 && < 0.14,-                 dyre >= 0.8.6,-                 HStringTemplate,+                 gtk >= 0.12.1 && < 0.15,+                 dyre >= 0.8.6 && < 0.9,+                 HStringTemplate >= 0.8 && < 0.9,                  gtk-traymanager >= 0.1.2 && < 0.2,                  xmonad-contrib,                  xmonad,-                 xdg-basedir,+                 xdg-basedir >= 0.2 && < 0.3,                  filepath,                  utf8-string,                  process,@@ -102,14 +103,12 @@   c-sources: src/gdk_property_change_wrapper.c    ghc-options: -Wall -funbox-strict-fields-  ghc-prof-options: -auto-all - executable taffybar   default-language: Haskell2010   build-depends: base > 3 && < 5,                  dyre >= 0.8.6,-                 gtk >= 0.12 && < 0.14,+                 gtk >= 0.12 && < 0.15,                  safe >= 0.3 && < 1,                  xdg-basedir,                  filepath@@ -118,7 +117,6 @@   pkgconfig-depends: gtk+-2.0   c-sources: src/gdk_property_change_wrapper.c   ghc-options: -Wall -rtsopts -threaded-  ghc-prof-options: -auto-all  source-repository head   type: git
taffybar.hs.example view
@@ -34,7 +34,7 @@       pager = taffyPagerNew defaultPagerConfig       note = notifyAreaNew defaultNotificationConfig       wea = weatherNew (defaultWeatherConfig "KMSN") 10-      mpris = mprisNew+      mpris = mprisNew defaultMPRISConfig       mem = pollingGraphNew memCfg 1 memCallback       cpu = pollingGraphNew cpuCfg 0.5 cpuCallback       tray = systrayNew
taffybar.rc view
@@ -1,6 +1,10 @@-gtk_color_scheme = "black:#000000\nwhite:#FFFFFF\ngreen:#00FF00\nred:#FF0000" -style "default" {+style "taffybar-default" {+  color["black"] = "#000000"+  color["white"] = "#ffffff"+  color["green"] = "#00ff00"+  color["red"]   = "#ff0000"+   bg[NORMAL]   = @black   fg[NORMAL]   = @white   text[NORMAL] = @white@@ -8,15 +12,15 @@   bg[PRELIGHT] = @black } -style "active-window" = "default" {+style "taffybar-active-window" = "taffybar-default" {   fg[NORMAL] = @green } -style "notification-button" = "default" {+style "taffybar-notification-button" = "taffybar-default" {   text[NORMAL] = @red   fg[NORMAL]   = @red } -widget "Taffybar*" style "default"-widget "Taffybar*WindowSwitcher*label" style "active-window"-widget "*NotificationCloseButton" style "notification-button"+widget "Taffybar*" style "taffybar-default"+widget "Taffybar*WindowSwitcher*label" style "taffybar-active-window"+widget "*NotificationCloseButton" style "taffybar-notification-button"