From a53a4fb237430f088d6e51c805ad14f03f1a18c5 Mon Sep 17 00:00:00 2001
From: Joachim Breitner <mail@joachim-breitner.de>
Date: Tue, 7 Oct 2008 10:00:41 +0200
Subject: UpdatePointer even to empty workspaces

This makes UpdatePointer more Xinerama-compatible: If the user switches to a
screen with an empty workspace, the pointer is moved to that workspace, which I
think is expected behavoiur.

darcs-hash:20081007080041-23c07-745bd6652a98765e33e732ee4291374ea825bc3c.gz
---
 XMonad/Actions/UpdatePointer.hs | 53 ++++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 22 deletions(-)

(limited to 'XMonad')

diff --git a/XMonad/Actions/UpdatePointer.hs b/XMonad/Actions/UpdatePointer.hs
index 9360fde..1caf3c2 100644
--- a/XMonad/Actions/UpdatePointer.hs
+++ b/XMonad/Actions/UpdatePointer.hs
@@ -25,7 +25,7 @@ module XMonad.Actions.UpdatePointer
 
 import XMonad
 import Control.Monad
-import XMonad.StackSet (member)
+import XMonad.StackSet (member, peek, screenDetail, current)
 
 -- $usage
 -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -53,40 +53,49 @@ import XMonad.StackSet (member)
 data PointerPosition = Nearest | Relative Rational Rational
 
 -- | Update the pointer's location to the currently focused
--- window unless it's already there, or unless the user was changing
+-- window or empty screen unless it's already there, or unless the user was changing
 -- focus with the mouse
 updatePointer :: PointerPosition -> X ()
-updatePointer p = withFocused $ \w -> do
+updatePointer p = do
   ws <- gets windowset
   dpy <- asks display
+  rect <- case peek ws of
+		Nothing -> return $ (screenRect . screenDetail .current) ws
+		Just w  -> windowAttributesToRectangle `fmap` io (getWindowAttributes dpy w)
   root <- asks theRoot
   mouseIsMoving <- asks mouseFocused
-  wa <- io $ getWindowAttributes dpy w
   (_sameRoot,_,currentWindow,rootx,rooty,_,_,_) <- io $ queryPointer dpy root
-  unless (pointWithinRegion rootx rooty (wa_x wa) (wa_y wa) (wa_width wa) (wa_height wa)
+  unless (pointWithin (fi rootx) (fi rooty) rect
           || mouseIsMoving
-          || not (currentWindow `member` ws)) $
+          || not (currentWindow `member` ws || currentWindow == none)) $
     case p of
     Nearest -> do
-      let x = moveWithin rootx (wa_x wa) ((wa_x wa) + (wa_width  wa))
-      let y = moveWithin rooty (wa_y wa) ((wa_y wa) + (wa_height wa))
-      io $ warpPointer dpy none root 0 0 0 0 (fromIntegral x) (fromIntegral y)
+      let x = moveWithin (fi rootx) (rect_x rect) (fi (rect_x rect) + fi (rect_width  rect))
+          y = moveWithin (fi rooty) (rect_y rect) (fi (rect_y rect) + fi (rect_height rect))
+      io $ warpPointer dpy none root 0 0 0 0 x y
     Relative h v ->
-      io $ warpPointer dpy none w 0 0 0 0
-           (fraction h (wa_width wa)) (fraction v (wa_height wa))
+      io $ warpPointer dpy none root 0 0 0 0
+           (rect_x rect + fraction h (rect_width rect))
+           (rect_y rect + fraction v (rect_height rect))
         where fraction x y = floor (x * fromIntegral y)
 
-moveWithin :: Integral a => a -> a -> a -> a
-moveWithin current lower upper =
-    if current < lower
+windowAttributesToRectangle :: WindowAttributes -> Rectangle
+windowAttributesToRectangle wa = Rectangle (fi (wa_x wa))     (fi (wa_y wa))
+                                           (fi (wa_width wa)) (fi (wa_height wa))
+moveWithin :: Ord a => a -> a -> a -> a
+moveWithin now lower upper =
+    if now < lower
     then lower
-    else if current > upper
+    else if now > upper
          then upper
-         else current
+         else now
+
+pointWithin :: Position -> Position -> Rectangle -> Bool
+pointWithin x y r = x >= rect_x r &&
+		    x <  rect_x r + fi (rect_width r) &&
+		    y >= rect_y r &&
+		    y <  rect_y r + fi (rect_height r)
+
+fi :: (Num b, Integral a) => a -> b
+fi = fromIntegral 
 
--- Test that a point resides within a region. 
--- This belongs somewhere more generally accessible than this module.
-pointWithinRegion :: Integral a => a -> a -> a -> a -> a -> a -> Bool
-pointWithinRegion px py rx ry rw rh =
-    within px rx (rx + rw) && within py ry (ry + rh)
-    where within x left right = x >= left && x <= right
-- 
cgit v1.2.3