Add support for attachable/detachable minibuffer
* exwm-workspace.el (exwm-workspace--update-minibuffer-height): Renamed from `exwm-workspace--update-minibuffer' to better reflect its usage. * exwm-input.el (exwm-input--update-focus): Directly put the floating X window at top since the minibuffer is no longer a sibling. * exwm-workspace.el (exwm-workspace--resize-minibuffer-frame): Calculate position in absolute coordinate; put minibuffer at bottom by default; resize the minibuffer frame with ConfigureWindow rather than `set-frame-width'. (exwm-workspace-switch): No need to reparent minibuffer any more. (exwm-workspace--on-ConfigureNotify): Calculate position in absolute coordinate. (exwm-workspace--show-minibuffer, exwm-workspace--hide-minibuffer): Show/Hide the minibuffer by adjusting the stacking order rather than mapping/unmapping. (exwm-workspace--init): Map the minibuffer frame container on creation. * exwm-workspace.el (exwm-workspace--minibuffer-attached-p): New function telling whether the minibuffer is attached. (exwm-workspace--attached-minibuffer-height): New variable storing the height of the attached minibuffer. (exwm-workspace-attach-minibuffer, exwm-workspace-detach-minibuffer): New functions for attaching/detaching the minibuffer. * exwm-workspace.el (exwm-workspace--show-minibuffer): Remove the workaround for minibuffer cursor (seems fixed).
This commit is contained in:
		
							parent
							
								
									624c72945a
								
							
						
					
					
						commit
						3909f65bae
					
				
					 2 changed files with 113 additions and 59 deletions
				
			
		|  | @ -125,24 +125,11 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.") | |||
