380 lines
11 KiB
Plaintext
380 lines
11 KiB
Plaintext
;;
|
|
;; Virtual Screen code my Emanuel Jay Berkenbilt, MIT
|
|
;;
|
|
;; Parameters
|
|
;;
|
|
;; vscreen.right, left, up, down are amounts to move windows in
|
|
;; the respective directions.
|
|
;;
|
|
;; vscreen.nailed-windows is a list of windowspecs that are immune from
|
|
;; the virtual screen code
|
|
;;
|
|
|
|
;; Colas' note: this neat vtwm-like package is included as sent to me by
|
|
;; Jay Berkenbilt, MIT <qjb@ATHENA.MIT.EDU>
|
|
|
|
;; The vscreen code that I am going to include here is not the most
|
|
;; "cleaned up" possible code. It isn't that bad, though. All
|
|
;; globals start with "vscreen.". The only hard-coded values that
|
|
;; are not set to constants are indices into lists. I have a list
|
|
;; called "params". I freely refer to (# 0 params) intead of
|
|
;; assigning this a name. I do this also with a point: (# 0
|
|
;; vscreen.pos) is the x coordinate..... In addition, I have some
|
|
;; things in vscreen.gwm that really should be in .profile.gwm, but
|
|
;; this will probably be obvious when you look at the code.
|
|
;;
|
|
;; I am not sure that my handling the "show-windows" code is
|
|
;; correct. I display a map of the windows on the screen by
|
|
;; creating a pixmap and making a one-bar menu out of it. I then
|
|
;; use place-menu to show the window and delete-menu to get rid of
|
|
;; it.
|
|
;;
|
|
;; Anyway, here is the code. After the code, I will mention a few
|
|
;; of the ways that I use it.
|
|
;;
|
|
;; The main interesting functions are
|
|
;; vscreen.move-windows-{left,up,down,right}, vscreen.restore and
|
|
;; vscreen.show-windows. The vscreen.move-windows routines move
|
|
;; all windows (except for the "nailed" ones) and keep vscreen.pos
|
|
;; consistent. vcsreen.restore puts the virtual screen back where
|
|
;; it belongs. vscreen.show-windows draws a map of the windows
|
|
;; putting an X on the spot where the physical origin of the screen
|
|
;; is.
|
|
;;
|
|
;; I have key bindings (CTRL-SHIFT arrows) for the move functions
|
|
;; and other key bindings for restore and show-windows.
|
|
;;
|
|
;; This code as presented works fine with the standard profile. (I
|
|
;; tested it with the aid of "Exec Cut" :-) .
|
|
;;
|
|
;; I use it elsewhere in my code as well, however. There is a
|
|
;; function vscreen.make-window-visible that moves the virtual
|
|
;; screen enough to make the current window visible. I use this
|
|
;; along with raise-window in my de-iconfication code. In
|
|
;; addition, I have some functions that bring a window of a given
|
|
;; name to the top, map the window and deiconify it if necessary,
|
|
;; and warp the mouse pointer to the window. That code now also
|
|
;; moves the vscreen appropriately as well. The vscreen motion is
|
|
;; occasionally a little off -- sometimes it moves one notch too
|
|
;; far. This is a border condition that happens because I have a
|
|
;; lot of windows flush against the edge of the screen. In any
|
|
;; case, the window is always at least partially on the screen...
|
|
;;
|
|
;; Finally, I load the vscreen code by doing
|
|
;; (set-window Gwm.Gwm.Vscreen vscreen) in my .profile. This is
|
|
;; the window that vscreen.show-windows creates.
|
|
|
|
;; User-redefinable defaults
|
|
;;==========================
|
|
|
|
(defaults-to ; user-settable resources
|
|
vscreen.menupos 6 ; position in root menu
|
|
vscreen.windowmenupos 4 ; position in window menu
|
|
vscreen.modifiers (together with-control with-alt) ; modifs for arrow keys
|
|
vscreen.no-bindings () ; t for not binding arrow keys
|
|
|
|
vscreen.right-left (/ screen-width 2) ; amount to move by keys
|
|
vscreen.down-up (/ screen-height 2)
|
|
|
|
vscreen.nailed-windows ; fixed windows
|
|
(list
|
|
(list 'client-class "Zwgc" 'client-name "zwgc")
|
|
(list 'client-class "XScreensaver")
|
|
(list 'client-class "Console" 'client-name "console")
|
|
(list 'client-class "XTerm" 'client-name "local" 'window-name "safe")
|
|
)))
|
|
|
|
;; ============================================================================
|
|
|
|
;;
|
|
;; Our position. This is the real coordinates of the virtual origin
|
|
;;
|
|
|
|
(setq vscreen.pos (list 0 0))
|
|
|
|
|
|
(defun vscreen.nailed ()
|
|
;;
|
|
;; Determine whether the current window is nailed or not
|
|
;; caches the result in 'nailed property on main window (not icon)
|
|
;;
|
|
(if (setq tmp (# 'nailed window-window))
|
|
(if (= 'no tmp) ()
|
|
t
|
|
)
|
|
(tag vscreen.match-windowspec
|
|
(for spec vscreen.nailed-windows
|
|
(if (match-windowspec spec)
|
|
(progn
|
|
(vscreen.nail)
|
|
(exit vscreen.match-windowspec t)
|
|
))
|
|
(vscreen.un-nail)
|
|
()
|
|
)))))
|
|
|
|
(defun vscreen.nail ()
|
|
;; nail down a window
|
|
(## 'nailed window-window t)
|
|
)
|
|
|
|
(defun vscreen.un-nail ()
|
|
;; un-nail a window
|
|
(## 'nailed window-window 'no)
|
|
)
|
|
|
|
(defun vscreen.movable ()
|
|
;;
|
|
;; Returns a list of movable windows
|
|
;;
|
|
(with (movable nil savewindow nil spec nil)
|
|
(setq savewindow window)
|
|
(for window (list-of-windows 'window)
|
|
(if (not (vscreen.nailed))
|
|
(setq movable (+ movable (list window)))))
|
|
movable))
|
|
|
|
(defun vscreen.move-windows (deltax deltay)
|
|
;;
|
|
;; Moves a window by deltax and deltay adjusting vscreen.pos
|
|
;; appropriately
|
|
;;
|
|
(for window (vscreen.movable)
|
|
(move-window (+ window-x deltax) (+ window-y deltay)))
|
|
(with (x (# 0 vscreen.pos) y (# 1 vscreen.pos))
|
|
(setq vscreen.pos (list (+ x deltax) (+ y deltay)))))
|
|
|
|
(defun vscreen.move-windows-right ()
|
|
(vscreen.move-windows vscreen.right-left 0))
|
|
|
|
(defun vscreen.move-windows-left ()
|
|
(vscreen.move-windows (- vscreen.right-left) 0))
|
|
|
|
(defun vscreen.move-windows-down ()
|
|
(vscreen.move-windows 0 vscreen.down-up))
|
|
|
|
(defun vscreen.move-windows-up ()
|
|
(vscreen.move-windows 0 (- vscreen.down-up)))
|
|
|
|
(defun vscreen.restore ()
|
|
(vscreen.move-windows (- (# 0 vscreen.pos)) (- (# 1 vscreen.pos))))
|
|
|
|
(defun vscreen.make-window-visible ()
|
|
;;
|
|
;; Here we move the virtual screen around so that as much of the
|
|
;; current window is visible as possible. For example, if the top
|
|
;; of the window is lower than the bottom of the screen, move so
|
|
;; that the BOTTOM of that window is above the bottom of the screen.
|
|
;; The other transformations are analagous.
|
|
;;
|
|
;; dx and dy start of being the number of increments we will
|
|
;; move. We then scale them to pixels.
|
|
;;
|
|
(if (not (vscreen.nailed))
|
|
(with (dx 0 dy 0
|
|
window-top window-y
|
|
window-bot (+ window-y window-height)
|
|
window-left window-x
|
|
window-right (+ window-x window-width)
|
|
screen-top 0
|
|
screen-bot screen-height
|
|
screen-left 0
|
|
screen-right screen-width)
|
|
(if (le window-right screen-left)
|
|
(setq dx (ceildiv (- screen-left window-left)
|
|
vscreen.right-left)))
|
|
(if (ge window-left screen-right)
|
|
(setq dx (- (ceildiv (- window-right screen-right)
|
|
vscreen.right-left))))
|
|
(if (le window-bot screen-top)
|
|
(setq dy (ceildiv (- screen-top window-top)
|
|
vscreen.down-up)))
|
|
(if (ge window-top screen-bot)
|
|
(setq dy (- (ceildiv (- window-bot screen-bot)
|
|
vscreen.down-up))))
|
|
(setq dx (* dx vscreen.right-left))
|
|
(setq dy (* dy vscreen.down-up))
|
|
(vscreen.move-windows dx dy))))
|
|
|
|
|
|
|
|
(setq vscreen.pixsize 300)
|
|
|
|
(defun vscreen.min (x y)
|
|
(if (< x y)
|
|
x
|
|
y))
|
|
|
|
(defun vscreen.max (x y)
|
|
(if (> x y)
|
|
x
|
|
y))
|
|
|
|
(defun vscreen.calc-params ()
|
|
;;
|
|
;; Return a list that contains scale factor, x position of origin,
|
|
;; and y position of origin
|
|
;;
|
|
|
|
;;
|
|
;; First, we find x and y extremes. Initialize so that the current
|
|
;; will always be visible.
|
|
;;
|
|
|
|
(with (minx 0 miny 0 maxx screen-width maxy screen-height
|
|
xcenter nil ycenter nil
|
|
range nil scale nil x0 nil y0 nil
|
|
low (list-of-windows 'window 'mapped))
|
|
(for window (list-of-windows 'window 'mapped)
|
|
(setq minx (vscreen.min minx window-x))
|
|
(setq miny (vscreen.min miny window-y))
|
|
(setq maxx (vscreen.max maxx (+ window-x window-width)))
|
|
(setq maxy (vscreen.max maxy (+ window-y window-height))))
|
|
|
|
;;
|
|
;; Next, figure out the number of pixels to display.
|
|
;;
|
|
|
|
(setq range (vscreen.max (- maxy miny) (- maxx minx)))
|
|
|
|
(setq xcenter (/ (+ minx maxx) 2))
|
|
(setq ycenter (/ (+ miny maxy) 2))
|
|
|
|
;;
|
|
;; Our scale factor is a simple quotient. We divide by .9
|
|
;; times the number of pixels to leave some inner border in
|
|
;; our map window. To get the origin, figure out where 0,0
|
|
;; would be given that the center of the current screen should
|
|
;; be in the center.
|
|
;;
|
|
|
|
(setq scale (/ range (* 9 (/ vscreen.pixsize 10))))
|
|
(setq x0 (/ vscreen.pixsize 2))
|
|
(setq y0 (/ vscreen.pixsize 2))
|
|
(setq x0 (- x0 (/ xcenter scale)))
|
|
(setq y0 (- y0 (/ ycenter scale)))
|
|
(list scale x0 y0)))
|
|
|
|
(defun vscreen.draw-windows (pix params)
|
|
(with (foreground black)
|
|
(draw-line vscreen.pix (- (# 1 params) 5) (- (# 2 params) 5)
|
|
(+ (# 1 params) 5) (+ (# 2 params) 5))
|
|
(draw-line vscreen.pix (- (# 1 params) 5) (+ (# 2 params) 5)
|
|
(+ (# 1 params) 5) (- (# 2 params) 5))
|
|
(for window (list-of-windows 'window 'mapped)
|
|
(with (tlx (+ (/ window-x (# 0 params)) (# 1 params))
|
|
tly (+ (/ window-y (# 0 params)) (# 2 params))
|
|
trx (+ tlx (/ window-width (# 0 params)))
|
|
try tly
|
|
blx tlx
|
|
bly (+ tly (/ window-height (# 0 params)))
|
|
brx trx
|
|
bry bly)
|
|
(draw-line pix tlx tly trx try)
|
|
(draw-line pix trx try brx bry)
|
|
(draw-line pix brx bry blx bly)
|
|
(draw-line pix blx bly tlx tly)
|
|
))))
|
|
|
|
|
|
(defun vscreen.show-windows ()
|
|
(with (params (vscreen.calc-params))
|
|
(with (bar-max-width vscreen.pixsize
|
|
fsm vscreen-fsm)
|
|
(with (foreground white)
|
|
(setq vscreen.pix (pixmap-make 300 300)))
|
|
(vscreen.draw-windows vscreen.pix params)
|
|
(setq vscreen.pixmenu
|
|
(menu-make (bar-make (plug-make vscreen.pix))))
|
|
(place-menu "Vscreen" vscreen.pixmenu))))
|
|
|
|
;; Colas: here is a sample code to bind it to control-alt-arrows
|
|
;; define vscreen.no-bindings if you don't want these bindings before loading
|
|
;; vscreen
|
|
|
|
(if (not vscreen.no-bindings)
|
|
(progn
|
|
|
|
(setq vscreen-behavior (state-make
|
|
(on (keypress "Left" vscreen.modifiers)
|
|
(vscreen.move-windows-right)
|
|
)
|
|
(on (setq a (keypress "Right" vscreen.modifiers))
|
|
(vscreen.move-windows-left)
|
|
)
|
|
(on (keypress "Up" vscreen.modifiers)
|
|
(vscreen.move-windows-down)
|
|
)
|
|
(on (keypress "Down" vscreen.modifiers)
|
|
(vscreen.move-windows-up)
|
|
)
|
|
))
|
|
|
|
(setq standard-behavior (state-make
|
|
standard-behavior
|
|
vscreen-behavior
|
|
))
|
|
(setq root-behavior (state-make
|
|
root-behavior
|
|
vscreen-behavior
|
|
))
|
|
|
|
(setq vscreen-grabs (list
|
|
(key "Left" vscreen.modifiers)
|
|
(key "Right" vscreen.modifiers)
|
|
(key "Up" vscreen.modifiers)
|
|
(key "Down" vscreen.modifiers)
|
|
))
|
|
(setq root-grabs (+ root-grabs vscreen-grabs))
|
|
(setq window-grabs (+ window-grabs vscreen-grabs))
|
|
(setq icon-grabs (+ icon-grabs vscreen-grabs))
|
|
(reparse-standard-behaviors)
|
|
))
|
|
|
|
(setq vscreen-fsm
|
|
(fsm-make
|
|
(state-make
|
|
(on (buttonrelease 1 alone) (delete-window))
|
|
(on (buttonrelease 2 alone) (delete-window))
|
|
(on (buttonrelease 3 alone) (delete-window))
|
|
window-behavior
|
|
standard-behavior
|
|
)))
|
|
|
|
(setq vscreen-grabs (+ grabs (list (button any alone))))
|
|
|
|
|
|
(setq vscreen
|
|
(with (fsm vscreen-fsm menu 'window-pop
|
|
borderpixel black
|
|
borderwidth 3
|
|
property (+ property '(nailed t))
|
|
grabs vscreen-grabs)
|
|
(window-make () () () () ())))
|
|
|
|
;; add entries in the root & window menus
|
|
|
|
(if (not (boundp 'vscreen.menu-added)) (progn
|
|
(setq vscreen.menu-added t)
|
|
|
|
(insert-at '(multi-item-make
|
|
"VS" ()
|
|
("Show" (vscreen.show-windows))
|
|
("Restore" (vscreen.restore))
|
|
)
|
|
root-pop-items
|
|
vscreen.menupos
|
|
)
|
|
|
|
(insert-at '(multi-item-make
|
|
"VS"
|
|
()
|
|
("Un" (vscreen.un-nail))
|
|
("Nail" (vscreen.nail))
|
|
()
|
|
)
|
|
window-pop-items
|
|
vscreen.windowmenupos
|
|
)
|
|
))
|