mirror of
https://github.com/ch11ng/exwm.git
synced 2024-11-23 19:47:58 +01:00
Fix multi-screen bugs
* RandR module is now made optional; users can enable it with `exwm-randr-enable`. * Correct the calculation of sizes/coordinates at various places. * Input focus is now tracked with (Emacs) window instead of buffer since the latter can be ambiguous in multi-screen settings.
This commit is contained in:
parent
35560a49d6
commit
07e59e0429
6 changed files with 54 additions and 30 deletions
|
@ -39,8 +39,9 @@
|
||||||
(defun exwm-floating--set-floating (id)
|
(defun exwm-floating--set-floating (id)
|
||||||
"Make window ID floating."
|
"Make window ID floating."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (get-buffer-window (exwm--id->buffer id)) ;window in non-floating state
|
(let ((window (get-buffer-window (exwm--id->buffer id))))
|
||||||
(set-window-buffer (selected-window) (other-buffer))) ;hide it first
|
(when window ;window in non-floating state
|
||||||
|
(set-window-buffer window (other-buffer)))) ;hide it first
|
||||||
(let* ((original-frame
|
(let* ((original-frame
|
||||||
(with-current-buffer (exwm--id->buffer id)
|
(with-current-buffer (exwm--id->buffer id)
|
||||||
(if (and exwm-transient-for (exwm--id->buffer exwm-transient-for))
|
(if (and exwm-transient-for (exwm--id->buffer exwm-transient-for))
|
||||||
|
@ -78,8 +79,8 @@
|
||||||
(exwm-workspace--update-switch-history)))
|
(exwm-workspace--update-switch-history)))
|
||||||
;; Fix illegal parameters
|
;; Fix illegal parameters
|
||||||
;; FIXME: check normal hints restrictions
|
;; FIXME: check normal hints restrictions
|
||||||
(let* ((display-width (x-display-pixel-width))
|
(let* ((display-width (frame-pixel-width original-frame))
|
||||||
(display-height (- (x-display-pixel-height)
|
(display-height (- (frame-pixel-height original-frame)
|
||||||
(window-pixel-height (minibuffer-window
|
(window-pixel-height (minibuffer-window
|
||||||
original-frame))
|
original-frame))
|
||||||
(* 2 (window-mode-line-height))
|
(* 2 (window-mode-line-height))
|
||||||
|
@ -373,6 +374,8 @@
|
||||||
"Perform move/resize."
|
"Perform move/resize."
|
||||||
(when exwm-floating--moveresize-calculate
|
(when exwm-floating--moveresize-calculate
|
||||||
(let ((obj (make-instance 'xcb:MotionNotify))
|
(let ((obj (make-instance 'xcb:MotionNotify))
|
||||||
|
(frame-x (or (frame-parameter exwm-workspace--current 'exwm-x) 0))
|
||||||
|
(frame-y (or (frame-parameter exwm-workspace--current 'exwm-y) 0))
|
||||||
result)
|
result)
|
||||||
(xcb:unmarshal obj data)
|
(xcb:unmarshal obj data)
|
||||||
(setq result (funcall exwm-floating--moveresize-calculate
|
(setq result (funcall exwm-floating--moveresize-calculate
|
||||||
|
@ -380,7 +383,8 @@
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:ConfigureWindow
|
(make-instance 'xcb:ConfigureWindow
|
||||||
:window (elt result 0) :value-mask (elt result 1)
|
:window (elt result 0) :value-mask (elt result 1)
|
||||||
:x (elt result 2) :y (elt result 3)
|
:x (- (elt result 2) frame-x)
|
||||||
|
:y (- (elt result 3) frame-y)
|
||||||
:width (elt result 4) :height (elt result 5)))
|
:width (elt result 4) :height (elt result 5)))
|
||||||
(xcb:flush exwm--connection))))
|
(xcb:flush exwm--connection))))
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.")
|
||||||
:time xcb:Time:CurrentTime)))
|
:time xcb:Time:CurrentTime)))
|
||||||
(xcb:flush exwm--connection)))
|
(xcb:flush exwm--connection)))
|
||||||
|
|
||||||
(defvar exwm-input--focus-buffer nil "The buffer to be focused.")
|
(defvar exwm-input--focus-window nil "The (Emacs) window to be focused.")
|
||||||
(defvar exwm-input--redirected nil
|
(defvar exwm-input--redirected nil
|
||||||
"Indicate next update on buffer list is actually a result of redirection.")
|
"Indicate next update on buffer list is actually a result of redirection.")
|
||||||
(defvar exwm-input--timer nil "Currently running timer.")
|
(defvar exwm-input--timer nil "Currently running timer.")
|
||||||
|
@ -85,15 +85,17 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.")
|
||||||
(defun exwm-input--on-buffer-list-update ()
|
(defun exwm-input--on-buffer-list-update ()
|
||||||
"Run in buffer-list-update-hook to track input focus."
|
"Run in buffer-list-update-hook to track input focus."
|
||||||
(let ((frame (selected-frame))
|
(let ((frame (selected-frame))
|
||||||
|
(window (selected-window))
|
||||||
(buffer (current-buffer)))
|
(buffer (current-buffer)))
|
||||||
(when (and (not (minibufferp buffer))
|
(when (and (not (minibufferp buffer))
|
||||||
(frame-parameter frame 'exwm-window-id) ;e.g. emacsclient frame
|
(frame-parameter frame 'exwm-window-id) ;e.g. emacsclient frame
|
||||||
(eq buffer (window-buffer))) ;e.g. `with-temp-buffer'
|
(eq buffer (window-buffer))) ;e.g. `with-temp-buffer'
|
||||||
(unless (and exwm-input--redirected
|
(unless (and exwm-input--redirected
|
||||||
exwm-input--focus-buffer
|
exwm-input--focus-window
|
||||||
(with-current-buffer exwm-input--focus-buffer
|
(with-current-buffer (window-buffer
|
||||||
|
exwm-input--focus-window)
|
||||||
exwm--floating-frame))
|
exwm--floating-frame))
|
||||||
(setq exwm-input--focus-buffer buffer)
|
(setq exwm-input--focus-window window)
|
||||||
(when exwm-input--timer (cancel-timer exwm-input--timer))
|
(when exwm-input--timer (cancel-timer exwm-input--timer))
|
||||||
(setq exwm-input--timer
|
(setq exwm-input--timer
|
||||||
(run-with-timer 0.01 nil 'exwm-input--update-focus)))
|
(run-with-timer 0.01 nil 'exwm-input--update-focus)))
|
||||||
|
@ -108,22 +110,23 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.")
|
||||||
|
|
||||||
(defun exwm-input--update-focus ()
|
(defun exwm-input--update-focus ()
|
||||||
"Update input focus."
|
"Update input focus."
|
||||||
(when exwm-input--focus-buffer
|
(when exwm-input--focus-window
|
||||||
(with-current-buffer exwm-input--focus-buffer
|
(with-current-buffer (window-buffer exwm-input--focus-window)
|
||||||
(exwm--log "Set focus on %s" exwm-input--focus-buffer)
|
(exwm--log "Set focus on %s" exwm-input--focus-window)
|
||||||
(setq exwm-input--focus-buffer nil)
|
|
||||||
(if (eq major-mode 'exwm-mode)
|
(if (eq major-mode 'exwm-mode)
|
||||||
(progn
|
(progn
|
||||||
(when exwm--floating-frame
|
(when exwm--floating-frame
|
||||||
(redirect-frame-focus exwm--floating-frame nil)
|
(redirect-frame-focus exwm--floating-frame nil)
|
||||||
(select-frame-set-input-focus exwm--floating-frame t))
|
(select-frame-set-input-focus exwm--floating-frame t))
|
||||||
(exwm-input--set-focus exwm--id))
|
(exwm-input--set-focus exwm--id))
|
||||||
(select-frame-set-input-focus exwm-workspace--current t)
|
(select-frame-set-input-focus (window-frame exwm-input--focus-window)
|
||||||
|
t)
|
||||||
(dolist (pair exwm--id-buffer-alist)
|
(dolist (pair exwm--id-buffer-alist)
|
||||||
(with-current-buffer (cdr pair)
|
(with-current-buffer (cdr pair)
|
||||||
(when (and exwm--floating-frame
|
(when (and exwm--floating-frame
|
||||||
(eq exwm--frame exwm-workspace--current))
|
(eq exwm--frame exwm-workspace--current))
|
||||||
(redirect-frame-focus exwm--floating-frame exwm--frame))))))))
|
(redirect-frame-focus exwm--floating-frame exwm--frame)))))
|
||||||
|
(setq exwm-input--focus-window nil))))
|
||||||
|
|
||||||
(defun exwm-input--finish-key-sequence ()
|
(defun exwm-input--finish-key-sequence ()
|
||||||
"Mark the end of a key sequence (with the aid of `pre-command-hook')."
|
"Mark the end of a key sequence (with the aid of `pre-command-hook')."
|
||||||
|
|
|
@ -111,8 +111,9 @@
|
||||||
xcb:ConfigWindow:Width
|
xcb:ConfigWindow:Width
|
||||||
xcb:ConfigWindow:Height)
|
xcb:ConfigWindow:Height)
|
||||||
:x 0 :y 0
|
:x 0 :y 0
|
||||||
:width (x-display-pixel-width)
|
:width (frame-pixel-width exwm-workspace--current)
|
||||||
:height (x-display-pixel-height))))
|
:height (frame-pixel-height
|
||||||
|
exwm-workspace--current))))
|
||||||
(xcb:flush exwm--connection))
|
(xcb:flush exwm--connection))
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:ConfigureWindow
|
(make-instance 'xcb:ConfigureWindow
|
||||||
|
@ -122,8 +123,8 @@
|
||||||
xcb:ConfigWindow:Width
|
xcb:ConfigWindow:Width
|
||||||
xcb:ConfigWindow:Height)
|
xcb:ConfigWindow:Height)
|
||||||
:x 0 :y 0
|
:x 0 :y 0
|
||||||
:width (x-display-pixel-width)
|
:width (frame-pixel-width exwm-workspace--current)
|
||||||
:height (x-display-pixel-height)))
|
:height (frame-pixel-height exwm-workspace--current)))
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:ewmh:set-_NET_WM_STATE
|
(make-instance 'xcb:ewmh:set-_NET_WM_STATE
|
||||||
:window exwm--id
|
:window exwm--id
|
||||||
|
@ -168,11 +169,11 @@
|
||||||
(if (frame-parameter frame 'exwm-window-id)
|
(if (frame-parameter frame 'exwm-window-id)
|
||||||
;; Refresh a floating frame
|
;; Refresh a floating frame
|
||||||
(progn
|
(progn
|
||||||
(cl-assert (eq major-mode 'exwm-mode))
|
(when (eq major-mode 'exwm-mode)
|
||||||
(let ((window (frame-first-window frame)))
|
(let ((window (frame-first-window frame)))
|
||||||
(with-current-buffer (window-buffer window)
|
(with-current-buffer (window-buffer window)
|
||||||
(exwm--log "Refresh floating window #x%x" exwm--id)
|
(exwm--log "Refresh floating window #x%x" exwm--id)
|
||||||
(exwm-layout--show exwm--id window))))
|
(exwm-layout--show exwm--id window)))))
|
||||||
;; Other frames (e.g. terminal/graphical frame of emacsclient)
|
;; Other frames (e.g. terminal/graphical frame of emacsclient)
|
||||||
;; We shall bury all `exwm-mode' buffers in this case
|
;; We shall bury all `exwm-mode' buffers in this case
|
||||||
(unless placeholder ;create the *scratch* buffer if it's killed
|
(unless placeholder ;create the *scratch* buffer if it's killed
|
||||||
|
|
|
@ -98,8 +98,14 @@ corresponding buffer.")
|
||||||
:window id
|
:window id
|
||||||
:value-mask (logior xcb:ConfigWindow:X
|
:value-mask (logior xcb:ConfigWindow:X
|
||||||
xcb:ConfigWindow:Y)
|
xcb:ConfigWindow:Y)
|
||||||
:x (/ (- (x-display-pixel-width) width) 2)
|
:x (/ (- (frame-pixel-width
|
||||||
:y (/ (- (x-display-pixel-height) height) 2)))))
|
exwm-workspace--current)
|
||||||
|
width)
|
||||||
|
2)
|
||||||
|
:y (/ (- (frame-pixel-height
|
||||||
|
exwm-workspace--current)
|
||||||
|
height)
|
||||||
|
2)))))
|
||||||
(xcb:flush exwm--connection)
|
(xcb:flush exwm--connection)
|
||||||
(setq kill-buffer-query-functions nil)
|
(setq kill-buffer-query-functions nil)
|
||||||
(setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist))
|
(setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist))
|
||||||
|
@ -277,7 +283,8 @@ corresponding buffer.")
|
||||||
(setq edges
|
(setq edges
|
||||||
(if exwm--fullscreen
|
(if exwm--fullscreen
|
||||||
(list 0 0
|
(list 0 0
|
||||||
(x-display-pixel-width) (x-display-pixel-height))
|
(frame-pixel-width exwm-workspace--current)
|
||||||
|
(frame-pixel-height exwm-workspace--current))
|
||||||
(or exwm--floating-edges
|
(or exwm--floating-edges
|
||||||
(window-inside-absolute-pixel-edges
|
(window-inside-absolute-pixel-edges
|
||||||
(get-buffer-window)))))
|
(get-buffer-window)))))
|
||||||
|
|
|
@ -26,8 +26,11 @@
|
||||||
;; tools such as xrandr(1) to properly configure RandR first. This dependency
|
;; tools such as xrandr(1) to properly configure RandR first. This dependency
|
||||||
;; may be removed in the future, but more work is needed before that.
|
;; may be removed in the future, but more work is needed before that.
|
||||||
|
|
||||||
;; To use this module, first set `exwm-randr-workspace-output-plist':
|
;; To use this module, first load/enable it and properly configure the variable
|
||||||
|
;; `exwm-randr-workspace-output-plist':
|
||||||
|
;; (require 'exwm-randr)
|
||||||
;; (setq exwm-randr-workspace-output-plist '(0 "VGA1"))
|
;; (setq exwm-randr-workspace-output-plist '(0 "VGA1"))
|
||||||
|
;; (exwm-randr-enable)
|
||||||
;; Then configure RandR with 'xrandr':
|
;; Then configure RandR with 'xrandr':
|
||||||
;; $ xrandr --output VGA1 --left-of LVDS1 --auto
|
;; $ xrandr --output VGA1 --left-of LVDS1 --auto
|
||||||
;; With above lines, workspace 0 should be assigned to the output named "VGA1",
|
;; With above lines, workspace 0 should be assigned to the output named "VGA1",
|
||||||
|
@ -82,6 +85,8 @@
|
||||||
(setq geometry default-geometry
|
(setq geometry default-geometry
|
||||||
output nil))
|
output nil))
|
||||||
(set-frame-parameter frame 'exwm-randr-output output)
|
(set-frame-parameter frame 'exwm-randr-output output)
|
||||||
|
(set-frame-parameter frame 'exwm-x (elt geometry 0))
|
||||||
|
(set-frame-parameter frame 'exwm-y (elt geometry 1))
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:ConfigureWindow
|
(make-instance 'xcb:ConfigureWindow
|
||||||
:window (frame-parameter frame 'exwm-outer-id)
|
:window (frame-parameter frame 'exwm-outer-id)
|
||||||
|
@ -108,9 +113,11 @@
|
||||||
(exwm-randr--refresh)
|
(exwm-randr--refresh)
|
||||||
(xcb:+event exwm--connection 'xcb:randr:ScreenChangeNotify
|
(xcb:+event exwm--connection 'xcb:randr:ScreenChangeNotify
|
||||||
(lambda (data synthetic)
|
(lambda (data synthetic)
|
||||||
|
(exwm--log "(RandR) ScreenChangeNotify")
|
||||||
(exwm-randr--refresh)))
|
(exwm-randr--refresh)))
|
||||||
;; (xcb:+event exwm--connection 'xcb:randr:Notify
|
;; (xcb:+event exwm--connection 'xcb:randr:Notify
|
||||||
;; (lambda (data synthetic)
|
;; (lambda (data synthetic)
|
||||||
|
;; (exwm--log "(RandR) Notify")
|
||||||
;; (exwm-randr--refresh)))
|
;; (exwm-randr--refresh)))
|
||||||
(xcb:+request exwm--connection
|
(xcb:+request exwm--connection
|
||||||
(make-instance 'xcb:randr:SelectInput
|
(make-instance 'xcb:randr:SelectInput
|
||||||
|
@ -124,6 +131,10 @@
|
||||||
))
|
))
|
||||||
(xcb:flush exwm--connection)))))
|
(xcb:flush exwm--connection)))))
|
||||||
|
|
||||||
|
(defun exwm-randr-enable ()
|
||||||
|
"Enable RandR support for EXWM."
|
||||||
|
(add-hook 'exwm-init-hook 'exwm-randr--init))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(provide 'exwm-randr)
|
(provide 'exwm-randr)
|
||||||
|
|
2
exwm.el
2
exwm.el
|
@ -144,7 +144,6 @@
|
||||||
(require 'exwm-floating)
|
(require 'exwm-floating)
|
||||||
(require 'exwm-manage)
|
(require 'exwm-manage)
|
||||||
(require 'exwm-input)
|
(require 'exwm-input)
|
||||||
(require 'exwm-randr)
|
|
||||||
|
|
||||||
(defvar exwm-debug-on nil "Non-nil to turn on debug for EXWM.")
|
(defvar exwm-debug-on nil "Non-nil to turn on debug for EXWM.")
|
||||||
|
|
||||||
|
@ -616,7 +615,6 @@
|
||||||
(exwm-floating--init)
|
(exwm-floating--init)
|
||||||
(exwm-manage--init)
|
(exwm-manage--init)
|
||||||
(exwm-input--init)
|
(exwm-input--init)
|
||||||
(exwm-randr--init)
|
|
||||||
(exwm--unlock)
|
(exwm--unlock)
|
||||||
;; Manage exiting windows
|
;; Manage exiting windows
|
||||||
(exwm-manage--scan)
|
(exwm-manage--scan)
|
||||||
|
|
Loading…
Reference in a new issue