From 8fbf8eac4711575bc82c7a524851c86c4f62d9f4 Mon Sep 17 00:00:00 2001 From: mail Date: Sat, 6 Oct 2007 13:05:29 +0200 Subject: EwmhWindows wrap up for inclusion Now with haddock documentation, a proper header and nicer, warningfree code, ready for a first release and inclusion in XMonadConrib. It works for me, but needs more testing. If you run xmonad with gnome-panel or something similar, please try it. Thanks, Joachim darcs-hash:20071006110529-c9905-998721b4329a1754d6e75a863bd5f44cf534836b.gz --- EwmhDesktops.hs | 114 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 21 deletions(-) (limited to 'EwmhDesktops.hs') diff --git a/EwmhDesktops.hs b/EwmhDesktops.hs index d6684ac..abce277 100644 --- a/EwmhDesktops.hs +++ b/EwmhDesktops.hs @@ -1,42 +1,114 @@ -module XMonadContrib.EwmhDesktops (ewmhDesktopsLogHook) where +----------------------------------------------------------------------------- +-- | +-- Module : XMonadContrib.EwmhDesktops +-- Copyright : (c) Joachim Breitner +-- License : BSD +-- +-- Maintainer : Joachim Breitner +-- Stability : unstable +-- Portability : unportable +-- +-- Makes xmonad use the EWMH hints to tell panel applications about its +-- workspaces and the windows therein. +----------------------------------------------------------------------------- +module XMonadContrib.EwmhDesktops ( + -- * Usage + -- $usage + ewmhDesktopsLogHook + ) where -import Data.Maybe (listToMaybe,fromJust) -import Data.List (elemIndex, sortBy) -import Data.Ord ( comparing) +import Data.List (elemIndex, sortBy) +import Data.Ord (comparing) +import Data.Maybe (fromMaybe) import Control.Monad.Reader import XMonad import qualified StackSet as W -import System.IO import Graphics.X11.Xlib import Graphics.X11.Xlib.Extras +-- $usage +-- Add the imports to your configuration file and add the logHook: +-- +-- > import XMonadContrib.EwmhDesktops +-- +-- > logHook :: X() +-- > logHook = do ewmhDesktopsLogHook +-- > return () + +-- %import XMonadContrib.EwmhDesktops +-- %def -- comment out default logHook definition above if you uncomment this: +-- %def logHook = ewmhDesktopsLogHook + + +-- | +-- Notifies pagers and window lists, such as those in the gnome-panel +-- of the current state of workspaces and windows. ewmhDesktopsLogHook :: X () -ewmhDesktopsLogHook = withDisplay $ \dpy -> withWindowSet $ \s -> do - -- Number of Workspaces +ewmhDesktopsLogHook = withWindowSet $ \s -> do -- Bad hack because xmonad forgets the original order of things, it seems + -- see http://code.google.com/p/xmonad/issues/detail?id=53 let ws = sortBy (comparing W.tag) $ W.workspaces s + let wins = W.allWindows s - let n = fromIntegral (length ws) - a <- getAtom "_NET_NUMBER_OF_DESKTOPS" - c <- getAtom "CARDINAL" - r <- asks theRoot - io $ changeProperty32 dpy r a c propModeReplace [n] + -- Number of Workspaces + setNumberOfDesktops (length ws) -- Names thereof - a <- getAtom "_NET_DESKTOP_NAMES" - c <- getAtom "UTF8_STRING" - let names = map (fromIntegral.fromEnum) $ - concatMap (("Workspace "++) . (++['\0']). W.tag) ws - io $ changeProperty8 dpy r a c propModeReplace names + setDesktopNames (map W.tag ws) -- Current desktop + fromMaybe (return ()) $ do + n <- W.lookupWorkspace 0 s + i <- elemIndex n $ map W.tag ws + return $ setCurrentDesktop i + + setClientList wins + + -- Per window Desktop + forM (zip ws [(0::Int)..]) $ \(w, wn) -> + forM (W.integrate' (W.stack w)) $ \win -> do + setWindowDesktop win wn + + return () + + +setNumberOfDesktops :: (Integral a) => a -> X () +setNumberOfDesktops n = withDisplay $ \dpy -> do + a <- getAtom "_NET_NUMBER_OF_DESKTOPS" + c <- getAtom "CARDINAL" + r <- asks theRoot + io $ changeProperty32 dpy r a c propModeReplace [fromIntegral n] + +setCurrentDesktop :: (Integral a) => a -> X () +setCurrentDesktop i = withDisplay $ \dpy -> do a <- getAtom "_NET_CURRENT_DESKTOP" c <- getAtom "CARDINAL" - let Just n = W.lookupWorkspace 0 s - let Just i = elemIndex n $ map W.tag ws + r <- asks theRoot io $ changeProperty32 dpy r a c propModeReplace [fromIntegral i] - - return () +setDesktopNames :: [String] -> X () +setDesktopNames names = withDisplay $ \dpy -> do + -- Names thereof + r <- asks theRoot + a <- getAtom "_NET_DESKTOP_NAMES" + c <- getAtom "UTF8_STRING" + let names' = map (fromIntegral.fromEnum) $ + concatMap (("Workspace "++) . (++['\0'])) names + io $ changeProperty8 dpy r a c propModeReplace names' +setClientList :: [Window] -> X () +setClientList wins = withDisplay $ \dpy -> do + -- (What order do we really need? Something about age and stacking) + r <- asks theRoot + c <- getAtom "WINDOW" + a <- getAtom "_NET_CLIENT_LIST" + io $ changeProperty32 dpy r a c propModeReplace wins + a' <- getAtom "_NET_CLIENT_LIST_STACKING" + io $ changeProperty32 dpy r a' c propModeReplace wins + +setWindowDesktop :: (Integral a) => Window -> a -> X () +setWindowDesktop win i = withDisplay $ \dpy -> do + a <- getAtom "_NET_WM_DESKTOP" + c <- getAtom "CARDINAL" + io $ changeProperty32 dpy win a c propModeReplace [fromIntegral i] -- cgit v1.2.3