[sawfish/viewport] Fixed viewport-scrambling bugs.



commit 6071da522763e524d3a7ac6a061edb430d222161
Author: Jeremy Hankins <nowan nowan org>
Date:   Sun Oct 11 20:34:01 2009 -0500

    Fixed viewport-scrambling bugs.
    
    Canged logic of stop-at-workspace-borders in infinite-desktop.

 ChangeLog                               |   10 +++
 lisp/sawfish/wm/ext/infinite-desktop.jl |   26 +++++--
 lisp/sawfish/wm/ext/match-window.jl     |    5 +-
 lisp/sawfish/wm/state/maximize.jl       |  111 ++++++++++++++++++-------------
 lisp/sawfish/wm/util/edges.jl           |   53 ++++++++-------
 lisp/sawfish/wm/viewport.jl             |   70 +++++++++++++++++--
 man/news.texi                           |    5 ++
 7 files changed, 195 insertions(+), 85 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 1343bef..e9618f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2009-10-11  Jeremy Hankins <nowan nowan org>
+	* lisp/sawfish/wm/ext/match-window.jl
+	* lisp/sawfish/wm/state/maximize.jl
+	* lisp/sawfish/wm/util/edges.jl
+	* lisp/sawfish/wm/viewport.jl: Fix bugs that shift windows between viewports on restart:
+	                               - maximize-window and maximize-window-fullscreen now work for windows outside of the current viewport
+	                               - the position window matcher now preserves the current viewport
+
+	* lisp/sawfish/wm/ext/infinite-desktop.jl: infinite-desktop.stop-at-workspace-borders is now true iff viewport-boundary-mode is not dynamic.
+
 2009-10-09  Christopher Bratusek <zanghar freenet de>
 	* lisp/sawfish/wm/menus.jl: added "Reload Appsmenu" entry
 
diff --git a/lisp/sawfish/wm/ext/infinite-desktop.jl b/lisp/sawfish/wm/ext/infinite-desktop.jl
index 3dc9f97..8f09b0d 100644
--- a/lisp/sawfish/wm/ext/infinite-desktop.jl
+++ b/lisp/sawfish/wm/ext/infinite-desktop.jl
@@ -65,56 +65,65 @@
     :type number
     :range (1 . nil))
 
