summaryrefslogtreecommitdiffstats
path: root/Main.hs
diff options
context:
space:
mode:
authorSpencer Janssen <sjanssen@cse.unl.edu>2007-06-06 23:40:06 +0200
committerSpencer Janssen <sjanssen@cse.unl.edu>2007-06-06 23:40:06 +0200
commit89605d843ddf353e29e0727f90770a4db3097030 (patch)
treeb4db0e066658b6ccd4afb4e4dd79496800d55e80 /Main.hs
parent1942cef8ab9f3c9ae5bf4c7c37928ed0fd01af6c (diff)
downloadmetatile-89605d843ddf353e29e0727f90770a4db3097030.tar
metatile-89605d843ddf353e29e0727f90770a4db3097030.zip
Fix unmap handling
According to the ICCCM, clients should send a synthetic unmap event when they initiate an unmap. The old code waited for these synthetic unmaps to unmanage windows. However, certain 'obsolete' clients do not send synthetic unmaps (notably xpdf's find dialog). These windows entered a zombified state: xmonad does not manage them, yet they are still mapped and raised on screen. The new algorithm (derived from wmii): - track windows that are mapped on screen - track the number of expected unmap events for each window, increment every time 'hide' is called on a window that is not mapped. - decrement the expected unmap counter on each unmap event - treat an unmap event as genuine (ie. unmap the window) when: - the event is synthetic (per ICCCM) - OR there are no expected unmap events for this window darcs-hash:20070606214006-a5988-7c2eced85319ff506a9b7c9dc86d5946ca0da8e5
Diffstat (limited to 'Main.hs')
-rw-r--r--Main.hs22
1 files changed, 12 insertions, 10 deletions
diff --git a/Main.hs b/Main.hs
index 03cf277..de1b979 100644
--- a/Main.hs
+++ b/Main.hs
@@ -15,8 +15,10 @@
import Data.Bits
import qualified Data.Map as M
+import qualified Data.Set as S
import Control.Monad.Reader
import Control.Monad.State
+import Data.Maybe (fromMaybe)
import System.Environment (getArgs)
@@ -62,7 +64,9 @@ main = do
{ windowset = winset
, layouts = M.fromList [(w, safeLayouts) | w <- [0 .. W workspaces - 1]]
, statusGaps = take (length xinesc) $ defaultGaps ++ repeat (0,0,0,0)
- , xineScreens = xinesc }
+ , xineScreens = xinesc
+ , mapped = S.empty
+ , waitingUnmap = M.empty }
xSetErrorHandler -- in C, I'm too lazy to write the binding: dons
@@ -160,15 +164,13 @@ handle (MapRequestEvent {ev_window = w}) = withDisplay $ \dpy -> do
-- window gone, unmanage it
handle (DestroyWindowEvent {ev_window = w}) = whenX (isClient w) $ unmanage w
--- We only handle synthetic unmap events, because real events are confusable
--- with the events produced by 'hide'. ICCCM says that all clients should send
--- synthetic unmap events immediately after unmapping, and later describes
--- clients that do not follow the rule as "obsolete". For now, we make the
--- simplifying assumption that nobody uses clients that were already obsolete
--- in 1994. Note that many alternative methods for resolving the hide/withdraw
--- ambiguity are racy.
-
-handle (UnmapEvent {ev_window = w, ev_send_event = True}) = whenX (isClient w) $ unmanage w
+-- We track expected unmap events in waitingUnmap. We ignore this event unless
+-- it is synthetic or we are not expecting an unmap notification from a window.
+handle (UnmapEvent {ev_window = w, ev_send_event = synthetic}) = whenX (isClient w) $ do
+ e <- gets (fromMaybe 0 . M.lookup w . waitingUnmap)
+ if (synthetic || e == 0)
+ then unmanage w
+ else modify (\s -> s { waitingUnmap = M.adjust pred w (waitingUnmap s) })
-- set keyboard mapping
handle e@(MappingNotifyEvent {ev_window = w}) = do