[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/exwm 5c5729c 2/2: Fix various issues with multi-monitor
From: |
Chris Feng |
Subject: |
[elpa] externals/exwm 5c5729c 2/2: Fix various issues with multi-monitor support |
Date: |
Mon, 19 Feb 2018 09:51:22 -0500 (EST) |
branch: externals/exwm
commit 5c5729c0d4832a870a928d6d7cc2f990a7e8f649
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>
Fix various issues with multi-monitor support
* exwm-workspace.el (exwm-workspace-switch): Do not hide X windows
when switching to a workspace on another output; update the
timestamp (last switched to) of a workspace frame.
(exwm-workspace-move-window): Do not hide an X window when moving it
to an active workspace on another output.
* exwm-floating.el (exwm-floating--set-floating):
* exwm-layout.el (exwm-layout-set-fullscreen):
* exwm-manage.el (exwm-manage--manage-window)
(exwm-manage--on-ConfigureRequest):
* exwm-systemtray.el (exwm-systemtray--refresh)
(exwm-systemtray--init):
Correct coordinate calculations.
* exwm-workspace.el (exwm-workspace--current-width): Removed since no
longer used.
---
exwm-floating.el | 74 ++++++++++++++++---------------------
exwm-layout.el | 9 +----
exwm-manage.el | 26 ++++++++-----
exwm-systemtray.el | 26 +++++++------
exwm-workspace.el | 105 ++++++++++++++++++++++++++++++++++-------------------
5 files changed, 131 insertions(+), 109 deletions(-)
diff --git a/exwm-floating.el b/exwm-floating.el
index 8cd0491..5a2c61e 100644
--- a/exwm-floating.el
+++ b/exwm-floating.el
@@ -129,52 +129,22 @@ This is also used by X window containers.")
(y (slot-value exwm--geometry 'y))
(width (slot-value exwm--geometry 'width))
(height (slot-value exwm--geometry 'height)))
- (exwm--log "Floating geometry (original, absolute): %dx%d%+d%+d"
- width height x y)
- (when (and (/= x 0)
- (/= y 0))
- (let ((workarea (elt exwm-workspace--workareas
- (exwm-workspace--position original-frame))))
- (setq x (- x (aref workarea 0))
- y (- y (aref workarea 1)))))
- (exwm--log "Floating geometry (original, relative): %dx%d%+d%+d"
- width height x y)
+ (exwm--log "Floating geometry (original): %dx%d%+d%+d" width height x y)
;; Save frame parameters.
(set-frame-parameter frame 'exwm-outer-id outer-id)
(set-frame-parameter frame 'exwm-id window-id)
(set-frame-parameter frame 'exwm-container frame-container)
;; Fix illegal parameters
;; FIXME: check normal hints restrictions
- (let* ((display-width (frame-pixel-width original-frame))
- (display-height (- (frame-pixel-height original-frame)
- (if (exwm-workspace--minibuffer-own-frame-p)
- 0
- (window-pixel-height (minibuffer-window
- original-frame)))
- (* 2 (window-mode-line-height))
- (window-header-line-height window)))
- (display-height (* 2 (/ display-height 2)))) ;round to even
- (if (> width display-width)
- ;; Too wide
- (progn (setq x 0
- width display-width))
- ;; Invalid width
- (when (= 0 width) (setq width (/ display-width 2)))
- ;; Make sure at least half of the window is visible
- (when (or (> (+ x (/ width 2)) display-width) (> 0 (+ x (/ width 2))))
- (setq x (/ (- display-width width) 2))))
- (if (> height display-height)
- ;; Too tall
- (setq y 0
- height display-height)
- ;; Invalid height
- (when (= 0 height) (setq height (/ display-height 2)))
- ;; Make sure at least half of the window is visible
- (when (or (> (+ y (/ height 2)) display-height)
- (> 0 (+ y (/ height 2))))
- (setq y (/ (- display-height height) 2))))
+ (let* ((workarea (elt exwm-workspace--workareas
+ (exwm-workspace--position original-frame)))
+ (x* (aref workarea 0))
+ (y* (aref workarea 1))
+ (width* (aref workarea 2))
+ (height* (aref workarea 3)))
;; Center floating windows
- (when (and (= x 0) (= y 0))
+ (when (and (or (= x 0) (= x x*))
+ (or (= y 0) (= y y*)))
(let ((buffer (exwm--id->buffer exwm-transient-for))
window edges)
(when (and buffer (setq window (get-buffer-window buffer)))
@@ -184,11 +154,29 @@ This is also used by X window containers.")
(setq edges nil)))
(if edges
;; Put at the center of leading window
- (setq x (/ (- (elt edges 2) (elt edges 0) width) 2)
- y (/ (- (elt edges 3) (elt edges 1) height) 2))
+ (setq x (+ x* (/ (- (elt edges 2) (elt edges 0) width) 2))
+ y (+ y* (/ (- (elt edges 3) (elt edges 1) height) 2)))
;; Put at the center of screen
- (setq x (/ (- display-width width) 2)
- y (/ (- display-height height) 2))))))
+ (setq x (/ (- width* width) 2)
+ y (/ (- height* height) 2)))))
+ (if (> width width*)
+ ;; Too wide
+ (progn (setq x x*
+ width width*))
+ ;; Invalid width
+ (when (= 0 width) (setq width (/ width* 2)))
+ ;; Make sure at least half of the window is visible
+ (unless (< x* (+ x (/ width 2)) (+ x* width*))
+ (setq x (+ x* (/ (- width* width) 2)))))
+ (if (> height height*)
+ ;; Too tall
+ (setq y y*
+ height height*)
+ ;; Invalid height
+ (when (= 0 height) (setq height (/ height* 2)))
+ ;; Make sure at least half of the window is visible
+ (unless (< y* (+ y (/ height 2)) (+ y* height*))
+ (setq y (+ y* (/ (- height* height) 2))))))
(exwm--set-geometry id x y nil nil)
(xcb:flush exwm--connection)
(exwm--log "Floating geometry (corrected): %dx%d%+d%+d" width height x y)
diff --git a/exwm-layout.el b/exwm-layout.el
index 3f624ad..5a01f90 100644
--- a/exwm-layout.el
+++ b/exwm-layout.el
@@ -49,8 +49,6 @@
(declare-function exwm-input-release-keyboard "exwm-input.el")
(declare-function exwm-workspace--client-p "exwm-workspace.el"
(&optional frame))
-(declare-function exwm-workspace--current-height "exwm-workspace.el")
-(declare-function exwm-workspace--current-width "exwm-workspace.el")
(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el")
(declare-function exwm-workspace--workspace-p "exwm-workspace.el"
(workspace))
@@ -137,11 +135,8 @@
(cl-return-from 'exwm-layout-set-fullscreen))
(with-current-buffer (if id (exwm--id->buffer id) (window-buffer))
;; Expand the X window to fill the whole screen.
- ;; Rationale: Floating X windows may not be positioned at (0, 0)
- ;; due to the extra border.
- (exwm--set-geometry exwm--id 0 0
- (exwm-workspace--current-width)
- (exwm-workspace--current-height))
+ (with-slots (x y width height) (exwm-workspace--get-geometry exwm--frame)
+ (exwm--set-geometry exwm--id x y width height))
;; Raise the X window.
(xcb:+request exwm--connection
(make-instance 'xcb:ConfigureWindow
diff --git a/exwm-manage.el b/exwm-manage.el
index 790b6f1..dd7c2e3 100644
--- a/exwm-manage.el
+++ b/exwm-manage.el
@@ -65,6 +65,7 @@ You can still make the X windows floating afterwards."
(defvar exwm-workspace--id-struts-alist)
(defvar exwm-workspace--list)
(defvar exwm-workspace--switch-history-outdated)
+(defvar exwm-workspace--workareas)
(defvar exwm-workspace-current-index)
(declare-function exwm--update-class "exwm.el" (id &optional force))
(declare-function exwm--update-hints "exwm.el" (id &optional force))
@@ -80,8 +81,7 @@ You can still make the X windows floating afterwards."
(declare-function exwm-input-grab-keyboard "exwm-input.el")
(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id))
(declare-function exwm-workspace--count "exwm-workspace.el" ())
-(declare-function exwm-workspace--current-height "exwm-workspace.el")
-(declare-function exwm-workspace--current-width "exwm-workspace.el")
+(declare-function exwm-workspace--position "exwm-workspace.el" (frame))
(declare-function exwm-workspace--set-desktop "exwm-workspace.el" (id))
(declare-function exwm-workspace--set-fullscreen "exwm-workspace.el" (frame))
(declare-function exwm-workspace--update-struts "exwm-workspace.el" ())
@@ -204,11 +204,17 @@ You can still make the X windows floating afterwards."
(with-slots (x y width height) exwm--geometry
;; Center window of type _NET_WM_WINDOW_TYPE_SPLASH
(when (memq xcb:Atom:_NET_WM_WINDOW_TYPE_SPLASH exwm-window-type)
- (exwm--set-geometry id
- (/ (- (exwm-workspace--current-width) width) 2)
- (/ (- (exwm-workspace--current-height) height)
- 2)
- nil nil)))
+ (let* ((workarea (elt exwm-workspace--workareas
+ (exwm-workspace--position exwm--frame)))
+ (x* (aref workarea 0))
+ (y* (aref workarea 1))
+ (width* (aref workarea 2))
+ (height* (aref workarea 3)))
+ (exwm--set-geometry id
+ (+ x* (/ (- width* width) 2))
+ (+ y* (/ (- height* height) 2))
+ nil
+ nil))))
;; Check for desktop.
(when (memq xcb:Atom:_NET_WM_WINDOW_TYPE_DESKTOP exwm-window-type)
;; There should be only one desktop X window.
@@ -501,9 +507,9 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
(with-current-buffer buffer
(setq edges
(if (memq xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state)
- (list 0 0
- (exwm-workspace--current-width)
- (exwm-workspace--current-height))
+ (with-slots (x y width height)
+ (exwm-workspace--get-geometry exwm--frame)
+ (list x y width height))
(window-inside-absolute-pixel-edges
(get-buffer-window buffer t))))
(exwm--log "Reply with ConfigureNotify (edges): %s" edges)
diff --git a/exwm-systemtray.el b/exwm-systemtray.el
index 5377ef8..d932032 100644
--- a/exwm-systemtray.el
+++ b/exwm-systemtray.el
@@ -82,8 +82,6 @@ You shall use the default value if using auto-hide
minibuffer."
(defvar exwm-workspace--workareas)
(defvar exwm-workspace-current-index)
(defvar xcb:Atom:_NET_SYSTEM_TRAY_S0)
-(declare-function exwm-workspace--current-height "exwm-workspace.el")
-(declare-function exwm-workspace--current-width "exwm-workspace.el")
(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el")
(defun exwm-systemtray--embed (icon)
@@ -205,13 +203,15 @@ You shall use the default value if using auto-hide
minibuffer."
(setq x (+ x (slot-value (cdr pair) 'width)
exwm-systemtray-icon-gap))
(setq map t)))
- (xcb:+request exwm-systemtray--connection
- (make-instance 'xcb:ConfigureWindow
- :window exwm-systemtray--embedder
- :value-mask (logior xcb:ConfigWindow:X
- xcb:ConfigWindow:Width)
- :x (- (exwm-workspace--current-width) x)
- :width x))
+ (let ((workarea (elt exwm-workspace--workareas
+ exwm-workspace-current-index)))
+ (xcb:+request exwm-systemtray--connection
+ (make-instance 'xcb:ConfigureWindow
+ :window exwm-systemtray--embedder
+ :value-mask (logior xcb:ConfigWindow:X
+ xcb:ConfigWindow:Width)
+ :x (- (aref workarea 2) x)
+ :width x)))
(when map
(xcb:+request exwm-systemtray--connection
(make-instance 'xcb:MapWindow :window exwm-systemtray--embedder))))
@@ -434,9 +434,11 @@ You shall use the default value if using auto-hide
minibuffer."
(- (line-pixel-height) exwm-systemtray-height)
;; Vertically centered.
(/ (- (line-pixel-height) exwm-systemtray-height) 2)))
- (setq frame exwm-workspace--current
- ;; Bottom aligned.
- y (- (exwm-workspace--current-height) exwm-systemtray-height)))
+ (let ((workarea (elt exwm-workspace--workareas
+ exwm-workspace-current-index)))
+ (setq frame exwm-workspace--current
+ ;; Bottom aligned.
+ y (- (aref workarea 3) exwm-systemtray-height))))
(setq parent (string-to-number (frame-parameter frame 'window-id))
depth (slot-value (xcb:+request-unchecked+reply
exwm-systemtray--connection
diff --git a/exwm-workspace.el b/exwm-workspace.el
index e2dfa23..9b0bfeb 100644
--- a/exwm-workspace.el
+++ b/exwm-workspace.el
@@ -273,14 +273,6 @@ NIL if FRAME is not a workspace"
:height (x-display-pixel-height))))
;;;###autoload
-(defun exwm-workspace--current-width ()
- "Return the width of current workspace."
- (let ((geometry (frame-parameter exwm-workspace--current 'exwm-geometry)))
- (if geometry
- (slot-value geometry 'width)
- (x-display-pixel-width))))
-
-;;;###autoload
(defun exwm-workspace--current-height ()
"Return the height of current workspace."
(let ((geometry (frame-parameter exwm-workspace--current 'exwm-geometry)))
@@ -536,14 +528,23 @@ for internal use only."
;; Set a default minibuffer frame.
(setq default-minibuffer-frame frame))
;; Show/Hide X windows.
- (dolist (i exwm--id-buffer-alist)
- (with-current-buffer (cdr i)
- (if (eq old-frame exwm--frame)
- (exwm-layout--hide exwm--id)
- (when (eq frame exwm--frame)
- (let ((window (get-buffer-window nil t)))
- (when window
- (exwm-layout--show exwm--id window)))))))
+ (let ((hide-x-windows-on-old-frame
+ (with-slots ((x1 x)
+ (y1 y))
+ (exwm-workspace--get-geometry frame)
+ (with-slots ((x2 x)
+ (y2 y))
+ (exwm-workspace--get-geometry old-frame)
+ (and (= x1 x2) (= y1 y2))))))
+ (dolist (i exwm--id-buffer-alist)
+ (with-current-buffer (cdr i)
+ (if (eq old-frame exwm--frame)
+ (when hide-x-windows-on-old-frame
+ (exwm-layout--hide exwm--id))
+ (when (eq frame exwm--frame)
+ (let ((window (get-buffer-window nil t)))
+ (when window
+ (exwm-layout--show exwm--id window))))))))
;; Hide windows in other workspaces by preprending a space
(unless exwm-workspace-show-all-buffers
(dolist (i exwm--id-buffer-alist)
@@ -553,6 +554,8 @@ for internal use only."
(exwm-workspace-rename-buffer (if (eq frame exwm--frame)
name
(concat " " name)))))))
+ ;; Update frame's timestamp.
+ (set-frame-parameter frame 'exwm-timestamp (float-time))
;; Update demands attention flag
(set-frame-parameter frame 'exwm-urgency nil)
;; Update switch workspace history
@@ -700,7 +703,7 @@ INDEX must not exceed the current number of workspaces."
(exwm-workspace--prompt-delete-allowed t))
(exwm-workspace--prompt-for-workspace "Move to [+/-]: "))))
(let ((frame (exwm-workspace--workspace-from-frame-or-index frame-or-index))
- old-frame container)
+ x-old y-old x-new y-new should-hide old-frame container)
(unless id (setq id (exwm--buffer->id (window-buffer))))
(with-current-buffer (exwm--id->buffer id)
(unless (eq exwm--frame frame)
@@ -712,6 +715,36 @@ INDEX must not exceed the current number of workspaces."
(concat " " name)))))
(setq old-frame exwm--frame
exwm--frame frame)
+ ;; Save the positions of new & old frames.
+ (with-slots ((x1 x)
+ (y1 y))
+ (exwm-workspace--get-geometry old-frame)
+ (with-slots ((x2 x)
+ (y2 y))
+ (exwm-workspace--get-geometry frame)
+ (setq x-old x1
+ y-old y1
+ x-new x2
+ y-new y2)))
+ (if (and (= x-old x-new)
+ (= y-old y-new))
+ ;; Switch to a workspace on the same output.
+ (setq should-hide t)
+ ;; Check if this frame has the largest timestamp of that output.
+ (let ((timestamp (frame-parameter frame 'exwm-timestamp))
+ (timestamp-active
+ (apply #'max
+ (mapcar (lambda (w)
+ (with-slots (x y)
+ (exwm-workspace--get-geometry w)
+ (if (and (= x x-new)
+ (= y y-new))
+ (frame-parameter w 'exwm-timestamp)
+ -1)))
+ exwm-workspace--list))))
+ (when (< timestamp timestamp-active)
+ ;; Switch to a workspace not active on another output.
+ (setq should-hide t))))
(if (not exwm--floating-frame)
;; Tiling.
(progn
@@ -724,31 +757,27 @@ INDEX must not exceed the current number of workspaces."
(exwm--id->buffer id))
(if (eq frame exwm-workspace--current)
(select-window (frame-selected-window frame))
- (exwm-layout--hide id)))
+ (when should-hide
+ (exwm-layout--hide id))))
;; Floating.
(setq container (frame-parameter exwm--floating-frame
'exwm-container))
- (with-slots ((x1 x)
- (y1 y))
- (exwm-workspace--get-geometry old-frame)
- (with-slots ((x2 x)
- (y2 y))
- (exwm-workspace--get-geometry frame)
- (unless (and (= x1 x2)
- (= y1 y2))
- (with-slots (x y)
- (xcb:+request-unchecked+reply exwm--connection
- (make-instance 'xcb:GetGeometry
- :drawable container))
- (setq x (+ x (- x2 x1))
- y (+ y (- y2 y1)))
- (exwm--set-geometry id x y nil nil)
- (exwm--set-geometry container x y nil nil)))))
+ (unless (and (= x-old x-new)
+ (= y-old y-new))
+ (with-slots (x y)
+ (xcb:+request-unchecked+reply exwm--connection
+ (make-instance 'xcb:GetGeometry
+ :drawable container))
+ (setq x (+ x (- x-new x-old))
+ y (+ y (- y-new y-old)))
+ (exwm--set-geometry id x y nil nil)
+ (exwm--set-geometry container x y nil nil)))
(if (exwm-workspace--minibuffer-own-frame-p)
(if (eq frame exwm-workspace--current)
(select-window (frame-root-window exwm--floating-frame))
(select-window (frame-selected-window exwm-workspace--current))
- (exwm-layout--hide id))
+ (when should-hide
+ (exwm-layout--hide id)))
;; The frame needs to be recreated since it won't use the
;; minibuffer on the new workspace.
;; The code is mostly copied from `exwm-floating--set-floating'.
@@ -808,7 +837,8 @@ INDEX must not exceed the current number of workspaces."
(if (eq frame exwm-workspace--current)
(with-current-buffer (exwm--id->buffer id)
(select-window (frame-root-window exwm--floating-frame)))
- (exwm-layout--hide id))))
+ (when should-hide
+ (exwm-layout--hide id)))))
;; Update the 'exwm-selected-window' frame parameter.
(when (not (eq frame exwm-workspace--current))
(with-current-buffer (exwm--id->buffer id)
@@ -1486,7 +1516,8 @@ applied to all subsequently created X frames."
;; Prevent frame parameters introduced by this module from being
;; saved/restored.
(dolist (i '(exwm-outer-id exwm-id exwm-container exwm-geometry
- fullscreen exwm-selected-window exwm-urgency))
+ exwm-selected-window exwm-timestamp exwm-urgency
+ fullscreen))
(push (cons i :never) frameset-filter-alist)))
(defun exwm-workspace--exit ()