about summary refs log tree commit diff
path: root/exwm-input.el
diff options
context:
space:
mode:
Diffstat (limited to 'exwm-input.el')
-rw-r--r--exwm-input.el74
1 files changed, 47 insertions, 27 deletions
diff --git a/exwm-input.el b/exwm-input.el
index a7fb16a1755f..d0ae4ad81250 100644
--- a/exwm-input.el
+++ b/exwm-input.el
@@ -1,6 +1,6 @@
 ;;; exwm-input.el --- Input Module for EXWM  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2018 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2019 Free Software Foundation, Inc.
 
 ;; Author: Chris Feng <chris.w.feng@gmail.com>
 
@@ -117,6 +117,9 @@ defined in `exwm-mode-map' here."
 
 (defvar exwm-input--simulation-keys nil "Simulation keys in line-mode.")
 
+(defvar exwm-input--skip-buffer-list-update nil
+  "Skip the upcoming 'buffer-list-update'.")
+
 (defvar exwm-input--temp-line-mode nil
   "Non-nil indicates it's in temporary line-mode for char-mode.")
 
@@ -224,7 +227,7 @@ ARGS are additional arguments to CALLBACK."
     (with-slots (time root event root-x root-y event-x event-y state) evt
       (setq buffer (exwm--id->buffer event)
             window (get-buffer-window buffer t))
-      (exwm--log "EnterNotify: buffer=%s; window=%s" buffer window)
+      (exwm--log "buffer=%s; window=%s" buffer window)
       (when (and buffer window (not (eq window (selected-window))))
         (setq frame (window-frame window)
               frame-xid (frame-parameter frame 'exwm-id))
@@ -260,12 +263,14 @@ ARGS are additional arguments to CALLBACK."
         (xcb:flush exwm--connection)))))
 
 (defun exwm-input--on-keysyms-update ()
+  (exwm--log)
   (let ((exwm-input--global-prefix-keys nil))
     (exwm-input--update-global-prefix-keys)))
 
 (defun exwm-input--on-buffer-list-update ()
   "Run in `buffer-list-update-hook' to track input focus."
   (when (and (not (eq this-command #'handle-switch-frame))
+             (not exwm-input--skip-buffer-list-update)
              (not (exwm-workspace--client-p))
              ;; The following conditions filter out events relating to temp
              ;; buffers.
@@ -380,6 +385,7 @@ ARGS are additional arguments to CALLBACK."
             buffer (exwm--id->buffer event)
             window (get-buffer-window buffer t))
       (cond ((and (eq button-event exwm-input-move-event)
+                  buffer
                   ;; Either an undecorated or a floating X window.
                   (with-current-buffer buffer
                     (or (not (derived-mode-p 'exwm-mode))
@@ -388,12 +394,13 @@ ARGS are additional arguments to CALLBACK."
              (exwm-floating--start-moveresize
               event xcb:ewmh:_NET_WM_MOVERESIZE_MOVE))
             ((and (eq button-event exwm-input-resize-event)
+                  buffer
                   (with-current-buffer buffer
                     (or (not (derived-mode-p 'exwm-mode))
                         exwm--floating-frame)))
              ;; Resize
              (exwm-floating--start-moveresize event))
-            (t
+            (buffer
              ;; Click to focus
              (unless (eq window (selected-window))
                (setq frame (window-frame window))
@@ -412,13 +419,18 @@ ARGS are additional arguments to CALLBACK."
                    (select-window window)
                  (setq window (get-buffer-window buffer t))
                  (when window (select-window window))))
+             ;; Also process keybindings.
              (with-current-buffer buffer
                (when (derived-mode-p 'exwm-mode)
                  (cl-case exwm--input-mode
                    (line-mode
-                    (setq mode (exwm-input--on-ButtonPress-line-mode buffer button-event)))
+                    (setq mode (exwm-input--on-ButtonPress-line-mode
+                                buffer button-event)))
                    (char-mode
-                    (setq mode (exwm-input--on-ButtonPress-char-mode)))))))))
+                    (setq mode (exwm-input--on-ButtonPress-char-mode)))))))
+            (t
+             ;; Replay this event by default.
+             (setq mode xcb:Allow:ReplayPointer))))
     (xcb:+request exwm--connection
         (make-instance 'xcb:AllowEvents :mode mode :time xcb:Time:CurrentTime))
     (xcb:flush exwm--connection))
@@ -491,6 +503,7 @@ ARGS are additional arguments to CALLBACK."
     (xcb:flush exwm--connection)))
 
 (defun exwm-input--set-key (key command)
+  (exwm--log "key: %s, command: %s" key command)
   (global-set-key key command)
   (cl-pushnew key exwm-input--global-keys))
 
@@ -534,9 +547,9 @@ instead."
     (exwm-input--update-global-prefix-keys)))
 
 ;; Putting (t . EVENT) into `unread-command-events' does not really work
-;; as documented for Emacs < 27.
+;; as documented for Emacs < 26.2.
 (eval-and-compile
-  (if (< emacs-major-version 27)
+  (if (string-version-lessp emacs-version "26.2")
       (defsubst exwm-input--unread-event (event)
         (setq unread-command-events
               (append unread-command-events (list event))))
@@ -570,8 +583,9 @@ instead."
           (cl-return-from exwm-input--translate translation)))))
   key)
 
-(defun exwm-input--cache-event (event)
+(defun exwm-input--cache-event (event &optional temp-line-mode)
   "Cache EVENT."
+  (exwm--log "%s" event)
   (setq exwm-input--line-mode-cache
         (vconcat exwm-input--line-mode-cache (vector event)))
   ;; Attempt to translate this key sequence.
@@ -580,8 +594,12 @@ instead."
   ;; When the key sequence is complete (not a keymap).
   ;; 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)))
+  (if (and exwm-input--line-mode-cache
+           (keymapp (key-binding exwm-input--line-mode-cache)))
+      ;; Grab keyboard temporarily to intercept the complete key sequence.
+      (when temp-line-mode
+        (setq exwm-input--temp-line-mode t)
+        (exwm-input--grab-keyboard))
     (setq exwm-input--line-mode-cache nil)
     (when exwm-input--temp-line-mode
       (setq exwm-input--temp-line-mode nil)
@@ -657,10 +675,7 @@ Current buffer must be an `exwm-mode' buffer."
                  (setq event (exwm-input--mimic-read-event raw-event)))
         (if (not (derived-mode-p 'exwm-mode))
             (exwm-input--unread-event raw-event)
-          ;; Grab keyboard temporarily.
-          (setq exwm-input--temp-line-mode t)
-          (exwm-input--grab-keyboard)
-          (exwm-input--cache-event event)
+          (exwm-input--cache-event event t)
           (exwm-input--unread-event raw-event)))))
   (xcb:+request exwm--connection
       (make-instance 'xcb:AllowEvents
@@ -677,6 +692,7 @@ 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)))
+      (exwm--log "%s" read-event)
       (if (and read-event
                (exwm-input--event-passthrough-p read-event))
           ;; The event should be forwarded to emacs
@@ -691,10 +707,12 @@ button event."
   "Handle button events in char-mode.
 The return value is used as event_mode to release the original
 button event."
+  (exwm--log)
   xcb:Allow:ReplayPointer)
 
 (defun exwm-input--update-mode-line (id)
   "Update the propertized `mode-line-process' for window ID."
+  (exwm--log "#x%x" id)
   (let (help-echo cmd mode)
     (cl-case exwm--input-mode
       (line-mode
@@ -826,6 +844,7 @@ button event."
 EXWM will prompt for the key to send.  This command can be prefixed to send
 multiple keys."
   (interactive "p")
+  (exwm--log)
   (unless (derived-mode-p 'exwm-mode)
     (cl-return-from exwm-input-send-next-key))
   (when (> times 12) (setq times 12))
@@ -844,6 +863,7 @@ multiple keys."
 
 (defun exwm-input--set-simulation-keys (simulation-keys &optional no-refresh)
   "Set simulation keys."
+  (exwm--log "%s" simulation-keys)
   (unless no-refresh
     ;; Unbind simulation keys.
     (let ((hash (buffer-local-value 'exwm-input--simulation-keys
@@ -894,14 +914,15 @@ Notes:
 * Setting the value directly (rather than customizing it) after EXWM
   finishes initialization has no effect.
 * Original-keys consist of multiple key events are only supported in Emacs
-  27 and later.
+  26.2 and later.
 * A minority of applications do not accept simulated keys by default.  It's
   required to customize them to accept events sent by SendEvent.
 * The predefined examples in the Customize interface are not guaranteed to
   work for all applications.  This can be tweaked on a per application basis
   with `exwm-input-set-local-simulation-keys'."
-  :type '(alist :key-type (choice (key-sequence :tag "Original"))
-                :value-type (choice (key-sequence :tag "Move left" [left])
+  :type '(alist :key-type (key-sequence :tag "Original")
+                :value-type (choice (key-sequence :tag "User-defined")
+                                    (key-sequence :tag "Move left" [left])
                                     (key-sequence :tag "Move right" [right])
                                     (key-sequence :tag "Move up" [up])
                                     (key-sequence :tag "Move down" [down])
@@ -913,8 +934,7 @@ Notes:
                                     (key-sequence :tag "Paste" [C-v])
                                     (key-sequence :tag "Delete" [delete])
                                     (key-sequence :tag "Delete to EOL"
-                                                  [S-end delete])
-                                    (key-sequence :tag "User-defined")))
+                                                  [S-end delete])))
   :set (lambda (symbol value)
          (set symbol value)
          (exwm-input--set-simulation-keys value)))
@@ -945,6 +965,7 @@ ends unless it's specifically saved in the Customize interface for
                         (format "Simulate %s as" (key-description original))
                         ?\C-g)))
      (list original simulated)))
+  (exwm--log "original: %s, simulated: %s" original-key simulated-key)
   (when (and original-key simulated-key)
     (let ((entry `((,original-key . ,simulated-key))))
       (setq exwm-input-simulation-keys (append exwm-input-simulation-keys
@@ -953,6 +974,7 @@ ends unless it's specifically saved in the Customize interface for
 
 (defun exwm-input--unset-simulation-keys ()
   "Clear simulation keys and key bindings defined."
+  (exwm--log)
   (when (hash-table-p exwm-input--simulation-keys)
     (maphash (lambda (key _value)
                (when (sequencep key)
@@ -965,6 +987,7 @@ ends unless it's specifically saved in the Customize interface for
 
 SIMULATION-KEYS is an alist of the form (original-key . simulated-key),
 where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
+  (exwm--log)
   (make-local-variable 'exwm-input--simulation-keys)
   (use-local-map (copy-keymap exwm-mode-map))
   (let ((exwm-input--local-simulation-keys t))
@@ -974,6 +997,7 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
 (cl-defun exwm-input-send-simulation-key (times)
   "Fake a key event according to the last input key sequence."
   (interactive "p")
+  (exwm--log)
   (unless (derived-mode-p 'exwm-mode)
     (cl-return-from exwm-input-send-simulation-key))
   (let ((keys (gethash (this-single-command-keys)
@@ -993,6 +1017,7 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
 
 (defun exwm-input--init ()
   "Initialize the keyboard module."
+  (exwm--log)
   ;; Refresh keyboard mapping
   (xcb:keysyms:init exwm--connection #'exwm-input--on-keysyms-update)
   ;; Create the X window and intern the atom used to fetch timestamp.
@@ -1015,14 +1040,7 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
       (make-instance 'xcb:ewmh:set-_NET_WM_NAME
                      :window exwm-input--timestamp-window
                      :data "EXWM: exwm-input--timestamp-window"))
-  (let ((atom "_TIME"))
-    (setq exwm-input--timestamp-atom
-          (slot-value (xcb:+request-unchecked+reply exwm--connection
-                          (make-instance 'xcb:InternAtom
-                                         :only-if-exists 0
-                                         :name-len (length atom)
-                                         :name atom))
-                      'atom)))
+  (setq exwm-input--timestamp-atom (exwm--intern-atom "_TIME"))
   ;; Initialize global keys.
   (dolist (i exwm-input-global-keys)
     (exwm-input--set-key (car i) (cdr i)))
@@ -1050,10 +1068,12 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
 
 (defun exwm-input--post-init ()
   "The second stage in the initialization of the input module."
+  (exwm--log)
   (exwm-input--update-global-prefix-keys))
 
 (defun exwm-input--exit ()
   "Exit the input module."
+  (exwm--log)
   (exwm-input--unset-simulation-keys)
   (remove-hook 'pre-command-hook #'exwm-input--on-pre-command)
   (remove-hook 'post-command-hook #'exwm-input--on-post-command)