Support binding mouse events in line-mode

* exwm-input.el (exwm-input--event-passthrough-p): Predicate
checking whether an event should be forwarded to Emacs.
(exwm-input--on-KeyPress-line-mode): Use it.
* exwm-input.el (exwm-input--cache-event): Protect against
translations swallow the event.
* exwm-input.el (exwm-input--on-ButtonPress-line-mode)
(exwm-input--on-ButtonPress-char-mode): New functions.
(exwm-input--on-ButtonPress): Forward bound mouse events to Emacs
when in line-mode.
This commit is contained in:
Adrián Medraño Calvo 2018-10-08 12:00:00 +00:00
parent dff1ef6a3c
commit 57d0e9e1d3

View file

@ -87,7 +87,7 @@ defined in `exwm-mode-map' here."
value)))) value))))
(defcustom exwm-input-line-mode-passthrough nil (defcustom exwm-input-line-mode-passthrough nil
"Non-nil makes 'line-mode' forwards all events to Emacs." "Non-nil makes 'line-mode' forward all events to Emacs."
:type 'boolean) :type 'boolean)
;; Input focus update requests should be accumulated for a short time ;; Input focus update requests should be accumulated for a short time
@ -378,11 +378,11 @@ ARGS are additional arguments to CALLBACK."
(xcb:unmarshal obj data) (xcb:unmarshal obj data)
(exwm--log "major-mode=%s buffer=%s" (exwm--log "major-mode=%s buffer=%s"
major-mode (buffer-name (current-buffer))) major-mode (buffer-name (current-buffer)))
(with-slots (detail time event state) obj (with-slots (detail event state) obj
(setq button-event (xcb:keysyms:keysym->event exwm--connection (setq button-event (xcb:keysyms:keysym->event exwm--connection
detail state) detail state)
window (get-buffer-window (exwm--id->buffer event) t) buffer (exwm--id->buffer event)
buffer (window-buffer window)) window (get-buffer-window buffer t))
(cond ((and (eq button-event exwm-input-move-event) (cond ((and (eq button-event exwm-input-move-event)
;; Either an undecorated or a floating X window. ;; Either an undecorated or a floating X window.
(with-current-buffer buffer (with-current-buffer buffer
@ -414,11 +414,15 @@ ARGS are additional arguments to CALLBACK."
;; It has been reported that the `window' may have be deleted ;; It has been reported that the `window' may have be deleted
(if (window-live-p window) (if (window-live-p window)
(select-window window) (select-window window)
(setq window (setq window (get-buffer-window buffer t))
(get-buffer-window (exwm--id->buffer event) t))
(when window (select-window window)))) (when window (select-window window))))
;; The event should be replayed (with-current-buffer buffer
(setq mode xcb:Allow:ReplayPointer)))) (when (derived-mode-p 'exwm-mode)
(cl-case (exwm-input--current-input-mode)
(line-mode
(setq mode (exwm-input--on-ButtonPress-line-mode buffer button-event)))
(char-mode
(setq mode (exwm-input--on-ButtonPress-char-mode)))))))))
(xcb:+request exwm--connection (xcb:+request exwm--connection
(make-instance 'xcb:AllowEvents :mode mode :time xcb:Time:CurrentTime)) (make-instance 'xcb:AllowEvents :mode mode :time xcb:Time:CurrentTime))
(xcb:flush exwm--connection))) (xcb:flush exwm--connection)))
@ -575,24 +579,19 @@ instead."
;; Attempt to translate this key sequence. ;; Attempt to translate this key sequence.
(setq exwm-input--line-mode-cache (setq exwm-input--line-mode-cache
(exwm-input--translate exwm-input--line-mode-cache)) (exwm-input--translate exwm-input--line-mode-cache))
;; When the key sequence is complete. ;; When the key sequence is complete (not a keymap).
(unless (keymapp (key-binding exwm-input--line-mode-cache)) ;; Note that `exwm-input--line-mode-cache' might get translated to nil, for
;; example 'mouse--down-1-maybe-follows-link' does this.
(unless (and exwm-input--line-mode-cache
(keymapp (key-binding exwm-input--line-mode-cache)))
(setq exwm-input--line-mode-cache nil) (setq exwm-input--line-mode-cache nil)
(when exwm-input--temp-line-mode (when exwm-input--temp-line-mode
(setq exwm-input--temp-line-mode nil) (setq exwm-input--temp-line-mode nil)
(exwm-input--release-keyboard)))) (exwm-input--release-keyboard))))
(defun exwm-input--on-KeyPress-line-mode (key-press raw-data) (defun exwm-input--event-passthrough-p (event)
"Parse X KeyPress event to Emacs key event and then feed the command loop." "Whether EVENT should be passed to Emacs.
(with-slots (detail state) key-press Current buffer must be an `exwm-mode' buffer."
(let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state))
event raw-event mode)
(exwm--log "%s" keysym)
(when (and (/= 0 (car keysym))
(setq raw-event (xcb:keysyms:keysym->event
exwm--connection (car keysym)
(logand state (lognot (cdr keysym)))))
(setq event (exwm-input--mimic-read-event raw-event))
(or exwm-input-line-mode-passthrough (or exwm-input-line-mode-passthrough
exwm-input--during-command exwm-input--during-command
;; Forward the event when there is an incomplete key ;; Forward the event when there is an incomplete key
@ -607,6 +606,19 @@ instead."
(vector event))) (vector event)))
(lookup-key (current-local-map) (vector event)) (lookup-key (current-local-map) (vector event))
(gethash event exwm-input--simulation-keys))) (gethash event exwm-input--simulation-keys)))
(defun exwm-input--on-KeyPress-line-mode (key-press raw-data)
"Parse X KeyPress event to Emacs key event and then feed the command loop."
(with-slots (detail state) key-press
(let ((keysym (xcb:keysyms:keycode->keysym exwm--connection detail state))
event raw-event mode)
(exwm--log "%s" keysym)
(when (and (/= 0 (car keysym))
(setq raw-event (xcb:keysyms:keysym->event
exwm--connection (car keysym)
(logand state (lognot (cdr keysym)))))
(setq event (exwm-input--mimic-read-event raw-event))
(exwm-input--event-passthrough-p event))
(setq mode xcb:Allow:AsyncKeyboard) (setq mode xcb:Allow:AsyncKeyboard)
(exwm-input--cache-event event) (exwm-input--cache-event event)
(exwm-input--unread-event raw-event)) (exwm-input--unread-event raw-event))
@ -658,6 +670,31 @@ instead."
:time xcb:Time:CurrentTime)) :time xcb:Time:CurrentTime))
(xcb:flush exwm--connection)) (xcb:flush exwm--connection))
(defun exwm-input--on-ButtonPress-line-mode (buffer button-event)
"Handle button events in line mode.
BUFFER is the `exwm-mode' buffer the event was generated
on. BUTTON-EVENT is the X event converted into an Emacs event.
The return value is used as event_mode to release the original
button event."
(with-current-buffer buffer
(let ((read-event (exwm-input--mimic-read-event button-event)))
(if (and read-event
(exwm-input--event-passthrough-p read-event))
;; The event should be forwarded to emacs
(progn
(exwm-input--cache-event read-event)
(exwm-input--unread-event button-event)
xcb:Allow:SyncPointer)
;; The event should be replayed
xcb:Allow:ReplayPointer))))
(defun exwm-input--on-ButtonPress-char-mode ()
"Handle button events in char-mode.
The return value is used as event_mode to release the original
button event."
xcb:Allow:ReplayPointer)
(defun exwm-input--current-input-mode () (defun exwm-input--current-input-mode ()
"Return current input mode. "Return current input mode.
The return value is one of the symbols \\='line-mode or \\=`char-mode. The return value is one of the symbols \\='line-mode or \\=`char-mode.