branch: externals/exwm
commit d1be727e1e96621478a209b48f7cf293a8fb4344
Author: Steven Allen <[email protected]>
Commit: Steven Allen <[email protected]>

    Set floating mode-lines using window parameters
    
    Rather than mess with the global mode-line each time a window is made
    floating/tiling:
    
    1. Set the buffer-local `mode-line-format' variable to customize the
       tiling mode-line.
    
    2. Set the floating window's `mode-line-format' window-parameter to
       customize the floating mode-line.
    
    This brings us a step closer to being able to have X windows appear in
    multiple windows at the same time.
    
    Additionally, apply all the same logic to the header line.
    
    Unfortunately, this did make `exwm-layout-toggle-mode-line'
    significantly more complex as it now has to handle window-specific
    versus global mode-lines.
    
    * exwm-core.el (exwm--saved-mode-line-format): Rename to make it clear
    that this is a backup variable.
    * exwm-floating.el (exwm-floating--set-floating): Apply floating window
    decoration (mode/header-line) customizations via window parameters.
    (exwm-floating-toggle-floating): We no longer need to restore
    header/mode-line settings when switching from floating to tiling mode
    because they're attached to the window, not the buffer.
    * exwm-manage.el (exwm-manage--manage-window): Configure the tiling
    mode-line on manage because we no longer do this from
    `exwm-floating--unset-floating'.
    * exwm-layout.el (exwm-layout-show-mode-line):
    (exwm-layout-hide-mode-line): Replace body with calls to
    `exwm-layout-toggle-mode-line'.
    (exwm-layout--toggle-mode-line-1): A new macro to abstract over
    configuring window-specific versus global mode-lines.
    (exwm-layout--window-specific-mode-line):
    (exwm-layout--mode-line): New helper functions.
    (exwm-layout-toggle-mode-line): Refactor to hide/show the
    window-specific (via window parameters) mode-line or the buffer-local
    mode-line, depending on whether or not the window has a window-specific
    mode-line format.
---
 exwm-core.el     |   2 +-
 exwm-floating.el |  40 +++++--------------
 exwm-layout.el   | 119 +++++++++++++++++++++++++++++++++++++++----------------
 exwm-manage.el   |   5 +++
 4 files changed, 101 insertions(+), 65 deletions(-)

diff --git a/exwm-core.el b/exwm-core.el
index 4e0e518576..627db1468c 100644
--- a/exwm-core.el
+++ b/exwm-core.el
@@ -273,7 +273,7 @@ If CONN is non-nil, use it instead of the value of the 
variable
 (defvar-local exwm--configurations nil)   ;initial configurations.
 (defvar-local exwm--frame nil)            ;workspace frame
 (defvar-local exwm--floating-frame nil)   ;floating frame
-(defvar-local exwm--mode-line-format nil) ;save mode-line-format
+(defvar-local exwm--saved-mode-line-format nil) ;save mode-line-format
 (defvar-local exwm--floating-frame-geometry nil) ;set when hidden.
 (defvar-local exwm--fixed-size nil)              ;fixed size
 (defvar-local exwm--selected-input-mode 'line-mode
diff --git a/exwm-floating.el b/exwm-floating.el
index 05a3166673..302a8d75a1 100644
--- a/exwm-floating.el
+++ b/exwm-floating.el
@@ -212,24 +212,15 @@ configured dimension is invalid."
             exwm--floating-frame frame)
 
       ;; Adjust the header & mode line before calculating sizes.
-      (if-let* ((floating-mode-line (plist-get exwm--configurations
-                                               'floating-mode-line)))
-          (setq exwm--mode-line-format (or exwm--mode-line-format
-                                           mode-line-format)
-                mode-line-format floating-mode-line)
-        (if (and (not (plist-member exwm--configurations 'floating-mode-line))
-                 exwm--mwm-hints-decorations)
-            (when exwm--mode-line-format
-              (setq mode-line-format exwm--mode-line-format))
-          ;; The mode-line need to be hidden in floating mode.
-          (setq exwm--mode-line-format (or exwm--mode-line-format
-                                           mode-line-format)
-                mode-line-format nil)))
-      (if-let* ((floating-header-line (plist-get exwm--configurations
-                                                 'floating-header-line)))
-          (setq header-line-format floating-header-line)
-        ;; The header-line need to be hidden in floating mode.
-        (setq header-line-format nil))
+      (pcase-dolist (`(,prop . ,setting) '((mode-line-format . 
floating-mode-line)
+                                           (header-line-format . 
floating-header-line)))
+        (cond
+         ((plist-member exwm--configurations setting)
+          (set-window-parameter
+           window prop
+           (or (plist-get exwm--configurations setting) 'none)))
+         ((not exwm--mwm-hints-decorations)
+          (set-window-parameter window prop 'none))))
 
       ;; We MUST redisplay with the frame visible here in order to correctly 
calculate the sizes.
       (redisplay)
@@ -413,18 +404,7 @@ configured dimension is invalid."
           (delete-frame exwm--floating-frame))))
     (with-current-buffer buffer
       (setq window-size-fixed nil
-            exwm--floating-frame nil)
-      (if (not (plist-member exwm--configurations 'tiling-mode-line))
-          (when exwm--mode-line-format
-            (setq mode-line-format exwm--mode-line-format))
-        (setq exwm--mode-line-format (or exwm--mode-line-format
-                                         mode-line-format)
-              mode-line-format (plist-get exwm--configurations
-                                          'tiling-mode-line)))
-      (if (not (plist-member exwm--configurations 'tiling-header-line))
-          (setq header-line-format nil)
-        (setq header-line-format (plist-get exwm--configurations
-                                            'tiling-header-line))))
+            exwm--floating-frame nil))
     ;; Only show X windows in normal state.
     (unless (exwm-layout--iconic-state-p)
       (pop-to-buffer-same-window buffer)))
diff --git a/exwm-layout.el b/exwm-layout.el
index de5294989d..229d80147e 100644
--- a/exwm-layout.el
+++ b/exwm-layout.el
@@ -542,47 +542,98 @@ See also `exwm-layout-enlarge-window'."
      (elt (exwm--window-inside-pixel-edges ) 3)))
 
 (defun exwm-layout-hide-mode-line ()
-  "Hide mode-line."
+  "Hide the mode-line.
+See `exwm-layout-toggle-mode-line' for more details."
   (interactive)
   (exwm--log)
-  (when (and (derived-mode-p 'exwm-mode) mode-line-format)
-    (if exwm--floating-frame
-        (let* ((window (frame-first-window exwm--floating-frame))
-               (old-bottom-offset (exwm-layout--window-bottom-offset window)))
-          (setq exwm--mode-line-format mode-line-format
-                mode-line-format nil)
-          (exwm-layout-enlarge-window
-           (- (exwm-layout--window-bottom-offset window) old-bottom-offset)))
-      (setq exwm--mode-line-format mode-line-format
-            mode-line-format nil)
-      (exwm-layout--show exwm--id))))
+  (exwm-layout-toggle-mode-line -1))
 
 (defun exwm-layout-show-mode-line ()
-  "Show mode-line."
+  "Show the mode-line.
+See `exwm-layout-toggle-mode-line' for more details."
   (interactive)
   (exwm--log)
-  (when (and (derived-mode-p 'exwm-mode) (not mode-line-format))
-    (if exwm--floating-frame
-        (let* ((window (frame-first-window exwm--floating-frame))
-               (old-bottom-offset (exwm-layout--window-bottom-offset window)))
-          (setq mode-line-format exwm--mode-line-format
-                exwm--mode-line-format nil)
-          (exwm-layout-enlarge-window
-           (- (exwm-layout--window-bottom-offset window) old-bottom-offset))
-          (call-interactively #'exwm-input-grab-keyboard))
-      (setq mode-line-format exwm--mode-line-format
-            exwm--mode-line-format nil)
-      (exwm-layout--show exwm--id))
-    (force-mode-line-update)))
-
-(defun exwm-layout-toggle-mode-line ()
-  "Toggle the display of mode-line."
-  (interactive)
+  (exwm-layout-toggle-mode-line 1))
+
+;; You can do this with by let-binding places with `gv-ref' and
+;; `gv-deref' instead of a macro, but the macro is cleaner.
+(defmacro exwm-layout--toggle-mode-line-1
+    (hide active-place saved-place none)
+  "Macro implementing the core logic behind mode-line toggling.
+
+If HIDE, the modeline is hidden. Otherwise, it is shown.
+
+ACTIVE-PLACE is the generalized variable where the active mode-line
+is stored.
+
+SAVED-PLACE is the generalized variable where the saved mode-line is
+stored when hidden.
+
+NONE is the symbol stored in ACTIVE-PLACE to hide the mode-line."
+  `(if ,hide
+       (ignore (cl-shiftf ,saved-place ,active-place ',none))
+     (setf ,active-place (or (cl-shiftf ,saved-place nil)
+                          mode-line-format
+                          (default-value 'mode-line-format)
+                          (error "No sane mode-line to show")))))
+
+(defsubst exwm-layout--window-specific-mode-line (window)
+  "Return non-nil if WINDOW has a WINDOW-specific mode-line."
+  (or (window-parameter window 'mode-line-format)
+      (window-parameter window 'exwm--saved-mode-line-format)))
+
+(defsubst exwm-layout--mode-line (&optional window)
+  "Return the effective mode-line for WINDOW or the current buffer.
+Return nil if the buffer/window has no mode-line."
+  (pcase (and window (window-parameter window 'mode-line-format))
+    ('none nil)
+    ('nil mode-line-format)
+    (wml wml)))
+
+(defun exwm-layout-toggle-mode-line (&optional arg)
+  "Toggle the display of mode-line.
+
+If ARG is a positive number, show the mode-line.
+If ARG is a negative number, hide the mode-line.
+Otherwise, toggle the mode-line.
+
+If the mode-line format is specific to the current window (e.g., an
+undecorated floating window), the mode-line is toggled in that window
+only. Otherwise, it's toggled globally."
+  (interactive (list (and current-prefix-arg
+                          (prefix-numeric-value current-prefix-arg))))
   (exwm--log)
-  (when (derived-mode-p 'exwm-mode)
-    (if mode-line-format
-        (exwm-layout-hide-mode-line)
-      (exwm-layout-show-mode-line))))
+  (let* ((target-window
+          (cond (exwm--floating-frame
+                 (frame-first-window exwm--floating-frame))
+                ((eq (window-buffer) (current-buffer))
+                 (selected-window))))
+         (is-visible
+          (not (null (exwm-layout--mode-line target-window)))))
+    (when (or (not (numberp arg)) (eq (< arg 0) is-visible))
+      (let ((old-bottom-offset
+             (and exwm--floating-frame
+                  target-window
+                  (exwm-layout--window-bottom-offset target-window))))
+        (if (and target-window
+                 (exwm-layout--window-specific-mode-line target-window))
+            (exwm-layout--toggle-mode-line-1
+             is-visible
+             (window-parameter target-window
+                               'mode-line-format)
+             (window-parameter target-window
+                               'exwm--saved-mode-line-format)
+             none)
+          (exwm-layout--toggle-mode-line-1
+           is-visible
+           mode-line-format
+           exwm--saved-mode-line-format
+           nil))
+        (when old-bottom-offset
+          (exwm-layout-enlarge-window
+           (- (exwm-layout--window-bottom-offset target-window)
+              old-bottom-offset))))
+      (force-mode-line-update))))
 
 (defun exwm-layout--init ()
   "Initialize layout module."
diff --git a/exwm-manage.el b/exwm-manage.el
index cccf9fedaf..674fc4f5c3 100644
--- a/exwm-manage.el
+++ b/exwm-manage.el
@@ -343,6 +343,11 @@ This only works when procfs is mounted, which may not be 
the case on some BSDs."
                                ;; UnmapNotify/DestroyNotify event of the dock.
                                (exwm--get-client-event-mask)
                              xcb:EventMask:NoEvent)))
+        ;; Configure the tiling mode-line & header-line
+        (pcase-dolist (`(,var . ,setting) '((mode-line-format . 
tiling-mode-line)
+                                            (header-line-format . 
tiling-header-line)))
+          (when (plist-member exwm--configurations setting)
+            (set var (plist-get exwm--configurations setting))))
         ;; The window needs to be mapped
         (xcb:+request exwm--connection
             (make-instance 'xcb:MapWindow :window id))

Reply via email to