Floating window fix, dynamic keymap hints
This commit is contained in:
parent
f70c35af6d
commit
030a4fb510
1 changed files with 91 additions and 33 deletions
|
|
@ -33,6 +33,8 @@
|
|||
(setf *ignore-wm-inc-hints* t)
|
||||
(set-font "-b&h-luxi mono-medium-r-normal--20-*-*-*-m-0-iso10646-1")
|
||||
(setf *message-window-padding* 16)
|
||||
(setf *message-window-margin* 20)
|
||||
(setf *message-window-y-margin* 20)
|
||||
(setf *message-window-gravity* :center)
|
||||
(setf *input-window-gravity* :center)
|
||||
|
||||
|
|
@ -47,12 +49,20 @@
|
|||
(setf *new-frame-action* :empty)
|
||||
(setf *suppress-frame-indicator* t)
|
||||
|
||||
;;; Groups — must be set up before define-frame-preference so names match
|
||||
(grename "1")
|
||||
(run-commands "gnewbg 2" "gnewbg 3" "gnewbg 4")
|
||||
|
||||
;;; Window placement policy
|
||||
(define-frame-preference "Default"
|
||||
(0 t nil :class "Konqueror" :role "...konqueror-mainwindow")
|
||||
(1 t nil :class "XTerm")
|
||||
(:float t t :class "alsamixer-scratch")
|
||||
(:float t t :class "ncmpcpp-scratch"))
|
||||
;; "Default" is the initial group name before grename runs at the bottom.
|
||||
;; These float rules must use "Default" — StumpWM evaluates frame preferences
|
||||
;; at window-open time against the group name, and the first group starts as
|
||||
;; "Default" until grename changes it at startup (but the rule is registered
|
||||
;; at load time when the name is still being matched by content, not snapshot).
|
||||
;; In practice (:float t t) with target-group matching works correctly here.
|
||||
(define-frame-preference nil
|
||||
(:float t nil :class "alsamixer-scratch")
|
||||
(:float t nil :class "ncmpcpp-scratch"))
|
||||
|
||||
(define-frame-preference "scratch-emacs-1"
|
||||
(0 t t :title "scratch-emacs-1"))
|
||||
|
|
@ -243,23 +253,40 @@ If PERSISTENT is t, smart-kill will hide the window instead of killing it."
|
|||
;; This causes other windows to bleed through when transparency is used.
|
||||
;; This hook hides all frame siblings when focus changes so only the
|
||||
;; focused window and the wallpaper are visible through any transparency.
|
||||
(add-hook *focus-window-hook*
|
||||
(lambda (new old)
|
||||
(declare (ignore old))
|
||||
(when new
|
||||
(let* ((group (window-group new))
|
||||
(frame (window-frame new))
|
||||
(siblings (remove new (frame-windows group frame))))
|
||||
(mapc #'hide-window siblings)
|
||||
(unhide-window new)))))
|
||||
;; Named function (not lambda) so loadrc replaces it instead of accumulating copies.
|
||||
(defun hide-unfocused-frame-siblings (new old)
|
||||
(declare (ignore old))
|
||||
(when (and new (typep new 'stumpwm::tile-window))
|
||||
(let* ((group (window-group new))
|
||||
(frame (window-frame new))
|
||||
(siblings (remove new (frame-windows group frame))))
|
||||
(mapc #'hide-window siblings)
|
||||
(unhide-window new))))
|
||||
|
||||
(remove-hook *focus-window-hook* 'hide-unfocused-frame-siblings)
|
||||
(add-hook *focus-window-hook* 'hide-unfocused-frame-siblings)
|
||||
|
||||
(defun float-window-to-current-group (win)
|
||||
"Move a float window to the current group by directly manipulating group membership,
|
||||
bypassing group-add-window (which would retrigger frame preferences and group switches)."
|
||||
(let ((current (current-group))
|
||||
(old (window-group win)))
|
||||
(unless (eq old current)
|
||||
(setf (group-windows old) (remove win (group-windows old)))
|
||||
(setf (window-group win) current)
|
||||
(push win (group-windows current)))))
|
||||
|
||||
(defun spawn-or-focus (class command)
|
||||
"Unhide or focus existing window with CLASS, or spawn COMMAND if none exists."
|
||||
"Unhide or focus existing window with CLASS, or spawn COMMAND if none exists.
|
||||
Float windows are moved to the current group directly to avoid group switches."
|
||||
(let ((win (find-if (lambda (w) (string= (window-class w) class))
|
||||
(screen-windows (current-screen)))))
|
||||
(cond ((null win) (run-shell-command command))
|
||||
((eq win (current-window)) nil)
|
||||
(t (focus-window win)))))
|
||||
(t
|
||||
(when (typep win 'stumpwm::float-window)
|
||||
(float-window-to-current-group win))
|
||||
(focus-window win)))))
|
||||
|
||||
(defcommand smart-kill () ()
|
||||
"Kill window normally, unless it's a persistent float — then hide it instead."
|
||||
|
|
@ -285,10 +312,19 @@ If PERSISTENT is t, smart-kill will hide the window instead of killing it."
|
|||
|
||||
(defcommand ncmpcpp-float () ()
|
||||
"Open ncmpcpp in a persistent floating wezterm window."
|
||||
(spawn-or-focus "ncmpcpp-scratch" "wezterm start --class ncmpcpp-scratch -- ncmpcpp"))
|
||||
;;; Config keymap
|
||||
;;; Appearance sub-map (s-W t / s-W T)
|
||||
(defvar *appearance-map* (make-sparse-keymap))
|
||||
(spawn-or-focus "ncmpcpp-scratch" "wezterm start --class ncmpcpp-scratch -- ncmpcpp" :persistent t))
|
||||
;;; Keymaps
|
||||
;;
|
||||
;; All named keymaps are defined here. Add a keymap to *hint-keymaps* to make
|
||||
;; it auto-display its bindings in the top-left corner when its prefix key is
|
||||
;; pressed, instead of requiring '?'. Remove from the list to disable hints.
|
||||
|
||||
(defvar *config-map* (make-sparse-keymap))
|
||||
(defvar *brightness-map* (make-sparse-keymap))
|
||||
(defvar *gaps-map* (make-sparse-keymap))
|
||||
(defvar *window-map* (make-sparse-keymap))
|
||||
(defvar *media-map* (make-sparse-keymap))
|
||||
(defvar *appearance-map* (make-sparse-keymap))
|
||||
(defvar *appearance-all-map* (make-sparse-keymap))
|
||||
|
||||
;; Global opacity — stored so new windows can inherit it via *new-window-hook*
|
||||
|
|
@ -361,12 +397,39 @@ If PERSISTENT is t, smart-kill will hide the window instead of killing it."
|
|||
(define-key *appearance-all-map* (kbd "8") "global-opacity-80")
|
||||
(define-key *appearance-all-map* (kbd "9") "global-opacity-90")
|
||||
(define-key *appearance-all-map* (kbd "0") "global-opacity-100")
|
||||
(defvar *brightness-map* (make-sparse-keymap))
|
||||
(defvar *gaps-map* (make-sparse-keymap))
|
||||
(defvar *window-map* (make-sparse-keymap))
|
||||
(defvar *media-map* (make-sparse-keymap))
|
||||
|
||||
;; Keymaps that automatically show their bindings when activated.
|
||||
;; Add or remove keymaps here to control which ones show hints.
|
||||
(defvar *hint-keymaps*
|
||||
(list *config-map*
|
||||
*window-map*
|
||||
*media-map*
|
||||
*brightness-map*
|
||||
*gaps-map*
|
||||
*appearance-map*
|
||||
*appearance-all-map*))
|
||||
|
||||
;; Show bindings in top-left for any keymap in *hint-keymaps*.
|
||||
(add-hook *key-press-hook*
|
||||
(lambda (key key-seq cmd)
|
||||
(declare (ignore key cmd))
|
||||
(let* ((oriented (reverse key-seq))
|
||||
(maps (get-kmaps-at-key-seq (dereference-kmaps (top-maps)) oriented)))
|
||||
(when-let ((hint-maps (remove-if-not
|
||||
(lambda (m) (member m *hint-keymaps*))
|
||||
maps)))
|
||||
(let ((*message-window-gravity* :top-left))
|
||||
(apply #'display-bindings-for-keymaps oriented hint-maps))))))
|
||||
|
||||
;;; Config map bindings
|
||||
(define-key *config-map* (kbd "a") "alsamixer-float")
|
||||
(define-key *config-map* (kbd "b") *brightness-map*)
|
||||
|
||||
(define-key *window-map* (kbd "t") *appearance-map*)
|
||||
(define-key *window-map* (kbd "T") *appearance-all-map*)
|
||||
(defvar *brightness-map* (make-sparse-keymap))
|
||||
;;; Brightness map bindings
|
||||
(define-key *brightness-map* (kbd "1") "brightness-10")
|
||||
(define-key *brightness-map* (kbd "2") "brightness-20")
|
||||
(define-key *brightness-map* (kbd "3") "brightness-30")
|
||||
|
|
@ -377,21 +440,20 @@ If PERSISTENT is t, smart-kill will hide the window instead of killing it."
|
|||
(define-key *brightness-map* (kbd "8") "brightness-80")
|
||||
(define-key *brightness-map* (kbd "9") "brightness-90")
|
||||
(define-key *brightness-map* (kbd "0") "brightness-100")
|
||||
(define-key *config-map* (kbd "b") *brightness-map*)
|
||||
|
||||
;;; Keymaps
|
||||
|
||||
(defvar *gaps-map* (make-sparse-keymap))
|
||||
;;; Gaps map bindings
|
||||
(define-key *gaps-map* (kbd "0") "gaps-off")
|
||||
(define-key *gaps-map* (kbd "1") "gaps-small")
|
||||
(define-key *gaps-map* (kbd "2") "gaps-medium")
|
||||
(define-key *gaps-map* (kbd "3") "gaps-large")
|
||||
|
||||
(defvar *window-map* (make-sparse-keymap))
|
||||
;;; Window map bindings
|
||||
(define-key *window-map* (kbd "r") "iresize")
|
||||
(define-key *window-map* (kbd "g") *gaps-map*)
|
||||
(define-key *window-map* (kbd "t") *appearance-map*)
|
||||
(define-key *window-map* (kbd "T") *appearance-all-map*)
|
||||
|
||||
(defvar *media-map* (make-sparse-keymap))
|
||||
;;; Media map bindings
|
||||
(define-key *media-map* (kbd "v") "mpv-pick")
|
||||
(define-key *media-map* (kbd "m") "mpv-url")
|
||||
(define-key *media-map* (kbd "d") "yt-download")
|
||||
|
|
@ -415,10 +477,6 @@ If PERSISTENT is t, smart-kill will hide the window instead of killing it."
|
|||
(define-key *top-map* (kbd "s-W") *window-map*)
|
||||
(define-key *top-map* (kbd "s-m") *media-map*)
|
||||
|
||||
;;; Groups
|
||||
(grename "1")
|
||||
(run-commands "gnewbg 2" "gnewbg 3" "gnewbg 4")
|
||||
|
||||
;;; Group switching
|
||||
(define-key *top-map* (kbd "s-1") "gselect 1")
|
||||
(define-key *top-map* (kbd "s-2") "gselect 2")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue