mirror of
https://github.com/emacs-exwm/exwm.git
synced 2024-11-23 13:07:59 +01:00
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,61 +241,27 @@ It's updated in several occasions, and only used by `exwm-input--set-focus'.")
|
|||
(defvar exwm-input--temp-line-mode nil
|
||||
"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))
|
||||
"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 minibuffer-window)
|
||||
(if (and keysym
|
||||
(setq event (xcb:keysyms:keysym->event keysym state))
|
||||
(or exwm-input--during-key-sequence
|
||||
(setq minibuffer-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)))
|
||||
;; Forward key to Emacs frame
|
||||
(progn (unless minibuffer-window
|
||||
(setq exwm-input--during-key-sequence t))
|
||||
(push event unread-command-events))
|
||||
;; Forward key to window
|
||||
(xcb:+request exwm--connection
|
||||
(make-instance 'xcb:SendEvent
|
||||
:propagate 0 :destination (slot-value obj 'event)
|
||||
:event-mask xcb:EventMask:NoEvent
|
||||
:event (xcb:marshal obj exwm--connection)))
|
||||
(xcb:flush exwm--connection)))))
|
||||
event minibuffer-window mode)
|
||||
(when (and keysym
|
||||
(setq event (xcb:keysyms:keysym->event keysym state))
|
||||
(or exwm-input--during-key-sequence
|
||||
(setq minibuffer-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:AsyncKeyboard)
|
||||
(unless minibuffer-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))))
|
||||
|
||||
(cl-defmethod exwm-input--on-KeyPress-char-mode ((obj xcb:KeyPress))
|
||||
"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
|
||||
exwm-input--during-key-sequence t)
|
||||
(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)
|
||||
"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
|
||||
:key xcb:Grab:Any
|
||||
: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))
|
||||
(setq exwm--on-KeyPress 'exwm-input--on-KeyPress-line-mode)))
|
||||
|
||||
|
|
Loading…
Reference in a new issue