From 07e59e0429c4b13a5036e9a207e37fc02135f599 Mon Sep 17 00:00:00 2001 From: Chris Feng Date: Thu, 13 Aug 2015 12:02:44 +0800 Subject: 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. --- exwm-floating.el | 14 +++++++++----- exwm-input.el | 23 +++++++++++++---------- exwm-layout.el | 19 ++++++++++--------- exwm-manage.el | 13 ++++++++++--- exwm-randr.el | 13 ++++++++++++- exwm.el | 2 -- 6 files changed, 54 insertions(+), 30 deletions(-) diff --git a/exwm-floating.el b/exwm-floating.el index e1d8738270d5..06d6fa505c88 100644 --- a/exwm-floating.el +++ b/exwm-floating.el @@ -39,8 +39,9 @@ (defun exwm-floating--set-floating (id) "Make window ID floating." (interactive) - (when (get-buffer-window (exwm--id->buffer id)) ;window in non-floating state - (set-window-buffer (selected-window) (other-buffer))) ;hide it first + (let ((window (get-buffer-window (exwm--id->buffer id)))) + (when window ;window in non-floating state + (set-window-buffer window (other-buffer)))) ;hide it first (let* ((original-frame (with-current-buffer (exwm--id->buffer id) (if (and exwm-transient-for (exwm--id->buffer exwm-transient-for)) @@ -78,8 +79,8 @@ (exwm-workspace--update-switch-history))) ;; Fix illegal parameters ;; FIXME: check normal hints restrictions - (let* ((display-width (x-display-pixel-width)) - (display-height (- (x-display-pixel-height) + (let* ((display-width (frame-pixel-width original-frame)) + (display-height (- (frame-pixel-height original-frame) (window-pixel-height (minibuffer-window original-frame)) (* 2 (window-mode-line-height)) @@ -373,6 +374,8 @@ "Perform move/resize." (when exwm-floating--moveresize-calculate (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) (xcb:unmarshal obj data) (setq result (funcall exwm-floating--moveresize-calculate @@ -380,7 +383,8 @@ (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow :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))) (xcb:flush exwm--connection)))) diff --git a/exwm-input.el b/exwm-input.el index b9a5f206e799..0ef72325bb0a 100644 --- a/exwm-input.el +++ b/exwm-input.el @@ -77,7 +77,7 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.") :time xcb:Time:CurrentTime))) (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 "Indicate next update on buffer list is actually a result of redirection.") (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 () "Run in buffer-list-update-hook to track input focus." (let ((frame (selected-frame)) + (window (selected-window)) (buffer (current-buffer))) (when (and (not (minibufferp buffer)) (frame-parameter frame 'exwm-window-id) ;e.g. emacsclient frame (eq buffer (window-buffer))) ;e.g. `with-temp-buffer' (unless (and exwm-input--redirected - exwm-input--focus-buffer - (with-current-buffer exwm-input--focus-buffer + exwm-input--focus-window + (with-current-buffer (window-buffer + exwm-input--focus-window) exwm--floating-frame)) - (setq exwm-input--focus-buffer buffer) + (setq exwm-input--focus-window window) (when exwm-input--timer (cancel-timer exwm-input--timer)) (setq exwm-input--timer (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 () "Update input focus." - (when exwm-input--focus-buffer - (with-current-buffer exwm-input--focus-buffer - (exwm--log "Set focus on %s" exwm-input--focus-buffer) - (setq exwm-input--focus-buffer nil) + (when exwm-input--focus-window + (with-current-buffer (window-buffer exwm-input--focus-window) + (exwm--log "Set focus on %s" exwm-input--focus-window) (if (eq major-mode 'exwm-mode) (progn (when exwm--floating-frame (redirect-frame-focus exwm--floating-frame nil) (select-frame-set-input-focus exwm--floating-frame t)) (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) (with-current-buffer (cdr pair) (when (and exwm--floating-frame (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 () "Mark the end of a key sequence (with the aid of `pre-command-hook')." diff --git a/exwm-layout.el b/exwm-layout.el index f2d4eb0cbeb9..a6b450f7daf5 100644 --- a/exwm-layout.el +++ b/exwm-layout.el @@ -111,8 +111,9 @@ xcb:ConfigWindow:Width xcb:ConfigWindow:Height) :x 0 :y 0 - :width (x-display-pixel-width) - :height (x-display-pixel-height)))) + :width (frame-pixel-width exwm-workspace--current) + :height (frame-pixel-height + exwm-workspace--current)))) (xcb:flush exwm--connection)) (xcb:+request exwm--connection (make-instance 'xcb:ConfigureWindow @@ -122,8 +123,8 @@ xcb:ConfigWindow:Width xcb:ConfigWindow:Height) :x 0 :y 0 - :width (x-display-pixel-width) - :height (x-display-pixel-height))) + :width (frame-pixel-width exwm-workspace--current) + :height (frame-pixel-height exwm-workspace--current))) (xcb:+request exwm--connection (make-instance 'xcb:ewmh:set-_NET_WM_STATE :window exwm--id @@ -168,11 +169,11 @@ (if (frame-parameter frame 'exwm-window-id) ;; Refresh a floating frame (progn - (cl-assert (eq major-mode 'exwm-mode)) - (let ((window (frame-first-window frame))) - (with-current-buffer (window-buffer window) - (exwm--log "Refresh floating window #x%x" exwm--id) - (exwm-layout--show exwm--id window)))) + (when (eq major-mode 'exwm-mode) + (let ((window (frame-first-window frame))) + (with-current-buffer (window-buffer window) + (exwm--log "Refresh floating window #x%x" exwm--id) + (exwm-layout--show exwm--id window))))) ;; Other frames (e.g. terminal/graphical frame of emacsclient) ;; We shall bury all `exwm-mode' buffers in this case (unless placeholder ;create the *scratch* buffer if it's killed diff --git a/exwm-manage.el b/exwm-manage.el index d1736ff9a4cf..4f11874d3a3e 100644 --- a/exwm-manage.el +++ b/exwm-manage.el @@ -98,8 +98,14 @@ corresponding buffer.") :window id :value-mask (logior xcb:ConfigWindow:X xcb:ConfigWindow:Y) - :x (/ (- (x-display-pixel-width) width) 2) - :y (/ (- (x-display-pixel-height) height) 2))))) + :x (/ (- (frame-pixel-width + exwm-workspace--current) + width) + 2) + :y (/ (- (frame-pixel-height + exwm-workspace--current) + height) + 2))))) (xcb:flush exwm--connection) (setq kill-buffer-query-functions nil) (setq exwm--id-buffer-alist (assq-delete-all id exwm--id-buffer-alist)) @@ -277,7 +283,8 @@ corresponding buffer.") (setq edges (if exwm--fullscreen (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 (window-inside-absolute-pixel-edges (get-buffer-window))))) diff --git a/exwm-randr.el b/exwm-randr.el index c9ad1ce6ae7b..cd40fb43bd3f 100644 --- a/exwm-randr.el +++ b/exwm-randr.el @@ -26,8 +26,11 @@ ;; 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. -;; 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")) +;; (exwm-randr-enable) ;; Then configure RandR with 'xrandr': ;; $ xrandr --output VGA1 --left-of LVDS1 --auto ;; With above lines, workspace 0 should be assigned to the output named "VGA1", @@ -82,6 +85,8 @@ (setq geometry default-geometry output nil)) (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 (make-instance 'xcb:ConfigureWindow :window (frame-parameter frame 'exwm-outer-id) @@ -108,9 +113,11 @@ (exwm-randr--refresh) (xcb:+event exwm--connection 'xcb:randr:ScreenChangeNotify (lambda (data synthetic) + (exwm--log "(RandR) ScreenChangeNotify") (exwm-randr--refresh))) ;; (xcb:+event exwm--connection 'xcb:randr:Notify ;; (lambda (data synthetic) + ;; (exwm--log "(RandR) Notify") ;; (exwm-randr--refresh))) (xcb:+request exwm--connection (make-instance 'xcb:randr:SelectInput @@ -124,6 +131,10 @@ )) (xcb:flush exwm--connection))))) +(defun exwm-randr-enable () + "Enable RandR support for EXWM." + (add-hook 'exwm-init-hook 'exwm-randr--init)) + (provide 'exwm-randr) diff --git a/exwm.el b/exwm.el index d33ab2619044..7dffa87aec4b 100644 --- a/exwm.el +++ b/exwm.el @@ -144,7 +144,6 @@ (require 'exwm-floating) (require 'exwm-manage) (require 'exwm-input) -(require 'exwm-randr) (defvar exwm-debug-on nil "Non-nil to turn on debug for EXWM.") @@ -616,7 +615,6 @@ (exwm-floating--init) (exwm-manage--init) (exwm-input--init) - (exwm-randr--init) (exwm--unlock) ;; Manage exiting windows (exwm-manage--scan) -- cgit 1.4.1