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
This commit is contained in:
mail
2007-10-06 11:05:29 +00:00
parent d72ff99200
commit 32cffdbca1
2 changed files with 99 additions and 25 deletions

View File

@@ -1,42 +1,114 @@
module XMonadContrib.EwmhDesktops (ewmhDesktopsLogHook) where -----------------------------------------------------------------------------
-- |
-- Module : XMonadContrib.EwmhDesktops
-- Copyright : (c) Joachim Breitner <mail@joachim-breitner.de>
-- License : BSD
--
-- Maintainer : Joachim Breitner <mail@joachim-breitner.de>
-- 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.List (elemIndex, sortBy)
import Data.Ord ( comparing) import Data.Ord (comparing)
import Data.Maybe (fromMaybe)
import Control.Monad.Reader import Control.Monad.Reader
import XMonad import XMonad
import qualified StackSet as W import qualified StackSet as W
import System.IO
import Graphics.X11.Xlib import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras import Graphics.X11.Xlib.Extras
ewmhDesktopsLogHook :: X () -- $usage
ewmhDesktopsLogHook = withDisplay $ \dpy -> withWindowSet $ \s -> do -- Add the imports to your configuration file and add the logHook:
-- Number of Workspaces --
-- Bad hack because xmonad forgets the original order of things, it seems -- > import XMonadContrib.EwmhDesktops
let ws = sortBy (comparing W.tag) $ W.workspaces s --
-- > logHook :: X()
-- > logHook = do ewmhDesktopsLogHook
-- > return ()
let n = fromIntegral (length ws) -- %import XMonadContrib.EwmhDesktops
a <- getAtom "_NET_NUMBER_OF_DESKTOPS" -- %def -- comment out default logHook definition above if you uncomment this:
c <- getAtom "CARDINAL" -- %def logHook = ewmhDesktopsLogHook
r <- asks theRoot
io $ changeProperty32 dpy r a c propModeReplace [n]
-- |
-- Notifies pagers and window lists, such as those in the gnome-panel
-- of the current state of workspaces and windows.
ewmhDesktopsLogHook :: X ()
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
-- Number of Workspaces
setNumberOfDesktops (length ws)
-- Names thereof -- Names thereof
a <- getAtom "_NET_DESKTOP_NAMES" setDesktopNames (map W.tag ws)
c <- getAtom "UTF8_STRING"
let names = map (fromIntegral.fromEnum) $
concatMap (("Workspace "++) . (++['\0']). W.tag) ws
io $ changeProperty8 dpy r a c propModeReplace names
-- Current desktop -- Current desktop
a <- getAtom "_NET_CURRENT_DESKTOP" fromMaybe (return ()) $ do
c <- getAtom "CARDINAL" n <- W.lookupWorkspace 0 s
let Just n = W.lookupWorkspace 0 s i <- elemIndex n $ map W.tag ws
let Just i = elemIndex n $ map W.tag ws return $ setCurrentDesktop i
io $ changeProperty32 dpy r a c propModeReplace [fromIntegral 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 () 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"
r <- asks theRoot
io $ changeProperty32 dpy r a c propModeReplace [fromIntegral i]
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]

View File

@@ -34,6 +34,7 @@ import XMonadContrib.DwmPromote ()
import XMonadContrib.DynamicLog () import XMonadContrib.DynamicLog ()
import XMonadContrib.DynamicWorkspaces () import XMonadContrib.DynamicWorkspaces ()
import XMonadContrib.Dzen () import XMonadContrib.Dzen ()
import XMonadContrib.EwmhDesktop ()
import XMonadContrib.FindEmptyWorkspace () import XMonadContrib.FindEmptyWorkspace ()
import XMonadContrib.FlexibleResize () import XMonadContrib.FlexibleResize ()
import XMonadContrib.FlexibleManipulate () import XMonadContrib.FlexibleManipulate ()
@@ -75,3 +76,4 @@ import XMonadContrib.XPropManage ()
import XMonadContrib.Warp () import XMonadContrib.Warp ()
import XMonadContrib.WindowNavigation () import XMonadContrib.WindowNavigation ()
import XMonadContrib.WorkspaceDir () import XMonadContrib.WorkspaceDir ()