Skip to content

Commit a278dab

Browse files
committed
exwm-manage: Refactor the ConfigureRequest handler
I found this function very difficult to reason about with some very complicated conditionals (with SIDE EFFECTS in the COND forms!). While fixing that, I also: 1. Removed the Chesterton fence (minimum height/width delta) because Chesterton (Chris Feng) didn't leave a note saying why they exist and is no longer around to answer questions. As far as I can tell, Emacs can handle single-pixel resizes just fine. Maybe this was a pre-native-compilation performance optimization? The FIXME said to make these values as small as possible, so I simply followed those instructions and set them to zero. 2. Fixed handling of fullscreen windows on secondary monitors. Previously, this code used x/y/width/height as the EDGES of fullscreen windows, which is only correct for windows where x and y are zero. 3. Actually obeyed the value-mask when setting the geometry of floating windows instead of (potentially) using garbage values. * exwm-manage.el (exwm-manage--height-delta-min): (exwm-manage--width-delta-min): Remove minimum height/width deltas. (exwm-manage--send-ConfigureNotify): Add a helper function to notify windows that they've been reconfigured. (exwm-manage--on-ConfigureRequest): Rewrite.
1 parent c891d6a commit a278dab

File tree

1 file changed

+75
-87
lines changed

1 file changed

+75
-87
lines changed

exwm-manage.el