-  (defcustom infinite-desktop.stop-at-workspace-borders nil
-    "Stop scrolling at workspace borders (Fixes warp-to-window bugs)."
-    :group (workspace infinite-desktop)
-    :type boolean )
+  (define (infinite-desktop.stop-at-workspace-borders)
+    "Whether or not to prevent the display from moving past the
+current viewport boundaries.  Returns true if `viewport-boundary-mode'
+is not set to 'dynamic."
+    (not (eq viewport-boundary-mode 'dynamic)))
 
   (define (infinite-desktop.move-right)
+    "Shifts the display `infinite-desktop.move-distance' pixels to the
+right."
     (let ((dist infinite-desktop.move-distance)
           (cdist infinite-desktop.move-cursor-distance)
           (maxx (* (screen-width) (1- (car viewport-dimensions)))))
       (if
-          (and infinite-desktop.stop-at-workspace-borders
+          (and (infinite-desktop.stop-at-workspace-borders)
                (> (+ dist viewport-x-offset) maxx))
           (setq dist (- maxx viewport-x-offset)))
       (set-viewport (+ viewport-x-offset dist) viewport-y-offset)
       (move-cursor (- (min dist cdist)) 0)))
 
   (define (infinite-desktop.move-left)
+    "Shifts the display `infinite-desktop.move-distance' pixels to the
+left."
     (let ((dist (- infinite-desktop.move-distance))
           (cdist (- infinite-desktop.move-cursor-distance))
           (minx 0))
       (if
-          (and infinite-desktop.stop-at-workspace-borders
+          (and (infinite-desktop.stop-at-workspace-borders)
                (< (+ viewport-x-offset dist) minx))
           (setq dist (- minx viewport-x-offset)))
       (set-viewport (+ viewport-x-offset dist) viewport-y-offset)
       (move-cursor (- (max dist cdist)) 0)))
 
   (define (infinite-desktop.move-top)
+    "Shifts the display `infinite-desktop.move-distance' pixels up."
     (let ((dist (- infinite-desktop.move-distance))
           (cdist (- infinite-desktop.move-cursor-distance))
           (miny 0))
       (if
-          (and infinite-desktop.stop-at-workspace-borders
+          (and (infinite-desktop.stop-at-workspace-borders)
                (< (+ viewport-y-offset dist) miny))
           (setq dist (- miny viewport-y-offset)))
       (set-viewport viewport-x-offset (+ viewport-y-offset dist))
       (move-cursor 0 (- (max dist cdist)))))
 
   (define (infinite-desktop.move-bottom)
+    "Shifts the display `infinite-desktop.move-distance' pixels down."
     (let ((dist infinite-desktop.move-distance)
           (cdist infinite-desktop.move-cursor-distance)
           (maxy (* (screen-height) (1- (cdr viewport-dimensions)))))
       (if
-          (and infinite-desktop.stop-at-workspace-borders
+          (and (infinite-desktop.stop-at-workspace-borders)
                (> (+ dist viewport-y-offset) maxy))
           (setq dist (- maxy viewport-y-offset)))
       (set-viewport viewport-x-offset (+ viewport-y-offset dist))
       (move-cursor 0 (- (min dist cdist)))))
 
   (define (infinite-desktop.enter-flipper-hook w)
+    "Called when a desktop flipper is triggered to shift the visible
+desktop."
     (if infinite-desktop-p
         (cond ((eq w 'right) (infinite-desktop.move-right))
               ((eq w 'left) (infinite-desktop.move-left))
@@ -123,6 +132,7 @@
               (t (display-message "move-unknown")))))
 
   (define (infinite-desktop.infinite-desktop)
+    "Turn on infinite-desktop if `infinite-desktop-p' is true."
     (if infinite-desktop-p
         (enable-flippers)))
 
diff --git a/lisp/sawfish/wm/ext/match-window.jl b/lisp/sawfish/wm/ext/match-window.jl
index 71c94ad..a03a2d1 100644
--- a/lisp/sawfish/wm/ext/match-window.jl
+++ b/lisp/sawfish/wm/ext/match-window.jl
@@ -352,6 +352,7 @@
     (lambda (w prop value)
       (declare (unused prop))
       (let* ((size (window-frame-dimensions w))
+             (vp-offset (viewport-offset (window-viewport w)))
              (x (if (symbolp value)
                     (cond ((memq value '(east south-east north-east))
                            (- (screen-width) (car size)))
@@ -383,7 +384,9 @@
           (setq x (+ (- (screen-width) (car size)) x)))
         (when (< y 0)
           (setq y (+ (- (screen-height) (cdr size)) y)))
-        (move-window-to w x y))))
+        (move-window-to w
+                        (+ (car vp-offset) x)
+                        (+ (cdr vp-offset) y)))))
 
   (define-match-window-setter 'dimensions
     (lambda (w prop value)
diff --git a/lisp/sawfish/wm/state/maximize.jl b/lisp/sawfish/wm/state/maximize.jl
index 2c89973..b6c98a0 100644
--- a/lisp/sawfish/wm/state/maximize.jl
+++ b/lisp/sawfish/wm/state/maximize.jl
@@ -68,6 +68,8 @@
 	  sawfish.wm.frames
 	  sawfish.wm.misc
 	  sawfish.wm.focus
+          sawfish.wm.viewport
+          sawfish.wm.state.shading
 	  sawfish.wm.util.prompt)
 
   (define-structure-alias maximize sawfish.wm.state.maximize)
@@ -132,8 +134,8 @@ that dimension.")
   ;; currently maximize window to `(X Y W H)', the saved geometry.
   (define (save-unmaximized-geometry w)
     (unless (window-get w 'unmaximized-geometry)
-      (let ((coords (window-position w))
-	    (dims (window-dimensions w)))
+      (let* ((coords (window-relative-position w))
+             (dims (window-dimensions w)))
 	(window-put w 'unmaximized-geometry (list (car coords) (cdr coords)
 						  (car dims) (cdr dims))))))
 
@@ -150,7 +152,7 @@ that dimension.")
     (when vertically
       (window-put w 'maximized-vertically nil))
     (let ((dims (window-dimensions w))
-	  (coords (window-position w))
+	  (coords (window-relative-position w))
 	  (saved (unmaximized-geometry w)))
       (when saved
 	(unless (window-maximized-horizontally-p w)
@@ -336,54 +338,61 @@ that dimension.")
 
   (define (maximize-window w #!optional direction only-1d)
     "Maximize the dimensions of the window."
-    (let ((unshade-selected-windows t))
-      (display-window-without-focusing w))
+    (when (window-get w 'shaded)
+      (unshade-window w))
     (when (window-maximized-fullscreen-p w)
       (maximize-window-fullscreen w nil))
-    (let* ((coords (window-position w))
-	   (dims (window-dimensions w))
-	   (fdims (window-frame-dimensions w))
-	   (hints (window-size-hints w))
-	   (avoided (and maximize-avoid-avoided (avoided-windows w)))
-	   (edges (get-visible-window-edges
-		   #:with-ignored-windows t
-		   #:windows avoided
-		   #:include-heads (list (current-head w)))))
+    (let* ((viewport (window-viewport w))
+           (vp-offset (viewport-offset viewport))
+           (coords (window-position w))
+           (head (find-head (- (car coords) (car vp-offset))
+                            (- (cdr coords) (cdr vp-offset))))
+           (dims (window-dimensions w))
+           (fdims (window-frame-dimensions w))
+           (hints (window-size-hints w))
+           (avoided (and maximize-avoid-avoided (avoided-windows w)))
+           (edges (get-visible-window-edges
+                   #:with-ignored-windows t
+                   #:windows avoided
+                   #:include-heads (list head)
+                   #:viewport viewport)))
       (when (window-maximizable-p w direction hints)
-	(save-unmaximized-geometry w)
-	(cond ((null direction)
-	       (if (not only-1d)
-		   (do-both w avoided edges coords dims fdims)
-		 (do-horizontal w edges coords dims fdims)
-		 (do-vertical w edges coords dims fdims))
-	       (window-put w 'maximized-horizontally t)
-	       (window-put w 'maximized-vertically t))
-	      ((eq direction 'horizontal)
-	       (do-horizontal w edges coords dims fdims)
-	       (window-put w 'maximized-horizontally t))
-	      ((eq direction 'vertical)
-	       (do-vertical w edges coords dims fdims)
-	       (window-put w 'maximized-vertically t)))
-	(maximize-truncate-dims w dims direction hints)
-	(move-resize-window-to w (car coords) (cdr coords)
-			       (car dims) (cdr dims))
-	(when maximize-raises
-	  (raise-window* w))
-	(call-window-hook 'window-maximized-hook w (list direction))
-	(call-window-hook 'window-state-change-hook w (list '(maximized))))))
+        (save-unmaximized-geometry w)
+        (cond ((null direction)
+               (if (not only-1d)
+                   (do-both w avoided edges coords dims fdims)
+                 (do-horizontal w edges coords dims fdims)
+                 (do-vertical w edges coords dims fdims))
+               (window-put w 'maximized-horizontally t)
+               (window-put w 'maximized-vertically t))
+              ((eq direction 'horizontal)
+               (do-horizontal w edges coords dims fdims)
+               (window-put w 'maximized-horizontally t))
+              ((eq direction 'vertical)
+               (do-vertical w edges coords dims fdims)
+               (window-put w 'maximized-vertically t)))
+        (maximize-truncate-dims w dims direction hints)
+        (move-resize-window-to w (car coords) (cdr coords)
+                               (car dims) (cdr dims))
+        (when maximize-raises
+          (raise-window* w))
+        (call-window-hook 'window-maximized-hook w (list direction))
+        (call-window-hook 'window-state-change-hook w
+                          (list '(maximized))))))
 
   ;; does all unmaximizing except for changing the window properties and
   ;; calling the hooks
   (define (unmaximize-window-1 w #!optional direction before)
-    (let ((geom (unmaximized-geometry w))
+    (let ((vp-offset (viewport-offset (window-viewport w)))
+          (geom (unmaximized-geometry w))
 	  (coords (window-position w))
 	  (dims (window-dimensions w)))
       (when geom
 	(when (memq direction '(() fullscreen horizontal))
-	  (rplaca coords (nth 0 geom))
+	  (rplaca coords (+ (nth 0 geom) (car vp-offset)))
 	  (rplaca dims (nth 2 geom)))
 	(when (memq direction '(() fullscreen vertical))
-	  (rplacd coords (nth 1 geom))
+	  (rplacd coords (+ (nth 1 geom) (cdr vp-offset)))
 	  (rplacd dims (nth 3 geom)))
 	(when before
 	  (before))
@@ -521,13 +530,20 @@ unmaximized."
     "Fullscreen maximize the window."
     (cond ((and state (not (window-maximized-fullscreen-p w)))
 	   (when (window-maximizable-p w)
-	     (let ((head-offset (current-head-offset w))
-                   (head-dims (current-head-dimensions w)))
+             (let* ((viewport (window-viewport w))
+                    (vp-offset (viewport-offset viewport))
+                    (coords (window-position w))
+                    (head (find-head (- (car coords) (car vp-offset))
+                                     (- (cdr coords) (cdr vp-offset))))
+                    (head-offset (head-offset head))
+                    (head-dims (head-dimensions head)))
 	       (save-unmaximized-geometry w)
 	       (window-put w 'unmaximized-type (window-type w))
 	       (push-window-type w 'unframed 'sawfish.wm.state.maximize)
-	       (move-resize-window-to w (car head-offset) (cdr head-offset)
-				      (car head-dims) (cdr head-dims))
+	       (move-resize-window-to w
+                                      (+ (car head-offset) (car vp-offset))
+                                      (+ (cdr head-offset) (cdr vp-offset))
+                                      (car head-dims) (cdr head-dims))
 	       (raise-window* w)
 	       (window-put w 'maximized-fullscreen t)
 	       (window-put w 'maximized-vertically t)
@@ -554,13 +570,16 @@ unmaximized."
     "Fullscreen maximize the window across all Xinerama screens."
     (cond ((and state (not (window-maximized-fullscreen-p w)))
 	   (when (window-maximizable-p w)
-	     (let ((screen-dims (screen-dimensions)))
+	     (let ((screen-dims (screen-dimensions))
+                   (vp-offset (viewport-offset (window-viewport w))))
 	       (save-unmaximized-geometry w)
 	       (window-put w 'unmaximized-type (window-type w))
 	       (push-window-type w 'unframed 'sawfish.wm.state.maximize)
-	       (move-resize-window-to w 0 0
-                                      (car screen-dims)
-                                      (cdr screen-dims))
+	       (move-resize-window-to w
+                                      (car vp-offset)
+                                      (cdr vp-offset)
+                                      (+ (car screen-dims) (car vp-offset))
+                                      (+ (cdr screen-dims) (cdr vp-offset)))
 	       (raise-window* w)
 	       (window-put w 'maximized-fullscreen t)
 	       (window-put w 'maximized-vertically t)
diff --git a/lisp/sawfish/wm/util/edges.jl b/lisp/sawfish/wm/util/edges.jl
index d76a048..8d01e77 100644
--- a/lisp/sawfish/wm/util/edges.jl
+++ b/lisp/sawfish/wm/util/edges.jl
@@ -34,7 +34,8 @@
 
   (define (get-visible-window-edges #!key with-ignored-windows
 				    windows-to-ignore (windows t)
-				    include-screen include-heads)
+				    include-screen include-heads
+                                    viewport)
     "Returns (X-EDGES . Y-EDGES), X-EDGES is a list of (X Y1 Y2 OPEN-P),
 and Y-EDGES is a list of (Y X1 X2 OPEN-P). OPEN-P is t if the edge is
 the left or top edge of a window. For the root window, the meaning of
@@ -43,14 +44,20 @@ OPEN-P is reversed.
 #:include-heads may be a list of head ids, or a true non-list, in which
 case all heads are included.
 
+#:viewport may be a cons cell specifying (col . row); if specified
+edges are given for that viewport rather than the current one.
+
 The returned lists may contain duplicates, and are unsorted."
 
-    (let (x-edges y-edges)
+    (let* ((width (screen-width))
+           (height (screen-height))
+           (vp-offset (viewport-offset viewport))
+           x-edges y-edges)
       (map-windows
        (lambda (w)
 	 (when (and (window-mapped-p w)
 		    (window-visible-p w)
-		    (not (window-outside-viewport-p w))
+		    (not (window-outside-viewport-p w viewport))
 		    (or with-ignored-windows
 			(not (window-get w 'ignored)))
 		    (not (memq w windows-to-ignore))
@@ -73,12 +80,16 @@ The returned lists may contain duplicates, and are unsorted."
                                        y-edges)))))))
 
       (when include-screen
-	(setq x-edges (list* (list 0 0 (screen-height) nil)
-			     (list (screen-width) 0 (screen-height) t)
-			     x-edges))
-	(setq y-edges (list* (list 0 0 (screen-width) nil)
-			     (list (screen-height) 0 (screen-width) t)
-			     y-edges)))
+        (let* ((x-min (car vp-offset))
+               (y-min (cdr vp-offset))
+               (x-max (+ x-min width))
+               (y-max (+ y-min height)))
+          (setq x-edges (list* (list x-min y-min y-max nil)
+                               (list x-max y-min y-max t)
+                               x-edges))
+          (setq y-edges (list* (list y-min x-min x-max nil)
+                               (list y-max x-min x-max t)
+                               y-edges))))
 
       (when (and include-heads (not (listp include-heads)))
 	(setq include-heads (do ((i 0 (1+ i))
@@ -86,21 +97,17 @@ The returned lists may contain duplicates, and are unsorted."
 				((= i (head-count)) lst))))
       (when include-heads
 	(mapc (lambda (h)
-		(let ((dims (head-dimensions h))
-		      (offset (head-offset h)))
-		  (setq x-edges (list* (list (car offset)
-					     (cdr offset)
-					     (+ (cdr offset) (cdr dims)) nil)
-				       (list (+ (car offset) (car dims))
-					     (cdr offset)
-					     (+ (cdr offset) (cdr dims)) t)
+		(let* ((dims (head-dimensions h))
+                       (offset (head-offset h))
+                       (x-min (+ (car offset) (car vp-offset)))
+                       (y-min (+ (cdr offset) (cdr vp-offset)))
+                       (x-max (+ x-min (car dims)))
+                       (y-max (+ y-min (cdr dims))))
+		  (setq x-edges (list* (list x-min y-min y-max nil)
+				       (list x-max y-min y-max t)
 				       x-edges))
-		  (setq y-edges (list* (list (cdr offset)
-					     (car offset)
-					     (+ (car offset) (car dims)) nil)
-				       (list (+ (cdr offset) (cdr dims))
-					     (car offset)
-					     (+ (car offset) (car dims)) t)
+		  (setq y-edges (list* (list y-min x-min x-max nil)
+				       (list y-max x-min x-max t)
 				       y-edges))))
 	      include-heads))
 
diff --git a/lisp/sawfish/wm/viewport.jl b/lisp/sawfish/wm/viewport.jl
index c9f8297..77c0909 100644
--- a/lisp/sawfish/wm/viewport.jl
+++ b/lisp/sawfish/wm/viewport.jl
@@ -32,6 +32,8 @@
 	    set-window-viewport
 	    move-window-viewport
 	    window-viewport
+            viewport-offset
+            window-relative-position
 	    window-absolute-position
 	    set-number-of-viewports
 	    viewport-minimum-size-changed
@@ -217,6 +219,9 @@ well as any windows in the current workspace."
   (add-hook 'viewport-moved-hook
 	    viewport-dynamic-resize)
 
+  (add-hook 'after-initialization-hook
+            viewport-dynamic-resize)
+
   (define (viewport-leave-workspace-handler ws)
     "On leaving a workspace, store information about the viewport
 configuration so that it can be restored properly later."
@@ -266,6 +271,7 @@ viewport is within `viewport-dimensions'."
 ;;; screen sized viewport handling
 
   (define (screen-viewport)
+    "Gives the row and column of the current viewport."
     (cons (quotient viewport-x-offset (screen-width))
 	  (quotient viewport-y-offset (screen-height))))
 
@@ -300,6 +306,10 @@ viewport is within `viewport-dimensions'."
 			     (quotient (cdr pos) (screen-height))))))
 
   (define (window-outside-workspace-p window)
+    "True if `window' is outside the virtual workspace.  Note that
+this does not check which workspace the windows is in; the window is
+outside the virtual workspace if it's position is not within any
+viewport."
     (let ((pos (window-position window))
 	  (dims (window-frame-dimensions window))
 	  (left (- viewport-x-offset))
@@ -313,13 +323,29 @@ viewport is within `viewport-dimensions'."
 	  (<= (+ (car pos) (car dims)) left)
 	  (<= (+ (cdr pos) (cdr dims)) top))))
 
-  (define (window-outside-viewport-p window)
-    (let ((pos (window-position window))
-	  (dims (window-frame-dimensions window)))
-      (or (<= (+ (car pos) (car dims)) 0)
-	  (<= (+ (cdr pos) (cdr dims)) 0)
-	  (>= (car pos) (screen-width))
-	  (>= (cdr pos) (screen-height)))))
+  (define (window-outside-viewport-p window #!optional viewport)
+    "True if some part of `window' is inside the current viewport.  If
+`viewport' is specified check against that viewport rather than the
+current one."
+    (let* ((cur-vp (screen-viewport))
+           (width (screen-width))
+           (height (screen-height))
+           (x-min (if viewport
+                      (* (- (car viewport) (car cur-vp))
+                         width)
+                    0))
+           (x-max (+ x-min width))
+           (y-min (if viewport
+                      (* (- (cdr viewport) (cdr cur-vp))
+                         height)
+                    0))
+           (y-max (+ y-min width))
+           (pos (window-position window))
+           (dims (window-frame-dimensions window)))
+      (or (<= (+ (car pos) (car dims)) x-min)
+          (<= (+ (cdr pos) (cdr dims)) y-min)
+          (>= (car pos) x-max)
+          (>= (cdr pos) y-max))))
 
   (define (move-window-to-current-viewport window)
     (when (and (window-outside-viewport-p window)
@@ -347,11 +373,41 @@ viewport is within `viewport-dimensions'."
 					(screen-height)) row))))
 
   (define (window-viewport w)
+    "Returns a cons cell consisting of the column and row of the
+viewport containing w."
     (let ((position (window-position w)))
       (cons (quotient (+ (car position) viewport-x-offset) (screen-width))
 	    (quotient (+ (cdr position) viewport-y-offset) (screen-height)))))
 
+  (define (viewport-offset vp)
+    "`vp' is (column . row) of a viewport (whether or not that
+viewport currently exists).  A cons cell consisting of the x and y
+offset between the specified viewport and the current viewport is
+returned.  The offset can be used to translate between locations in
+the two viewports.  For example:
+
+<position in current vp> + <offset> = <equivalent position in other vp>
+
+If `vp' is nil treat it as the current viewport -- i.e., return '(0 . 0)"
+    (if (consp vp)
+        (let* ((cur-vp (screen-viewport)))
+          (cons
+           (* (- (car vp) (car cur-vp)) (screen-width))
+           (* (- (cdr vp) (cdr cur-vp)) (screen-height))))
+      '(0 . 0)))
+
+  (define (window-relative-position w)
+    "Returns a cons cell with the coordinates of the window relative
+to the viewport it occupies."
+    (let ((offset (viewport-offset (window-viewport w)))
+          (coords (window-position w)))
+      (cons
+       (- (car coords) (car offset))
+       (- (cdr coords) (cdr offset)))))
+
   (define (window-absolute-position w)
+    "Returns a cons cell with the coordinates of the window relative
+to the viewport 0,0."
     (let ((position (window-position w)))
       (if (window-outside-viewport-p w)
 	  (cons (mod (+ (car position) viewport-x-offset) (screen-width))
diff --git a/man/news.texi b/man/news.texi
index 0a27dd1..d6bb389 100644
--- a/man/news.texi
+++ b/man/news.texi
@@ -29,6 +29,11 @@ they occurred between. For more detailed information see the
 @item User visible changes:
 @itemize @minus
 
+ item In @code{infinite-desktop} there is no longer any option to
+prevent the viewport from going beyond the edge of the workspace.
+Instead it is prevented if and only if @code{viewport-boundary-mode} is
+not set to @code{'dynamic}.
+
 @item Sawfish now got an implementation of the FDO (freedesktop.org) application menu, it is
 beeing generated, if there's no customized apps-menu
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]