Re: dynamic viewports



Christopher Roy Bratusek <zanghar freenet de> writes:
> no patch?

Yeah, lets try that again.  :P

-------------------------------------
diff --git a/lisp/sawfish/wm/viewport.jl b/lisp/sawfish/wm/viewport.jl
index 117ff2b..054b5ae 100644
--- a/lisp/sawfish/wm/viewport.jl
+++ b/lisp/sawfish/wm/viewport.jl
@@ -35,6 +35,7 @@
 	    window-viewport
 	    window-absolute-position
 	    set-number-of-viewports
+            viewport-minimum-size-changed
 	    viewport-windows)
 
     (open rep
@@ -57,7 +58,7 @@
     "Number of columns and rows in each virtual workspace: \\w"
     :group (workspace viewport)
     :type (pair (number 1) (number 1))
-    :after-set (lambda () (viewport-size-changed)))
+    :after-set (lambda () (viewport-size-changed t)))
 
   (defcustom viewport-minimum-dimensions '(1 . 1)
     "Minimum number of columns and rows in each virtual workspace: \\w"
@@ -77,10 +78,14 @@
     :range (1 . 50))
 
   (defcustom viewport-boundary-mode 'stop
-    "Whether to stop or wrap-around on first/last viewport"
+    "Whether to stop, wrap-around, or grow the virtual workspace on
+first/last viewport"
     :group (workspace viewport)
     :type (choice wrap-around stop dynamic))
 
+  (defvar workspace-viewport-data nil
+    "Information about the viewport details of different workspaces.")
+
 ;;; raw viewport handling
 
   (defvar viewport-x-offset 0)
@@ -106,7 +111,12 @@
 		;; ..then move away the windows on the old viewport,
 		;; in bottom-to-top order
 		(mapc move-window inside)))
-
+              ;; No need to warp windows not in the current workspace.
+              ;; See viewport-leave-workspace-handler and
+              ;; viewport-enter-workspace handler below.
+              ((not
+                (window-appears-in-workspace-p (car rest) current-workspace))
+               (loop (cdr rest) inside outside))
 	      ((window-outside-viewport-p (car rest))
 	       (loop (cdr rest) inside (cons (car rest) outside)))
 
