summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Main.hs27
-rw-r--r--Operations.hs33
2 files changed, 46 insertions, 14 deletions
diff --git a/Main.hs b/Main.hs
index 79b92bf..89d07e0 100644
--- a/Main.hs
+++ b/Main.hs
@@ -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
-- ---------------------------------------------------------------------