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) | ||||
|   "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)))) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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')." | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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))))) | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
							
								
								
									
										2
									
								
								exwm.el
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								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) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue