Replay KeyPress events instead of fake them in line-mode
X windows in line-mode receive KeyPress events faked with SendEvent requests previously. This causes many problems including: * Some applications (e.g. xterm) ignore synthetic events completely * KeyPress and KeyRelease evnets arrive disorderly This commit makes EXWM exploiting AllowEvents requests (in ReplayKeyboard mode) to forward KeyPress events to X windows instead.
This commit is contained in:
		
							parent
							
								
									874c383672
								
							
						
					
					
						commit
						981293f06a
					
				
					 1 changed files with 24 additions and 53 deletions
				
			
		|  | @ -241,43 +241,12 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.") | ||||||
| (defvar exwm-input--temp-line-mode nil | (defvar exwm-input--temp-line-mode nil | ||||||
|   "Non-nil indicates it's in temporary line-mode for char-mode.") |   "Non-nil indicates it's in temporary line-mode for char-mode.") | ||||||
| 
 | 
 | ||||||
| ;; ;; This implementation has a problem that it also releases queued keys after |  | ||||||
| ;; ;; requesting AllowEvent. The client window will capture unexpected key events |  | ||||||
| ;; ;; in this case. |  | ||||||
| ;; ;; P.S.; to use this implementation, comment out the KeyRelease listener |  | ||||||
| ;; ;;       together with this one and make GrabKey in Sync mode. |  | ||||||
| ;; (cl-defmethod exwm-input--on-KeyPress-line-mode ((obj xcb:KeyPress)) |  | ||||||
| ;;   "Parse X KeyPress event to Emacs key event and then feed the command loop." |  | ||||||
| ;;   (with-slots (detail state) obj |  | ||||||
| ;;     (let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state)) |  | ||||||
| ;;           event window mode) |  | ||||||
| ;;       (when (and keysym |  | ||||||
| ;;                  (setq event (xcb:keysyms:keysym->event keysym state)) |  | ||||||
| ;;                  (or exwm-input--during-key-sequence |  | ||||||
| ;;                      (setq window (active-minibuffer-window)) |  | ||||||
| ;;                      (eq event ?\C-c)   ;mode-specific key |  | ||||||
| ;;                      (memq event exwm-input--global-prefix-keys) |  | ||||||
| ;;                      (memq event exwm-input-prefix-keys) |  | ||||||
| ;;                      (memq event |  | ||||||
| ;;                            exwm-input--simulation-prefix-keys))) |  | ||||||
| ;;         (setq mode xcb:Allow:SyncKeyboard) |  | ||||||
| ;;         (unless window (setq exwm-input--during-key-sequence t)) |  | ||||||
| ;;         (push event unread-command-events)) |  | ||||||
| ;;       (xcb:+request exwm--connection |  | ||||||
| ;;           (make-instance 'xcb:AllowEvents |  | ||||||
| ;;                          :mode (or mode xcb:Allow:ReplayKeyboard) |  | ||||||
| ;;                          :time xcb:Time:CurrentTime)) |  | ||||||
| ;;       (xcb:flush exwm--connection)))) |  | ||||||
| 
 |  | ||||||