@@ -134,6 +144,8 @@ The scrolling makes a number of increments equal to `scroll-viewport-steps'."
   (add-hook 'before-exit-hook viewport-before-exiting t)
 
   (define (viewport-dynamic-resize)
+    "Reset the size of the viewport to include the current screen as
+well as any windows in the current workspace."
     (when (eq viewport-boundary-mode 'dynamic)
       (let ((windows
 	     (filter-windows
@@ -141,7 +153,9 @@ The scrolling makes a number of increments equal to `scroll-viewport-steps'."
 		(window-in-workspace-p w current-workspace)))))
 	(if windows
 	    (let*
-		((points
+                ((width (screen-width))
+		 (height (screen-height))
+		 (points
 		  (nconc
 		   (mapcar (lambda (w)
 			     (let ((pos (window-position w))
@@ -151,39 +165,45 @@ The scrolling makes a number of increments equal to `scroll-viewport-steps'."
 				     (+ (car pos) (car dims))
 				     (+ (cdr pos) (cdr dims)))))
 			   windows)
-		   ;; Include a region in the current screen:
-		   `((0 0 1 1))))
-		 (x-min (apply min (mapcar car points)))
-		 (y-min (apply min (mapcar (lambda (e) (nth 1 e)) points)))
-		 (x-max (apply max (mapcar (lambda (e) (nth 2 e)) points)))
-		 (y-max (apply max (mapcar (lambda (e) (nth 3 e)) points)))
-		 (width (screen-width))
-		 (height (screen-height))
+		   ;; Include the current screen:
+		   `((0 0 ,(1- width) ,(1- height)))))
+                 ;; The min/max values calculated below are relative to
+                 ;; the old logical 0,0 point of the virtual desktop:
+                 (old-x-origin (- viewport-x-offset))
+                 (old-y-origin (- viewport-y-offset))
+                 (x-min (- (apply min (mapcar car points)) old-x-origin))
+                 (y-min (- (apply min (mapcar (lambda (e) (nth 1 e)) points))
+                           old-y-origin))
+                 (x-max (- (apply max (mapcar (lambda (e) (nth 2 e)) points))
+                           old-x-origin))
+                 (y-max (- (apply max (mapcar (lambda (e) (nth 3 e)) points))
+                           old-y-origin))
+                 ;; high-* values are the number of rows/columns above
+                 ;; the old origin, low-* values the number below the
+                 ;; old origin.
 		 (high-rows (+ (quotient y-max height)
-			       (if (> (mod y-max height) 0)
-				   1
-				 0)))
-		 (low-rows (if (< y-min 0)
-			       (+ (- (quotient y-min height))
-				  (if (> (mod y-min height) 0)
-				      1
-				    0))
-			     0))
+                               (if (> (mod y-max height) 0)
+                                   1
+                                 0)))
+		 (low-rows (+ (- (quotient y-min height))
+                              (if (and (< y-min 0)
+                                       (> (mod y-min height) 0))
+                                  1
+                                0)))
 		 (rows (+ low-rows high-rows))
 		 (high-cols (+ (quotient x-max width)
 			       (if (> (mod x-max width) 0)
 				   1
 				 0)))
-		 (low-cols (if (< x-min 0)
-			       (+ (- (quotient x-min width))
-				  (if (> (mod x-min width) 0)
-				      1
-				    0))
-			     0))
+		 (low-cols (+ (- (quotient x-min width))
+                              (if (and (< x-min 0)
+                                       (> (mod x-min width) 0))
+                                  1
+                                0)))
 		 (cols (+ low-cols high-cols)))
 	      (setq
-	       viewport-y-offset (* low-rows height)
-	       viewport-x-offset (* low-cols width)
+	       viewport-y-offset (- (- old-y-origin (* low-rows height)))
+	       viewport-x-offset (- (- old-x-origin (* low-cols width)))
 	       viewport-dimensions (cons
 				    (max cols
 					 (car viewport-minimum-dimensions))
@@ -194,14 +214,55 @@ The scrolling makes a number of increments equal to `scroll-viewport-steps'."
 		viewport-dimensions viewport-minimum-dimensions))
 	(call-hook 'viewport-resized-hook))))
 
-  ;; Resize virtual workspace on workspace switch or viewport move.
-  ;; TODO: Ensure that the viewport is set reasonably in the new
-  ;; workspace.
-  (add-hook 'enter-workspace-hook
-	    viewport-dynamic-resize)
+  ;; Resize virtual workspace on workspace switch or viewport move:
   (add-hook 'viewport-moved-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."
+    (let ((vp-data (list viewport-y-offset
+                         viewport-x-offset
+                         viewport-dimensions))
+          (old-ent (assoc ws workspace-viewport-data)))
+      (if old-ent
+          (rplacd old-ent vp-data)
+        (setq workspace-viewport-data
+              (cons (cons ws vp-data)
+                    workspace-viewport-data)))))
+
+  (add-hook 'leave-workspace-hook
+            viewport-leave-workspace-handler)
+
+  (define (viewport-enter-workspace-handler ws)
+    "Restore any saved data about the viewport for the new workspace.
+When `viewport-boundary-mode' is not `dynamic', make sure that the new
+viewport is within `viewport-dimensions'."
+    (let ((vp-data (cdr (assoc ws workspace-viewport-data))))
+      (if vp-data
+          (let ((maybe-y-offset (car vp-data))
+                (maybe-x-offset (nth 1 vp-data)))
+            (if (eq viewport-boundary-mode 'dynamic)
+                (setq viewport-dimensions (nth 2 vp-data)
+                      viewport-y-offset maybe-y-offset
+                      viewport-x-offset maybe-x-offset)
+              ;; Do maybe-y-offset and maybe-x-offset fit within
+              ;; current viewport-dimensions?
+              (if (and (<= maybe-y-offset
+                          (* (1- (car viewport-dimensions)) (screen-height)))
+                       (<= maybe-x-offset
+                          (* (1- (cdr viewport-dimensions)) (screen-width))))
+                  (setq viewport-y-offset maybe-y-offset
+                        viewport-x-offset maybe-x-offset)
+                (setq viewport-y-offset 0
+                      viewport-x-offset 0))))
+        (setq viewport-y-offset 0
+              viewport-x-offset 0))
+      (viewport-size-changed)))
+
+  (add-hook 'enter-workspace-hook
+            viewport-enter-workspace-handler)
+
 ;; screen sized viewport handling
 
   (define (screen-viewport)
@@ -297,22 +358,37 @@ The scrolling makes a number of increments equal to `scroll-viewport-steps'."
 		(mod (+ (cdr position) viewport-y-offset) (screen-height)))
 	position)))
 
-  (define (viewport-size-changed)
+  (define (viewport-size-changed #!optional force)
+    ;; This is called when the user requests a change (e.g., from the
+    ;; gui, or via `set-number-of-viewports') as well as when the
+    ;; desktop is switched.  If `force' is set it's considered to be
+    ;; user-requested, and therefore mandatory that the
+    ;; `viewport-dimensions' variable be respected.
     (when (or (< (car viewport-dimensions) (car viewport-minimum-dimensions))
 	      (< (cdr viewport-dimensions) (cdr viewport-minimum-dimensions)))
-      (setq viewport-minimum-dimensions
-	    (cons (min (car viewport-dimensions)
-		       (car viewport-minimum-dimensions))
-		  (min (cdr viewport-dimensions)
-		       (cdr viewport-minimum-dimensions))))
+      (if force
+          (setq viewport-minimum-dimensions
+                (cons (min (car viewport-dimensions)
+                           (car viewport-minimum-dimensions))
+                      (min (cdr viewport-dimensions)
+                           (cdr viewport-minimum-dimensions))))
+        (setq viewport-dimensions
+              (cons (max (car viewport-dimensions)
+                         (car viewport-minimum-dimensions))
+                    (max (cdr viewport-dimensions)
+                         (cdr viewport-minimum-dimensions)))))
       (when (eq viewport-boundary-mode 'dynamic)
 	(viewport-dynamic-resize)))
     (unless (eq viewport-boundary-mode 'dynamic)
+      ;; Not using dynmic viewports, so ensure that windows are within
+      ;; the current virtual-workspace boundaries:
       (let ((port (screen-viewport)))
 	(set-screen-viewport (min (car port) (1- (car viewport-dimensions)))
 			     (min (cdr port) (1- (cdr viewport-dimensions))))
 	(map-windows (lambda (w)
-		       (when (window-outside-workspace-p w)
+		       (when (and (window-outside-workspace-p w)
+                                  (window-appears-in-workspace-p
+                                   w current-workspace))
 			 (move-window-to-current-viewport w))))
 	(call-hook 'viewport-resized-hook))))
 
@@ -333,7 +409,7 @@ The scrolling makes a number of increments equal to `scroll-viewport-steps'."
     (setq viewport-minimum-dimensions (cons width height))
     (if (eq viewport-boundary-mode 'dynamic)
 	(viewport-dynamic-resize)
-      (viewport-size-changed)))
+      (viewport-size-changed t)))
 
   (define (viewport-windows #!optional vp-col vp-row workspace
                             exclude-sticky exclude-iconified)
diff --git a/man/sawfish.texi b/man/sawfish.texi
index f16b663..b66d1c0 100644
--- a/man/sawfish.texi
+++ b/man/sawfish.texi
@@ -3842,6 +3842,17 @@ This is a cons cell @code{(@var{across} . @var{down})}.  Defaults to
 @code{(1 . 1)}.
 @end defvar
 
+ defvar viewport-minimum-dimensions
+This is only useful if @code{viewport-boundary-mode} is set to
+ code{dynamic}, otherwise it is automatically set to the same value as
+viewport-dimensions.  If @code{viewport-boundary-mode} is set to
+ code{dynamic} then @code{viewport-dimensions} will never shrink to
+less than @code{viewport-minimum-dimensions}.  If setting
+ code{viewport-minimum-dimensions} by hand (not by the customization
+interface) be sure to call @code{viewport-minimum-size-changed} after
+doing so.
+ end defvar
+
 @defun set-number-of-viewports width height
 Change @code{viewport-dimensions} to have the value
 @code{(@var{width} . @var{height})}.
@@ -3885,9 +3896,11 @@ that is outside of @code{viewport-dimensions}.  When set to
 @code{wrap-around}, it loops in the vertical and horizontal axes
 enough times to keep the viewport within the defined dimensions.  When
 set to @code{stop}, it refuses to switch to a viewport outside of
- code{viewport-dimensions}, if set to @code{dynamic}, it will create a
-new viewport at the side the pointer hit the screen-edge.
-Defaults to @code{wrap-around}.
+ code{viewport-dimensions}   If it is set to @code{dynamic} it
+automatically resizes @code{viewport-dimensions} to permit the move
+and eliminate unneeded rows or columns, down to the minimum dimensions
+specified by @code{viewport-minimum-dimensions}.  Defaults to
+ code{wrap-around} 
 @end defvar
 
 @defun warp-viewport x y
-------------------------------------

-- 
Jeremy Hankins <nowan nowan org>
PGP fingerprint: 748F 4D16 538E 75D6 8333  9E10 D212 B5ED 37D0 0A03


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