Lines changed: 75 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,6 @@ want to match against EXWM internal variables such as `exwm-title',
135135
(cons match config)))
136136
value))))
137137

138-
;; FIXME: Make the following values as small as possible.
139-
(defconst exwm-manage--height-delta-min 5)
140-
(defconst exwm-manage--width-delta-min 5)
141-
142138
;; The _MOTIF_WM_HINTS atom (see <Xm/MwmUtil.h> for more details)
143139
;; It's currently only used in 'exwm-manage' module
144140
(defvar exwm-manage--_MOTIF_WM_HINTS nil "_MOTIF_WM_HINTS atom.")
@@ -660,94 +656,86 @@ FRAME is the frame to be deleted."
660656
(delq (string-to-number (frame-parameter frame 'outer-window-id))
661657
exwm-manage--frame-outer-id-list))))
662658

659+
(defun exwm-manage--send-ConfigureNotify (window x y width height)
660+
"Send a ConfigureNotify event to WINDOW with X Y WIDTH and HEIGHT."
661+
(exwm--log "Reply with ConfigureNotify: %dx%d+%d+%d" width height x y)
662+
(xcb:+request exwm--connection
663+
(make-instance 'xcb:SendEvent
664+
:propagate 0 :destination window
665+
:event-mask xcb:EventMask:StructureNotify
666+
:event (xcb:marshal
667+
(make-instance
668+
'xcb:ConfigureNotify
669+
:event window :window window
670+
:above-sibling xcb:Window:None
671+
:x x :y y
672+
:width width
673+
:height height
674+
:border-width 0 :override-redirect 0)
675+
exwm--connection))))
676+
663677
(defun exwm-manage--on-ConfigureRequest (data _synthetic)
664678
"Handle ConfigureRequest event.
665679
DATA contains unmarshalled ConfigureRequest event data."
666680
(exwm--log)
667-
(let ((obj (xcb:unmarshal-new 'xcb:ConfigureRequest data))
668-
buffer edges width-delta height-delta)
669-
(with-slots (window x y width height
670-
border-width sibling stack-mode value-mask)
671-
obj
672-
(exwm--log "#x%x (#x%x) @%dx%d%+d%+d; \
681+
(with-slots (window x y width height
682+
border-width sibling stack-mode value-mask)
683+
(xcb:unmarshal-new 'xcb:ConfigureRequest data)
684+
(exwm--log "#x%x (#x%x) @%dx%d%+d%+d; \
673685
border-width: %d; sibling: #x%x; stack-mode: %d"
674-
window value-mask width height x y
675-
border-width sibling stack-mode)
676-
(if (and (setq buffer (exwm--id->buffer window))
677-
(with-current-buffer buffer
678-
(or (exwm-layout--fullscreen-p)
679-
;; Make sure it's a floating X window wanting to resize
680-
;; itself.
681-
(or (not exwm--floating-frame)
682-
(progn
683-
(setq edges
684-
(exwm--window-inside-pixel-edges
685-
(get-buffer-window buffer t))
686-
width-delta (- width (- (elt edges 2)
687-
(elt edges 0)))
688-
height-delta (- height (- (elt edges 3)
689-
(elt edges 1))))
690-
;; We cannot do resizing precisely for now.
691-
(and (if (= 0 (logand value-mask
692-
xcb:ConfigWindow:Width))
693-
t
694-
(< (abs width-delta)
695-
exwm-manage--width-delta-min))
696-
(if (= 0 (logand value-mask
697-
xcb:ConfigWindow:Height))
698-
t
699-
(< (abs height-delta)
700-
exwm-manage--height-delta-min))))))))
701-
;; Send client message for managed windows
702-
(with-current-buffer buffer
703-
(setq edges
704-
(if (exwm-layout--fullscreen-p)
705-
(with-slots (x y width height)
706-
(exwm-workspace--get-geometry exwm--frame)
707-
(list x y width height))
708-
(exwm--window-inside-absolute-pixel-edges
709-
(get-buffer-window buffer t))))
710-
(exwm--log "Reply with ConfigureNotify (edges): %s" edges)
711-
(xcb:+request exwm--connection
712-
(make-instance 'xcb:SendEvent
713-
:propagate 0 :destination window
714-
:event-mask xcb:EventMask:StructureNotify
715-
:event (xcb:marshal
716-
(make-instance
717-
'xcb:ConfigureNotify
718-
:event window :window window
719-
:above-sibling xcb:Window:None
720-
:x (elt edges 0) :y (elt edges 1)
721-
:width (- (elt edges 2) (elt edges 0))
722-
:height (- (elt edges 3) (elt edges 1))
723-
:border-width 0 :override-redirect 0)
724-
exwm--connection))))
725-
(if buffer
726-
(with-current-buffer buffer
727-
(exwm--log "ConfigureWindow (resize floating X window)")
728-
(exwm--set-geometry (frame-parameter exwm--floating-frame
729-
'exwm-outer-id)
730-
nil
731-
nil
732-
(+ (frame-outer-width exwm--floating-frame)
733-
width-delta)
734-
(+ (frame-outer-height exwm--floating-frame)
735-
height-delta)))
736-
(exwm--log "ConfigureWindow (preserve geometry)")
737-
;; Configure the unmanaged window.
738-
;; But Emacs frames should be excluded. Generally we don't
739-
;; receive ConfigureRequest events from Emacs frames since we
740-
;; have set OverrideRedirect on them, but this is not true for
741-
;; Lucid build (as of 25.1).
742-
(unless (memq window exwm-manage--frame-outer-id-list)
743-
(xcb:+request exwm--connection
744-
(make-instance 'xcb:ConfigureWindow
745-
:window window
746-
:value-mask value-mask
747-
:x x :y y :width width :height height
748-
:border-width border-width
749-
:sibling sibling
750-
:stack-mode stack-mode)))))))
686+
window value-mask width height x y
687+
border-width sibling stack-mode)
688+
(if-let* ((buffer (exwm--id->buffer window)))
689+
(with-current-buffer buffer
690+
(if (exwm-layout--fullscreen-p)
691+
;; Fit fullscreen windows to the workspace.
692+
(with-slots (x y width height)
693+
(exwm-workspace--get-geometry exwm--frame)
694+
(exwm-manage--send-ConfigureNotify
695+
window x y width height))
696+
(let* ((edges (exwm--window-inside-absolute-pixel-edges
697+
(get-buffer-window buffer t)))
698+
(window-x (elt edges 0))
699+
(window-y (elt edges 1))
700+
(window-width (- (elt edges 2) window-x))
701+
(window-height (- (elt edges 3) window-y)))
702+
(if (not exwm--floating-frame)
703+
;; If the window isn't floating, fit it to its Emacs window.
704+
(exwm-manage--send-ConfigureNotify
705+
window window-x window-y
706+
window-width window-height)
707+
;; Finally, resize the floating window.
708+
(exwm--log "ConfigureWindow (resize floating X window)")
709+
(let* ((frame-id (frame-parameter exwm--floating-frame
710+
'exwm-outer-id))
711+
(frame-edges (frame-edges exwm--floating-frame
712+
'outer-edges))
713+
(frame-width (- (elt frame-edges 2)
714+
(elt frame-edges 0)))
715+
(frame-height (- (elt frame-edges 3)
716+
(elt frame-edges 1))))
717+
(exwm--set-geometry
718+
frame-id
719+
nil nil
720+
(unless (= 0 (logand value-mask xcb:ConfigWindow:Width))
721+
(+ frame-width (- width window-width)))
722+
(unless (= 0 (logand value-mask xcb:ConfigWindow:Height))
723+
(+ frame-height (- height window-height)))))))))
724+
(exwm--log "ConfigureWindow (preserve geometry)")
725+
;; Configure the unmanaged window.
726+
;; But Emacs frames should be excluded. Generally we don't
727+
;; receive ConfigureRequest events from Emacs frames since we
728+
;; have set OverrideRedirect on them, but this is not true for
729+
;; Lucid build (as of 25.1).
730+
(unless (memq window exwm-manage--frame-outer-id-list)
731+
(xcb:+request exwm--connection
732+
(make-instance 'xcb:ConfigureWindow
733+
:window window
734+
:value-mask value-mask
735+
:x x :y y :width width :height height
736+
:border-width border-width
737+
:sibling sibling
738+
:stack-mode stack-mode)))))
751739
(xcb:flush exwm--connection))
752740

753741
(defun exwm-manage--on-MapRequest (data _synthetic)

0 commit comments

Comments
 (0)