mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-08-02 13:11:52 -07:00
EwmhDesktops: Cache properties independently
This commit is contained in:
@@ -75,20 +75,37 @@ ewmhDesktopsLogHook :: X ()
|
|||||||
ewmhDesktopsLogHook = ewmhDesktopsLogHookCustom id
|
ewmhDesktopsLogHook = ewmhDesktopsLogHookCustom id
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
-- The values of @_NET_NUMBER_OF_DESKTOPS@, @_NET_CLIENT_LIST@,
|
-- Cached desktop names (e.g. @_NET_NUMBER_OF_DESKTOPS@ and
|
||||||
-- @_NET_CLIENT_LIST_STACKING@, and @_NET_CURRENT_DESKTOP@, cached to avoid
|
-- @_NET_DESKTOP_NAMES@).
|
||||||
-- unnecessary property updates. Another design would be to cache each of these
|
newtype DesktopNames = DesktopNames [String]
|
||||||
-- independently to allow us to avoid even more updates.
|
deriving (Eq)
|
||||||
data DesktopState
|
|
||||||
= DesktopState { desktopNames :: [String]
|
|
||||||
, clientList :: [Window]
|
|
||||||
, currentDesktop :: Maybe Int
|
|
||||||
, windowDesktops :: M.Map Window Int
|
|
||||||
}
|
|
||||||
deriving (Eq)
|
|
||||||
|
|
||||||
instance ExtensionClass DesktopState where
|
instance ExtensionClass DesktopNames where
|
||||||
initialValue = DesktopState [] [] Nothing M.empty
|
initialValue = DesktopNames []
|
||||||
|
|
||||||
|
-- |
|
||||||
|
-- Cached client list (e.g. @_NET_CLIENT_LIST@).
|
||||||
|
newtype ClientList = ClientList [Window]
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance ExtensionClass ClientList where
|
||||||
|
initialValue = ClientList []
|
||||||
|
|
||||||
|
-- |
|
||||||
|
-- Cached current desktop (e.g. @_NET_CURRENT_DESKTOP@).
|
||||||
|
newtype CurrentDesktop = CurrentDesktop Int
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance ExtensionClass CurrentDesktop where
|
||||||
|
initialValue = CurrentDesktop 0
|
||||||
|
|
||||||
|
-- |
|
||||||
|
-- Cached window-desktop assignments (e.g. @_NET_CLIENT_LIST_STACKING@).
|
||||||
|
newtype WindowDesktops = WindowDesktops (M.Map Window Int)
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance ExtensionClass WindowDesktops where
|
||||||
|
initialValue = WindowDesktops M.empty
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
-- The value of @_NET_ACTIVE_WINDOW@, cached to avoid unnecessary property
|
-- The value of @_NET_ACTIVE_WINDOW@, cached to avoid unnecessary property
|
||||||
@@ -99,20 +116,6 @@ newtype ActiveWindow = ActiveWindow Window
|
|||||||
instance ExtensionClass ActiveWindow where
|
instance ExtensionClass ActiveWindow where
|
||||||
initialValue = ActiveWindow none
|
initialValue = ActiveWindow none
|
||||||
|
|
||||||
toDesktopState :: ([WindowSpace] -> [WindowSpace]) -> WindowSet -> DesktopState
|
|
||||||
toDesktopState f s =
|
|
||||||
DesktopState
|
|
||||||
{ desktopNames = map W.tag ws
|
|
||||||
, clientList = nub . concatMap (maybe [] (\(W.Stack x l r) -> reverse l ++ r ++ [x]) . W.stack) $ ws
|
|
||||||
, currentDesktop =
|
|
||||||
let maybeCurrent' = W.tag <$> listToMaybe (f [W.workspace $ W.current s])
|
|
||||||
in join (flip elemIndex (map W.tag ws) <$> maybeCurrent')
|
|
||||||
, windowDesktops =
|
|
||||||
let f wsId workspace = M.fromList [ (winId, wsId) | winId <- W.integrate' $ W.stack workspace ]
|
|
||||||
in M.unions $ zipWith f [0..] ws
|
|
||||||
}
|
|
||||||
where ws = f $ W.workspaces s
|
|
||||||
|
|
||||||
-- | Compare the given value against the value in the extensible state. Run the
|
-- | Compare the given value against the value in the extensible state. Run the
|
||||||
-- action if it has changed.
|
-- action if it has changed.
|
||||||
whenChanged :: (Eq a, ExtensionClass a) => a -> X () -> X ()
|
whenChanged :: (Eq a, ExtensionClass a) => a -> X () -> X ()
|
||||||
@@ -128,25 +131,34 @@ whenChanged v action = do
|
|||||||
ewmhDesktopsLogHookCustom :: ([WindowSpace] -> [WindowSpace]) -> X ()
|
ewmhDesktopsLogHookCustom :: ([WindowSpace] -> [WindowSpace]) -> X ()
|
||||||
ewmhDesktopsLogHookCustom f = withWindowSet $ \s -> do
|
ewmhDesktopsLogHookCustom f = withWindowSet $ \s -> do
|
||||||
sort' <- getSortByIndex
|
sort' <- getSortByIndex
|
||||||
let s' = toDesktopState (f . sort') s
|
let ws = f $ sort' $ W.workspaces s
|
||||||
whenChanged s' $ do
|
|
||||||
-- Number of Workspaces
|
|
||||||
setNumberOfDesktops (length $ desktopNames s')
|
|
||||||
|
|
||||||
-- Names thereof
|
-- Set number of workspaces and names thereof
|
||||||
setDesktopNames $ desktopNames s'
|
let desktopNames = map W.tag ws
|
||||||
|
whenChanged (DesktopNames desktopNames) $ do
|
||||||
|
setNumberOfDesktops (length desktopNames)
|
||||||
|
setDesktopNames desktopNames
|
||||||
|
|
||||||
-- all windows, with focused windows last
|
-- Set client list; all windows, with focused windows last
|
||||||
setClientList $ clientList s'
|
let clientList = nub . concatMap (maybe [] (\(W.Stack x l r) -> reverse l ++ r ++ [x]) . W.stack) $ ws
|
||||||
|
whenChanged (ClientList clientList) $ setClientList clientList
|
||||||
|
|
||||||
-- Remap the current workspace to handle any renames that f might be doing.
|
-- Remap the current workspace to handle any renames that f might be doing.
|
||||||
fromMaybe (return ()) $ setCurrentDesktop <$> currentDesktop s'
|
let maybeCurrent' = W.tag <$> listToMaybe (f [W.workspace $ W.current s])
|
||||||
|
current = join (flip elemIndex (map W.tag ws) <$> maybeCurrent')
|
||||||
|
whenChanged (CurrentDesktop $ fromMaybe 0 current) $ do
|
||||||
|
mapM_ setCurrentDesktop current
|
||||||
|
|
||||||
mapM_ (uncurry setWindowDesktop) (M.toList $ windowDesktops s')
|
-- Set window-desktop mapping
|
||||||
|
let windowDesktops =
|
||||||
|
let f wsId workspace = M.fromList [ (winId, wsId) | winId <- W.integrate' $ W.stack workspace ]
|
||||||
|
in M.unions $ zipWith f [0..] ws
|
||||||
|
whenChanged (WindowDesktops windowDesktops) $ do
|
||||||
|
mapM_ (uncurry setWindowDesktop) (M.toList windowDesktops)
|
||||||
|
|
||||||
|
-- Set active window
|
||||||
let activeWindow' = fromMaybe none (W.peek s)
|
let activeWindow' = fromMaybe none (W.peek s)
|
||||||
whenChanged (ActiveWindow activeWindow') $ do
|
whenChanged (ActiveWindow activeWindow') $ setActiveWindow activeWindow'
|
||||||
setActiveWindow activeWindow'
|
|
||||||
|
|
||||||
-- |
|
-- |
|
||||||
-- Intercepts messages from pagers and similar applications and reacts on them.
|
-- Intercepts messages from pagers and similar applications and reacts on them.
|
||||||
|
Reference in New Issue
Block a user