diff options
-rw-r--r-- | Main.hs | 27 | ||||
-rw-r--r-- | Operations.hs | 33 |
2 files changed, 46 insertions, 14 deletions
@@ -27,8 +27,11 @@ import Graphics.X11.Xinerama (getScreenInfo) import XMonad import Config import StackSet (new, floating, member) +import qualified StackSet as W import Operations +import System.IO + -- -- The main entry point -- @@ -47,6 +50,7 @@ main = do let winset | ("--resume" : s : _) <- args , [(x, "")] <- reads s = x | otherwise = new (fromIntegral workspaces) (fromIntegral $ length xinesc) + safeLayouts = case defaultLayouts of [] -> (full, []); (x:xs) -> (x, xs) cf = XConf { display = dpy @@ -71,14 +75,27 @@ main = do sync dpy False - ws <- scan dpy rootw + ws <- scan dpy rootw -- on the resume case, will pick up new windows allocaXEvent $ \e -> runX cf st $ do - mapM_ manage ws + + -- walk workspace, resetting X states/mask for windows + -- TODO, general iterators for these lists. + sequence_ [ setInitialProperties w >> reveal w + | wk <- map W.workspace (W.current winset : W.visible winset) + , w <- W.integrate (W.stack wk) ] + + sequence_ [ setInitialProperties w >> hide w + | wk <- W.hidden winset + , w <- W.integrate (W.stack wk) ] + + mapM_ manage ws -- find new windows -- withWindowSet (io . hPrint stderr) -- uncomment for state logging -- main loop, for all you HOF/recursion fans out there. - forever $ handle =<< io (nextEvent dpy e >> getEvent e) + forever $ do x <- io (nextEvent dpy e >> getEvent e) + io (hPrint stderr (eventName x, x)) + handle x where forever a = a >> forever a @@ -86,12 +103,12 @@ main = do -- IO stuff. Doesn't require any X state -- Most of these things run only on startup (bar grabkeys) --- | scan for any initial windows to manage +-- | scan for any new windows to manage. If they're already managed, +-- this should be idempotent. scan :: Display -> Window -> IO [Window] scan dpy rootw = do (_, _, ws) <- queryTree dpy rootw filterM ok ws - where ok w = do wa <- getWindowAttributes dpy w return $ not (wa_override_redirect wa) && wa_map_state wa == waIsViewable diff --git a/Operations.hs b/Operations.hs index 4ac14fd..93c0da0 100644 --- a/Operations.hs +++ b/Operations.hs @@ -36,13 +36,14 @@ import Graphics.X11.Xlib.Extras -- Window manager operations -- | manage. Add a new window to be managed in the current workspace. --- Bring it into focus. If the window is already managed, nothing happens. +-- Bring it into focus. +-- +-- Whether the window is already managed, or not, it is mapped, has its +-- border set, and its event mask set. -- manage :: Window -> X () manage w = withDisplay $ \d -> do - io $ selectInput d w $ structureNotifyMask .|. enterWindowMask .|. propertyChangeMask - io $ mapWindow d w - io $ setWindowBorderWidth d w borderWidth + setInitialProperties w >> reveal w -- FIXME: This is pretty awkward. We can't can't let "refresh" happen -- before the call to float, because that will resize the window and @@ -60,6 +61,9 @@ manage w = withDisplay $ \d -> do -- FIXME: clearFloating should be taken care of in W.delete, but if we do it -- there, floating status is lost when moving windows between workspaces, -- because W.shift calls W.delete. +-- +-- should also unmap? +-- unmanage :: Window -> X () unmanage w = setWMState w 0 {-withdrawn-} >> windows (W.sink w . W.delete w) @@ -183,12 +187,25 @@ setWMState w v = withDisplay $ \dpy -> do a <- atom_WM_STATE io $ changeProperty32 dpy w a a propModeReplace [fromIntegral v, fromIntegral none] --- | hide. Hide a window by unmapping it. +-- | hide. Hide a window by unmapping it, and setting Iconified. hide :: Window -> X () -hide w = withDisplay $ \d -> do +hide w = withDisplay $ \d -> do io $ unmapWindow d w setWMState w 3 --iconic +-- | reveal. Show a window by mapping it and setting Normal +-- this is harmless if the window was already visible +reveal :: Window -> X () +reveal w = withDisplay $ \d -> do + setWMState w 1 --normal + io $ mapWindow d w + +-- | Set some properties when we initially gain control of a window +setInitialProperties :: Window -> X () +setInitialProperties w = withDisplay $ \d -> io $ do + selectInput d w $ structureNotifyMask .|. enterWindowMask .|. propertyChangeMask + setWindowBorderWidth d w borderWidth + -- | refresh. Render the currently visible workspaces, as determined by -- the StackSet. Also, set focus to the focused window. -- @@ -213,9 +230,7 @@ tileWindow w r = withDisplay $ \d -> do bw <- (fromIntegral . wa_border_width) `liftM` io (getWindowAttributes d w) io $ moveResizeWindow d w (rect_x r) (rect_y r) (rect_width r - bw*2) (rect_height r - bw*2) - -- this is harmless if the window was already visible - setWMState w 1 --normal - io $ mapWindow d w + reveal w -- --------------------------------------------------------------------- |