| ;; This implementation has a drawback that some (legacy) applications |  | ||||||
| ;; (e.g. xterm) ignore the synthetic key events, making it only viable for EXWM |  | ||||||
| ;; to work in char-mode in such case. |  | ||||||
| (cl-defmethod exwm-input--on-KeyPress-line-mode ((obj xcb:KeyPress)) | (cl-defmethod exwm-input--on-KeyPress-line-mode ((obj xcb:KeyPress)) | ||||||
|   "Parse X KeyPress event to Emacs key event and then feed the command loop." |   "Parse X KeyPress event to Emacs key event and then feed the command loop." | ||||||
|   (with-slots (detail state) obj |   (with-slots (detail state) obj | ||||||
|     (let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state)) |     (let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state)) | ||||||
|           event minibuffer-window) |           event minibuffer-window mode) | ||||||
|       (if (and keysym |       (when (and keysym | ||||||
|                  (setq event (xcb:keysyms:keysym->event keysym state)) |                  (setq event (xcb:keysyms:keysym->event keysym state)) | ||||||
|                  (or exwm-input--during-key-sequence |                  (or exwm-input--during-key-sequence | ||||||
|                      (setq minibuffer-window (active-minibuffer-window)) |                      (setq minibuffer-window (active-minibuffer-window)) | ||||||
|  | @ -285,17 +254,14 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.") | ||||||
|                      (memq event exwm-input--global-prefix-keys) |                      (memq event exwm-input--global-prefix-keys) | ||||||
|                      (memq event exwm-input-prefix-keys) |                      (memq event exwm-input-prefix-keys) | ||||||
|                      (memq event exwm-input--simulation-prefix-keys))) |                      (memq event exwm-input--simulation-prefix-keys))) | ||||||
|           ;; Forward key to Emacs frame |         (setq mode xcb:Allow:AsyncKeyboard) | ||||||
|           (progn (unless minibuffer-window |         (unless minibuffer-window (setq exwm-input--during-key-sequence t)) | ||||||
|                    (setq exwm-input--during-key-sequence t)) |  | ||||||
|         (push event unread-command-events)) |         (push event unread-command-events)) | ||||||
|         ;; Forward key to window |  | ||||||
|       (xcb:+request exwm--connection |       (xcb:+request exwm--connection | ||||||
|             (make-instance 'xcb:SendEvent |           (make-instance 'xcb:AllowEvents | ||||||
|                            :propagate 0 :destination (slot-value obj 'event) |                          :mode (or mode xcb:Allow:ReplayKeyboard) | ||||||
|                            :event-mask xcb:EventMask:NoEvent |                          :time xcb:Time:CurrentTime)) | ||||||
|                            :event (xcb:marshal obj exwm--connection))) |       (xcb:flush exwm--connection)))) | ||||||
|         (xcb:flush exwm--connection))))) |  | ||||||
| 
 | 
 | ||||||
| (cl-defmethod exwm-input--on-KeyPress-char-mode ((obj xcb:KeyPress)) | (cl-defmethod exwm-input--on-KeyPress-char-mode ((obj xcb:KeyPress)) | ||||||
|   "Handle KeyPress event in char-mode." |   "Handle KeyPress event in char-mode." | ||||||
|  | @ -307,7 +273,12 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.") | ||||||
|           (setq exwm-input--temp-line-mode t |           (setq exwm-input--temp-line-mode t | ||||||
|                 exwm-input--during-key-sequence t) |                 exwm-input--during-key-sequence t) | ||||||
|           (exwm-input--grab-keyboard)) ;grab keyboard temporarily |           (exwm-input--grab-keyboard)) ;grab keyboard temporarily | ||||||
|         (push event unread-command-events))))) |         (push event unread-command-events)))) | ||||||
|  |   (xcb:+request exwm--connection | ||||||
|  |       (make-instance 'xcb:AllowEvents | ||||||
|  |                      :mode xcb:Allow:AsyncKeyboard | ||||||
|  |                      :time xcb:Time:CurrentTime)) | ||||||
|  |   (xcb:flush exwm--connection)) | ||||||
| 
 | 
 | ||||||
| (defun exwm-input--grab-keyboard (&optional id) | (defun exwm-input--grab-keyboard (&optional id) | ||||||
|   "Grab all key events on window ID." |   "Grab all key events on window ID." | ||||||
|  | @ -319,7 +290,7 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.") | ||||||
|                              :modifiers xcb:ModMask:Any |                              :modifiers xcb:ModMask:Any | ||||||
|                              :key xcb:Grab:Any |                              :key xcb:Grab:Any | ||||||
|                              :pointer-mode xcb:GrabMode:Async |                              :pointer-mode xcb:GrabMode:Async | ||||||
|                              :keyboard-mode xcb:GrabMode:Async)) |                              :keyboard-mode xcb:GrabMode:Sync)) | ||||||
|       (exwm--log "Failed to grab keyboard for #x%x" id)) |       (exwm--log "Failed to grab keyboard for #x%x" id)) | ||||||
|     (setq exwm--on-KeyPress 'exwm-input--on-KeyPress-line-mode))) |     (setq exwm--on-KeyPress 'exwm-input--on-KeyPress-line-mode))) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue