This extension stumpwm-dynamic-float
provides StumpWM users a
(gapped) dynamic tiling experience based on its floating windows.
Watch the demo videos to immediately grasp what it does.
- Have a working stumpwm on your machine.
- If you use
quicklisp
, download the repo into your quicklisp local directory. To check if it would work properly, with quicklisp loaded in your CL implementation, load the system by(ql:quickload :stumpwm-dynamic-float)
. Finally, if it works out well, add that form into your StumpWM init config. - To start enjoying
stumpwm-dynamic-float
, see the configuration example below.
Commonly used commands defined in stumpwm-dynamic-float
are
included in this configuration example.
;; Navigation
(define-key *top-map* (kbd "s-j") "window-focus-next")
(define-key *top-map* (kbd "s-k") "window-focus-prev")
(define-key *top-map* (kbd "s-J") "permute-window")
(define-key *top-map* (kbd "s-K") "permute-window-reverse")
;; Master Ratio
(define-key *top-map* (kbd "s-+") "master-ratio-increase")
(define-key *top-map* (kbd "s--") "master-ratio-decrease")
(define-key *top-map* (kbd "s-=") "master-ratio-set-default")
;; Layout Selection
(define-key *top-map* (kbd "s-f") "layout-toggle-fullscreen")
(define-key *top-map* (kbd "s-F") "layout-change-next")
;; Gaps
(define-key *top-map* (kbd "s-[") "gap-toggle")
(define-key *top-map* (kbd "s-]") "gap-set-default")
(define-key *top-map* (kbd "s-}") "gap-increase")
(define-key *top-map* (kbd "s-{") "gap-decrease")
;; Window Status: 'tiled, 'foreground, 'background.
(define-key *top-map* (kbd "s-_") "window-status-tile-at-point")
(define-key *top-map* (kbd "s-|") "window-status-make-all-tiled")
I put the following code in my StumpWM config so whenever it starts it create 10 dynamic floating windows for me, named 0 to 9.
;; Groups creation
(grename "1")
(loop for n in '(2 3 4 5 6 7 8 9 0)
do (stumpwm-dynamic-float:gnew-dyn-float-bg (format nil "~a" n)))
(gkill)
(stumpwm-dynamic-float:gnew-dyn-float "1")
To bind group-navigation and window-throwing in batch, use the following code.
(in-package :stumpwm)
;; Keybindings for selecting and navigating among groups.
;; E.g. =super-3= navigates to the third group, while =super-#=
;; throws the current window at point to the third group.
(mapcar (lambda (n)
(define-key *top-map*
(kbd (format nil "s-~a" n))
(format nil "gselect ~a" n))
(let ((shift-keys '(")" "!" "@" "#" "$"
"%" "^" "&" "*" "(")))
(define-key *top-map*
(kbd (format nil "s-~a" (nth n shift-keys)))
(format nil "gmove ~a" n))))
'(1 2 3 4 5 6 7 8 9 0))
By default, this extension tiles every new window introduced into
the group. To alter this behavior, add a customized hook into the
variable *new-window-spec-hooks*
. For example, the following code
forces any new window with title starting from "[TOP]"
to have
the spec specified in the car of the cons.
(push (cons (lambda (w) (equal 0 (search "[TOP]" (window-title w))))
(list ;; :x 300 :y 300 :height 300 :width 300
:status 'foreground))
stumpwm-dynamic-float:*new-window-spec-hooks*)
Remark. Probably it is a better approach to use stumpwm’s window class and hooks to alter the behavior of certain new windows. Please let me know if you figure out how to do so.
Currently, supported layouts are '(left-vertical horizontal
fullscreen)
. To define your own, check out their source codes and
the macro #'deflayout
. The simplest example is 'fullscreen
:
(deflayout fullscreen
"A layout where every tiled windows are fully expanded."
(list :x x0 :y y0 :width sw :height sh))
The macro defines a function #'fullscreen
, which will be called
to calculate the desired values (:x :y :width :height)
of the
floating windows that are supposed to be tiled. Then something
else use this calculated information to redraw the window. See
'left-vertical
for a more complicated example (but not too bad).
Each dyn-float-group
keeps a private list of data called
dfg-data
. Each dfg-datum
corresponds to a floating window
internal to stumpwm. Whenever a window is added, removed, or
dragged, #'sync!
updates the dfg-data
(see group-add-window
,
group-delete-window
, and group-button-press
).
A layout is implemented as a pure function that computes the
values (x, y, width, height
) of the kth window among the N-many
windows that are supposed to be tiled. The dynamic tiling
functionality is enforced by #'apply-data!
, in which
#'stumpwm::float-window-move-resize
redraws the windows based the
current layout of the group.
- Use emacs to replace
dmenu
,rofi
, andnotify-send
.
- Only tested on SBCL.
- Any feedback is welcome (especially lisp-fu related).