|             (exwm-input--set-focus exwm--id) | ||||
|             (when exwm--floating-frame | ||||
|               ;; Adjust stacking orders of the floating container. | ||||
|               (if (exwm-workspace--minibuffer-own-frame-p) | ||||
|                   ;; Put this floating X window just below the minibuffer. | ||||
|                   (xcb:+request exwm--connection | ||||
|                       (make-instance 'xcb:ConfigureWindow | ||||
|                                      :window exwm--container | ||||
|                                      :value-mask | ||||
|                                      (logior xcb:ConfigWindow:Sibling | ||||
|                                              xcb:ConfigWindow:StackMode) | ||||
|                                      :sibling (frame-parameter | ||||
|                                                exwm-workspace--minibuffer | ||||
|                                                'exwm-container) | ||||
|                                      :stack-mode xcb:StackMode:Below)) | ||||
|                 ;; Put this floating X window at top. | ||||
|                 (xcb:+request exwm--connection | ||||
|                     (make-instance 'xcb:ConfigureWindow | ||||
|                                    :window exwm--container | ||||
|                                    :value-mask xcb:ConfigWindow:StackMode | ||||
|                                    :stack-mode xcb:StackMode:Above))) | ||||
|               (xcb:+request exwm--connection | ||||
|                   (make-instance 'xcb:ConfigureWindow | ||||
|                                  :window exwm--container | ||||
|                                  :value-mask xcb:ConfigWindow:StackMode | ||||
|                                  :stack-mode xcb:StackMode:Above)) | ||||
|               ;; This floating X window might be hide by `exwm-floating-hide'. | ||||
|               (when (exwm-layout--iconic-state-p) | ||||
|                 (exwm-layout--set-state exwm--id | ||||
|  |  | |||
|  | @ -308,20 +308,32 @@ Value nil means to use the default position which is fixed at bottom, while | |||
|                                     'exwm-container)) | ||||
|         y width) | ||||
|     (setq y (if (eq exwm-workspace-minibuffer-position 'top) | ||||
|                 0 | ||||
|               (- (aref workarea 3) | ||||
|                  (frame-pixel-height exwm-workspace--minibuffer))) | ||||
|                 (- (aref workarea 1) | ||||
|                    exwm-workspace--attached-minibuffer-height) | ||||
|               ;; Reset the frame size. | ||||
|               (set-frame-height exwm-workspace--minibuffer 1) | ||||
|               (redisplay)               ;FIXME. | ||||
|               (+ (aref workarea 1) (aref workarea 3) | ||||
|                  (- (frame-pixel-height exwm-workspace--minibuffer)) | ||||
|                  exwm-workspace--attached-minibuffer-height)) | ||||
|           width (aref workarea 2)) | ||||
|     (xcb:+request exwm--connection | ||||
|         (make-instance 'xcb:ConfigureWindow | ||||
|                        :window container | ||||
|                        :value-mask (logior xcb:ConfigWindow:Y | ||||
|                        :value-mask (logior xcb:ConfigWindow:X | ||||
|                                            xcb:ConfigWindow:Y | ||||
|                                            xcb:ConfigWindow:Width | ||||
|                                            xcb:ConfigWindow:StackMode) | ||||
|                        :x (aref workarea 0) | ||||
|                        :y y | ||||
|                        :width width | ||||
|                        :stack-mode xcb:StackMode:Above)) | ||||
|     (set-frame-width exwm-workspace--minibuffer width nil t))) | ||||
|                        :stack-mode xcb:StackMode:Below)) | ||||
|     (xcb:+request exwm--connection | ||||
|         (make-instance 'xcb:ConfigureWindow | ||||
|                        :window (frame-parameter exwm-workspace--minibuffer | ||||
|                                                 'exwm-outer-id) | ||||
|                        :value-mask xcb:ConfigWindow:Width | ||||
|                        :width width)))) | ||||
| 
 | ||||
| (defun exwm-workspace--switch-map-nth-prefix (&optional prefix-digits) | ||||
|   "Allow selecting a workspace by number. | ||||
|  | @ -428,17 +440,11 @@ The optional FORCE option is for internal use only." | |||
|                                      ;; Might be aborted by then. | ||||
|                                      (when (active-minibuffer-window) | ||||
|                                        (abort-recursive-edit))))) | ||||
|       (if (not (exwm-workspace--minibuffer-own-frame-p)) | ||||
|           (setq default-minibuffer-frame frame) | ||||
|         ;; Resize/reposition the minibuffer frame | ||||
|         (xcb:+request exwm--connection | ||||
|             (make-instance 'xcb:ReparentWindow | ||||
|                            :window | ||||
|                            (frame-parameter exwm-workspace--minibuffer | ||||
|                                             'exwm-container) | ||||
|                            :parent (frame-parameter frame 'exwm-workspace) | ||||
|                            :x 0 :y 0)) | ||||
|         (exwm-workspace--resize-minibuffer-frame)) | ||||
|       (if (exwm-workspace--minibuffer-own-frame-p) | ||||
|           ;; Resize the minibuffer frame. | ||||
|           (exwm-workspace--resize-minibuffer-frame) | ||||
|         ;; Set a default minibuffer frame. | ||||
|         (setq default-minibuffer-frame frame)) | ||||
|       ;; Hide windows in other workspaces by preprending a space | ||||
|       (unless exwm-workspace-show-all-buffers | ||||
|         (dolist (i exwm--id-buffer-alist) | ||||
|  | @ -778,8 +784,59 @@ INDEX must not exceed the current number of workspaces." | |||
|     (xcb:flush exwm--connection) | ||||
|     frame)) | ||||
| 
 | ||||
| (defun exwm-workspace--update-minibuffer (&optional echo-area) | ||||
|   "Update the minibuffer frame." | ||||
| (defsubst exwm-workspace--minibuffer-attached-p () | ||||
|   "Return non-nil if the minibuffer is attached. | ||||
| 
 | ||||
| Please check `exwm-workspace--minibuffer-own-frame-p' first." | ||||
|   (assq (frame-parameter exwm-workspace--minibuffer 'exwm-container) | ||||
|         exwm-workspace--id-struts-alist)) | ||||
| 
 | ||||
| (defvar exwm-workspace--attached-minibuffer-height 0 | ||||
|   "Height (in pixel) of the attached minibuffer. | ||||
| 
 | ||||
| If the minibuffer is detached, this value is 0.") | ||||
| 
 | ||||
| (defun exwm-workspace-attach-minibuffer () | ||||
|   "Attach the minibuffer so that it always shows." | ||||
|   (interactive) | ||||
|   (when (and (exwm-workspace--minibuffer-own-frame-p) | ||||
|              (not (exwm-workspace--minibuffer-attached-p))) | ||||
|     ;; Reset the frame size. | ||||
|     (set-frame-height exwm-workspace--minibuffer 1) | ||||
|     (redisplay)                       ;FIXME. | ||||
|     (setq exwm-workspace--attached-minibuffer-height | ||||
|           (frame-pixel-height exwm-workspace--minibuffer)) | ||||
|     (let ((container (frame-parameter exwm-workspace--minibuffer | ||||
|                                       'exwm-container))) | ||||
|       (push (cons container | ||||
|                   (if (eq exwm-workspace-minibuffer-position 'top) | ||||
|                       (vector 0 0 exwm-workspace--attached-minibuffer-height 0) | ||||
|                     (vector 0 0 0 exwm-workspace--attached-minibuffer-height))) | ||||
|             exwm-workspace--id-struts-alist) | ||||
|       (exwm-workspace--update-struts) | ||||
|       (exwm-workspace--update-workareas) | ||||
|       (dolist (f exwm-workspace--list) | ||||
|         (exwm-workspace--set-fullscreen f)) | ||||
|       (exwm-workspace--show-minibuffer)))) | ||||
| 
 | ||||
| (defun exwm-workspace-detach-minibuffer () | ||||
|   "Detach the minibuffer so that it automatically hides." | ||||
|   (interactive) | ||||
|   (when (and (exwm-workspace--minibuffer-own-frame-p) | ||||
|              (exwm-workspace--minibuffer-attached-p)) | ||||
|     (setq exwm-workspace--attached-minibuffer-height 0) | ||||
|     (let ((container (frame-parameter exwm-workspace--minibuffer | ||||
|                                       'exwm-container))) | ||||
|       (setq exwm-workspace--id-struts-alist | ||||
|             (assq-delete-all container exwm-workspace--id-struts-alist)) | ||||
|       (exwm-workspace--update-struts) | ||||
|       (exwm-workspace--update-workareas) | ||||
|       (dolist (f exwm-workspace--list) | ||||
|         (exwm-workspace--set-fullscreen f)) | ||||
|       (exwm-workspace--hide-minibuffer)))) | ||||
| 
 | ||||
| (defun exwm-workspace--update-minibuffer-height (&optional echo-area) | ||||
|   "Update the minibuffer frame height." | ||||
|   (let ((height | ||||
|          (with-current-buffer | ||||
|              (window-buffer (minibuffer-window exwm-workspace--minibuffer)) | ||||
|  | @ -802,7 +859,7 @@ INDEX must not exceed the current number of workspaces." | |||
| (defun exwm-workspace--on-ConfigureNotify (data _synthetic) | ||||
|   "Adjust the container to fit the minibuffer frame." | ||||
|   (let ((obj (make-instance 'xcb:ConfigureNotify)) | ||||
|         value-mask y) | ||||
|         workarea y) | ||||
|     (xcb:unmarshal obj data) | ||||
|     (with-slots (window height) obj | ||||
|       (when (eq (frame-parameter exwm-workspace--minibuffer 'exwm-outer-id) | ||||
|  | @ -818,19 +875,19 @@ INDEX must not exceed the current number of workspaces." | |||
|                              :window window | ||||
|                              :value-mask xcb:ConfigWindow:Height | ||||
|                              :height height))) | ||||
|         (if (eq exwm-workspace-minibuffer-position 'top) | ||||
|             (setq value-mask xcb:ConfigWindow:Height | ||||
|                   y 0) | ||||
|           (setq value-mask (logior xcb:ConfigWindow:Y xcb:ConfigWindow:Height) | ||||
|                 y (- (aref (elt exwm-workspace--workareas | ||||
|                                 exwm-workspace-current-index) | ||||
|                            3) | ||||
|                      height))) | ||||
|         (setq workarea (elt exwm-workspace--workareas | ||||
|                             exwm-workspace-current-index) | ||||
|               y (if (eq exwm-workspace-minibuffer-position 'top) | ||||
|                     (- (aref workarea 1) | ||||
|                        exwm-workspace--attached-minibuffer-height) | ||||
|                   (+ (aref workarea 1) (aref workarea 3) (- height) | ||||
|                      exwm-workspace--attached-minibuffer-height))) | ||||
|         (xcb:+request exwm--connection | ||||
|             (make-instance 'xcb:ConfigureWindow | ||||
|                            :window (frame-parameter exwm-workspace--minibuffer | ||||
|                                                     'exwm-container) | ||||
|                            :value-mask value-mask | ||||
|                            :value-mask (logior xcb:ConfigWindow:Y | ||||
|                                                xcb:ConfigWindow:Height) | ||||
|                            :y y | ||||
|                            :height height)) | ||||
|         (xcb:flush exwm--connection))))) | ||||
|  | @ -851,26 +908,31 @@ INDEX must not exceed the current number of workspaces." | |||
|     (setq exwm-workspace--display-echo-area-timer nil)) | ||||
|   ;; Show the minibuffer frame. | ||||
|   (xcb:+request exwm--connection | ||||
|       (make-instance 'xcb:MapWindow | ||||
|       (make-instance 'xcb:ConfigureWindow | ||||
|                      :window (frame-parameter exwm-workspace--minibuffer | ||||
|                                               'exwm-container))) | ||||
|                                               'exwm-container) | ||||
|                      :value-mask xcb:ConfigWindow:StackMode | ||||
|                      :stack-mode xcb:StackMode:Above)) | ||||
|   (xcb:flush exwm--connection) | ||||
|   ;; Unfortunately we need the following lines to workaround a cursor | ||||
|   ;; flickering issue for line-mode floating X windows.  They just make the | ||||
|   ;; minibuffer appear to be focused. | ||||
|   (with-current-buffer (window-buffer (minibuffer-window | ||||
|                                        exwm-workspace--minibuffer)) | ||||
|     (setq cursor-in-non-selected-windows | ||||
|           (frame-parameter exwm-workspace--minibuffer 'cursor-type)))) | ||||
| 
 | ||||
|   ;; (FIXED?) | ||||
|   ;; (with-current-buffer (window-buffer (minibuffer-window | ||||
|   ;;                                      exwm-workspace--minibuffer)) | ||||
|   ;;   (setq cursor-in-non-selected-windows | ||||
|   ;;         (frame-parameter exwm-workspace--minibuffer 'cursor-type))) | ||||
|   ) | ||||
| 
 | ||||
| (defun exwm-workspace--hide-minibuffer () | ||||
|   "Hide the minibuffer frame." | ||||
|   ;; Hide the minibuffer frame. | ||||
|   (xcb:+request exwm--connection | ||||
|       (make-instance 'xcb:UnmapWindow | ||||
|       (make-instance 'xcb:ConfigureWindow | ||||
|                      :window (frame-parameter exwm-workspace--minibuffer | ||||
|                                               'exwm-container))) | ||||
|                                               'exwm-container) | ||||
|                      :value-mask xcb:ConfigWindow:StackMode | ||||
|                      :stack-mode xcb:StackMode:Below)) | ||||
|   (xcb:flush exwm--connection)) | ||||
| 
 | ||||
| (defun exwm-workspace--on-minibuffer-setup () | ||||
|  | @ -878,7 +940,7 @@ INDEX must not exceed the current number of workspaces." | |||
|   (when (and (= 1 (minibuffer-depth)) | ||||
|              ;; Exclude non-graphical frames. | ||||
|              (frame-parameter nil 'exwm-outer-id)) | ||||
|     (add-hook 'post-command-hook #'exwm-workspace--update-minibuffer) | ||||
|     (add-hook 'post-command-hook #'exwm-workspace--update-minibuffer-height) | ||||
|     (exwm-workspace--show-minibuffer) | ||||
|     ;; Set input focus on the Emacs frame | ||||
|     (x-focus-frame (window-frame (minibuffer-selected-window))))) | ||||
|  | @ -888,7 +950,7 @@ INDEX must not exceed the current number of workspaces." | |||
|   (when (and (= 1 (minibuffer-depth)) | ||||
|              ;; Exclude non-graphical frames. | ||||
|              (frame-parameter nil 'exwm-outer-id)) | ||||
|     (remove-hook 'post-command-hook #'exwm-workspace--update-minibuffer) | ||||
|     (remove-hook 'post-command-hook #'exwm-workspace--update-minibuffer-height) | ||||
|     (exwm-workspace--hide-minibuffer))) | ||||
| 
 | ||||
| (defvar exwm-input--during-command) | ||||
|  | @ -900,7 +962,7 @@ INDEX must not exceed the current number of workspaces." | |||
|              (frame-parameter nil 'exwm-outer-id) | ||||
|              (or (current-message) | ||||
|                  cursor-in-echo-area)) | ||||
|     (exwm-workspace--update-minibuffer t) | ||||
|     (exwm-workspace--update-minibuffer-height t) | ||||
|     (exwm-workspace--show-minibuffer) | ||||
|     (unless (or (not exwm-workspace-display-echo-area-timeout) | ||||
|                 exwm-input--during-command ;e.g. read-event | ||||
|  | @ -1217,9 +1279,14 @@ applied to all subsequently created X frames." | |||
|              (make-instance 'xcb:ewmh:set-_NET_WM_NAME | ||||
|                             :window container | ||||
|                             :data "Minibuffer container"))) | ||||
|         ;; Reparent the minibuffer frame to the container. | ||||
|         (xcb:+request exwm--connection | ||||
|             (make-instance 'xcb:ReparentWindow | ||||
|                            :window outer-id :parent container :x 0 :y 0)) | ||||
|         ;; Map the container. | ||||
|         (xcb:+request exwm--connection | ||||
|             (make-instance 'xcb:MapWindow | ||||
|                            :window container)) | ||||
|         ;; Attach event listener for monitoring the frame | ||||
|         (xcb:+request exwm--connection | ||||
|             (make-instance 'xcb:ChangeWindowAttributes | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue