Sv: Spatial organization of windows in StumpWM
Shostek <[email protected]> Mon, 7 Mar 2022 21:00:37 +0000 (UTC)
| Newsgroups | gmane.comp.window-managers.stumpwm.devel |
|---|---|
| Message-ID | <[email protected]> |
This is phenomenal! I didn't grok it when you explained on irc but the video demo made perfect sense. I think this would make an very powerful contribution to StumpWM, if not in the core than as a module. The video is also really well put together, and demonstrates the true power of stump. If you feel like it, I think it would be quite publishable. If you'd like feedback or constructive criticism I would be happy to give it when I have some time. Now please excuse me while I add all of this code to my stumpwmrc while waiting for it to be formally published :). 7. mar. 2022 20:12:03 Russell Adams <[email protected]>: > I composed a short video about using spatial groups in StumpWM to > share. I've tried to explain the idea of spatial grouping before on > IRC, and I felt a demonstration would be clearer. > > http://demosthenes.org/tmp/StumpWMSpatialGroups.mp4 > > Please pardon the rough edges. I'm not starting a Youtube channel, > just trying to have a conversation about how to manage windows and > groups in Stump. > > Spatial grouping abuses Stump's ability to dynamically create groups > to create a sparse 3d array of groups, visualized as multiple desktops > of a 2d grid of screens. Hotkeys use arrows to navigate the grid and > swap desktops in a way which emulates a larger physical screen > surface. > > Using this method allows me to group windows by project, adjacent to > each other. This allows absolute navigation to each window, as opposed > to relative navigation (ie: alt-tab). > > I'm not grouping related application windows on the same screen, but > rather organizing patterns of groups to keep related application > windows cognitively near each other. I still may use splits and tile > windows within a screen, but not as often. > > I'm hoping to inspire further discussion on the matter. Critically, I > have not tested multiple monitor support. > > Concepts: > Spatial groups use a 3d coordinate system: “x,y,z” > Valid groups are “0,0,0”, “-1,2,0”, etc. > Z is used as the desktop index > > Keys: > Control-Shift-{Left,Right}: Change desktop (Z axis) > Control-Arrows: Navigate virtual screens on current desktop > Control-Shift-Up: Return to 0,0 on current desktop (Z) > Shift-Arrows: Navigate splits on current screen group > > Relevant code: > > ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; > > (ql:quickload 'cl-ppcre) > > (in-package :stumpwm) > > ;; change the prefix key to something else > (set-prefix-key (kbd "s-.")) > > ;; fix scroll wheel? > (setf (getenv "GDK_CORE_DEVICE_EVENTS") "1") > > ;; early define global vars > (defparameter *z-cursors* '() > "Association list of groups by Z coordinate for preserving last position on that plane.") > > (defparameter *last-cursor* NIL > "Previous group for popping back.") > > ;; Change focus > (set-focus-color "darkblue") ;; Set the border around the current frame > (setf *suppress-frame-indicator* t) ;; Stop the popup on the current frame > > ;; Modeline settings > (enable-mode-line (current-screen) (current-head) t) > (setf *mode-line-timeout* 60) > (setf *screen-mode-line-format* (list "[^B%n^b] %d |" "| %W")) > > ;; Shift arrows between adjacent windows > (define-key *top-map* (kbd "S-Up") "move-focus up") > (define-key *top-map* (kbd "S-Down") "move-focus down") > (define-key *top-map* (kbd "S-Left") "move-focus left") > (define-key *top-map* (kbd "S-Right") "move-focus right") > > ;; Control arrows between groups > (defcommand coord-left () () (coord-group-change -1 0 0)) > (defcommand coord-right () () (coord-group-change 1 0 0)) > (defcommand coord-up () () (coord-group-change 0 1 0)) > (defcommand coord-down () () (coord-group-change 0 -1 0)) > (defcommand coord-taskleft () () (coord-group-change 0 0 -1)) > (defcommand coord-taskright () () (coord-group-change 0 0 1)) > > ;; return to 0,0 on the current taskplane as a shortcut to return to the core task > (defcommand coord-taskorigin () () > (gselect > (group-name > (my-find-group (current-screen) > (format nil "~{~a~^,~}" (list 0 0 (parse-integer (third (cl-ppcre:split "," (group-name (current-group))))))))))) > > ;; pop back to last location > (defcommand coord-taskpop () () (when *last-cursor* (my-gselect *last-cursor*))) > > (define-key *top-map* (kbd "C-Left") "coord-left") > (define-key *top-map* (kbd "C-Right") "coord-right") > (define-key *top-map* (kbd "C-Up") "coord-up") > (define-key *top-map* (kbd "C-Down") "coord-down") > (define-key *top-map* (kbd "C-S-Left") "coord-taskleft") > (define-key *top-map* (kbd "C-S-Right") "coord-taskright") > (define-key *top-map* (kbd "C-S-Up") "coord-taskorigin") > (define-key *top-map* (kbd "C-S-Down") "coord-taskpop") > > (define-key *top-map* (kbd "s-S-SPC") "fullscreen") > > > ;; Groups will manage the coordinate system > ;; format: 0,0,0 with positive and negative numbers > ;; create groups on the fly as needed > ;; only supports one screen atm, would like multimonitor support later > > (gnew "0,0,0") ; create origin on startup > > (defun my-find-group (screen name) > (find name (screen-groups screen) :key 'group-name :test 'string=)) > > (defun my-gselect (name) > "Preserve prior location for pop, and handle when group is new" > (banish) > (setf *last-cursor* (group-name (current-group))) > (gselect (group-name > (or (my-find-group (current-screen) name) > (gnew name))))) > > (defun coord-group-change (xo yo zo) > "Navigate a 3d array of groups using x,y,z coordinates by passing the offset of the change." > (let* ((current-coords > (mapcar #'parse-integer > (cl-ppcre:split "," (group-name (current-group))))) > (new-coords (mapcar #'+ current-coords (list xo yo zo))) > (new-group-name (format nil "~{~a~^,~}" new-coords)) ) > > (if (= 0 zo) > > ;; Not changing taskplanes, so just move by coordinates > (my-gselect new-group-name) > > ;; Changing Z across taskplanes, RESTORE z-cursor for that plane > (let ((old-z (third current-coords)) > (new-z (third new-coords))) > > (if (assoc old-z *z-cursors*) > (setf (cdr (assoc old-z *z-cursors*)) (current-group)) > (push (cons old-z (current-group)) *z-cursors*)) > > (let ((z-cursor (cdr (or (assoc new-z *z-cursors*) '(nil . nil))))) > (if z-cursor > ;; Restore saved location > (my-gselect (group-name z-cursor)) > ;; create new taskplane > (my-gselect new-group-name))))))) > > (defun my-startup () (my-gselect "0,0,0")) > > (when *initializing* (my-startup)) > > > > > ------------------------------------------------------------------ > Russell Adams [email protected] > > PGP Key ID: 0x1160DCB3 http://www.adamsinfoserv.com/ > > Fingerprint: 1723 D8CA 4280 1EC9 557F 66E8 1154 E018 1160 DCB3