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.el207
1 files changed, 125 insertions, 82 deletions
diff --git a/exwm-input.el b/exwm-input.el
index eaddf6b25268..e536a14144b6 100644
--- a/exwm-input.el
+++ b/exwm-input.el
@@ -38,32 +38,119 @@
 (require 'xcb-keysyms)
 (require 'exwm-core)
 
-(defvar exwm-input-move-event 's-down-mouse-1
-  "Emacs event to start moving a window.")
-(defvar exwm-input-resize-event 's-down-mouse-3
-  "Emacs event to start resizing a window.")
+(defgroup exwm-input nil
+  "Input."
+  :version "25.3"
+  :group 'exwm)
 
-(defvar exwm-input--timestamp-window nil)
-(defvar exwm-input--timestamp-atom nil)
-(defvar exwm-input--timestamp-callback nil)
+(defcustom exwm-input-prefix-keys
+  '(?\C-c ?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:)
+  "List of prefix keys EXWM should forward to Emacs when in line-mode."
+  :type '(repeat key-sequence)
+  :get (lambda (symbol)
+         (mapcar #'vector (default-value symbol)))
+  :set (lambda (symbol value)
+         (set symbol (mapcar (lambda (i)
+                               (if (sequencep i)
+                                   (aref i 0)
+                                 i))
+                             value))))
+
+(defcustom exwm-input-move-event 's-down-mouse-1
+  "Emacs event to start moving a window."
+  :type 'key-sequence
+  :get (lambda (symbol)
+         (let ((value (default-value symbol)))
+           (if (mouse-event-p value)
+               value
+             (vector value))))
+  :set (lambda (symbol value)
+         (set symbol (if (sequencep value)
+                         (aref value 0)
+                       value))))
+
+(defcustom exwm-input-resize-event 's-down-mouse-3
+  "Emacs event to start resizing a window."
+  :type 'key-sequence
+  :get (lambda (symbol)
+         (let ((value (default-value symbol)))
+           (if (mouse-event-p value)
+               value
+             (vector value))))
+  :set (lambda (symbol value)
+         (set symbol (if (sequencep value)
+                         (aref value 0)
+                       value))))
+
+(defcustom exwm-input-line-mode-passthrough nil
+  "Non-nil makes 'line-mode' forwards all events to Emacs."
+  :type 'boolean)
 
-(defvar exwm-workspace--current)
-(defvar exwm-workspace--switch-history-outdated)
-(defvar exwm-workspace-current-index)
-(defvar exwm-workspace--minibuffer)
-(defvar exwm-workspace--list)
+;; Input focus update requests should be accumulated for a short time
+;; interval so that only the last one need to be processed.  This not
+;; improves the overall performance, but avoids the problem of input
+;; focus loop, which is a result of the interaction with Emacs frames.
+;;
+;; FIXME: The time interval is hard to decide and perhaps machine-dependent.
+;;        A value too small can cause redundant updates of input focus,
+;;        and even worse, dead loops.  OTOH a large value would bring
+;;        laggy experience.
+(defconst exwm-input--update-focus-interval 0.01
+  "Time interval (in seconds) for accumulating input focus update requests.")
+
+(defvar exwm-input--during-command nil
+  "Indicate whether between `pre-command-hook' and `post-command-hook'.")
 
 (defvar exwm-input--global-keys nil "Global key bindings.")
+
 (defvar exwm-input--global-prefix-keys nil
   "List of prefix keys of global key bindings.")
-(defvar exwm-input-prefix-keys
-  '(?\C-c ?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:)
-  "List of prefix keys EXWM should forward to Emacs when in line-mode.")
+
+(defvar exwm-input--line-mode-cache nil "Cache for incomplete key sequence.")
+
+(defvar exwm-input--local-simulation-keys nil
+  "Whether simulation keys are local.")
+
 (defvar exwm-input--simulation-keys nil "Simulation keys in line-mode.")
+
 (defvar exwm-input--simulation-prefix-keys nil
   "List of prefix keys of simulation keys in line-mode.")
 
+(defvar exwm-input--temp-line-mode nil
+  "Non-nil indicates it's in temporary line-mode for char-mode.")
+
+(defvar exwm-input--timestamp-atom nil)
+
+(defvar exwm-input--timestamp-callback nil)
+
+(defvar exwm-input--timestamp-window nil)
+
+(defvar exwm-input--update-focus-defer-timer nil "Timer for polling the lock.")
+
+(defvar exwm-input--update-focus-lock nil
+  "Lock for solving input focus update contention.")
+
+(defvar exwm-input--update-focus-timer nil
+  "Timer for deferring the update of input focus.")
+
+(defvar exwm-input--update-focus-window nil "The (Emacs) window to be focused.
+This value should always be overwritten.")
+
+(defvar exwm-workspace--current)
+(declare-function exwm-floating--do-moveresize "exwm-floating.el"
+                  (data _synthetic))
+(declare-function exwm-floating--start-moveresize "exwm-floating.el"
+                  (id &optional type))
+(declare-function exwm-floating--stop-moveresize "exwm-floating.el"
+                  (&rest _args))
+(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id))
 (declare-function exwm-layout--show "exwm-layout.el" (id &optional window))
+(declare-function exwm-workspace--client-p "exwm-workspace.el"
+                  (&optional frame))
+(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el")
+(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace))
+(declare-function exwm-workspace-switch "exwm-workspace.el"
+                  (frame-or-index &optional force))
 
 (defun exwm-input--set-focus (id)
   "Set input focus to window ID in a proper way."
@@ -185,13 +272,6 @@ ARGS are additional arguments to CALLBACK."
   (let ((exwm-input--global-prefix-keys nil))
     (exwm-input--update-global-prefix-keys)))
 
-(declare-function exwm-workspace--client-p "exwm-workspace.el"
-                  (&optional frame))
-
-(defvar exwm-input--update-focus-window nil "The (Emacs) window to be focused.
-
-This value should always be overwritten.")
-
 (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))
@@ -205,24 +285,6 @@ This value should always be overwritten.")
     (setq exwm-input--update-focus-window (selected-window))
     (exwm-input--update-focus-defer)))
 
-;; Input focus update requests should be accumulated for a short time
-;; interval so that only the last one need to be processed.  This not
-;; improves the overall performance, but avoids the problem of input
-;; focus loop, which is a result of the interaction with Emacs frames.
-;;
-;; FIXME: The time interval is hard to decide and perhaps machine-dependent.
-;;        A value too small can cause redundant updates of input focus,
-;;        and even worse, dead loops.  OTOH a large value would bring
-;;        laggy experience.
-(defconst exwm-input--update-focus-interval 0.01
-  "Time interval (in seconds) for accumulating input focus update requests.")
-
-(defvar exwm-input--update-focus-lock nil
-  "Lock for solving input focus update contention.")
-(defvar exwm-input--update-focus-defer-timer nil "Timer for polling the lock.")
-(defvar exwm-input--update-focus-timer nil
-  "Timer for deferring the update of input focus.")
-
 (defun exwm-input--update-focus-defer ()
   "Defer updating input focus."
   (when exwm-input--update-focus-defer-timer
@@ -240,12 +302,6 @@ This value should always be overwritten.")
                           #'exwm-input--update-focus-commit
                           exwm-input--update-focus-window))))
 
-(declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id))
-(declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el")
-(declare-function exwm-workspace-switch "exwm-workspace.el"
-                  (frame-or-index &optional force))
-(declare-function exwm-workspace--workspace-p "exwm-workspace.el" (workspace))
-
 (defun exwm-input--update-focus-commit (window)
   "Commit updating input focus."
   (setq exwm-input--update-focus-lock t)
@@ -317,10 +373,6 @@ This value should always be overwritten.")
                      :window exwm--root
                      :data (or id xcb:Window:None))))
 
-(declare-function exwm-floating--start-moveresize "exwm-floating.el"
-                  (id &optional type))
-(declare-function exwm-workspace--position "exwm-workspace.el" (frame))
-
 (defun exwm-input--on-ButtonPress (data _synthetic)
   "Handle ButtonPress event."
   (let ((obj (make-instance 'xcb:ButtonPress))
@@ -419,7 +471,10 @@ This value should always be overwritten.")
 
 ;;;###autoload
 (defun exwm-input-set-key (key command)
-  "Set a global key binding."
+  "Set a global key binding.
+
+The new key binding only takes effect in real time when this command is
+called interactively.  Only invoke it non-interactively in configuration."
   (interactive "KSet key globally: \nCSet key %s to command: ")
   (global-set-key key command)
   (cl-pushnew key exwm-input--global-keys)
@@ -437,22 +492,6 @@ This value should always be overwritten.")
       (setq unread-command-events
             (append unread-command-events `((t . ,event)))))))
 
-(defvar exwm-input-command-whitelist nil
-  "A list of commands that when active all keys should be forwarded to Emacs.")
-(make-obsolete-variable 'exwm-input-command-whitelist
-                        "This variable can be safely removed." "25.1")
-
-(defvar exwm-input--during-command nil
-  "Indicate whether between `pre-command-hook' and `post-command-hook'.")
-
-(defvar exwm-input-line-mode-passthrough nil
-  "Non-nil makes 'line-mode' forwards all events to Emacs.")
-
-(defvar exwm-input--line-mode-cache nil "Cache for incomplete key sequence.")
-
-(defvar exwm-input--temp-line-mode nil
-  "Non-nil indicates it's in temporary line-mode for char-mode.")
-
 (cl-defun exwm-input--translate (key)
   (let (translation)
     (dolist (map (list input-decode-map
@@ -606,7 +645,8 @@ This value should always be overwritten.")
 ;;;###autoload
 (defun exwm-input-grab-keyboard (&optional id)
   "Switch to line-mode."
-  (interactive (list (exwm--buffer->id (window-buffer))))
+  (interactive (list (when (derived-mode-p 'exwm-mode)
+                       (exwm--buffer->id (window-buffer)))))
   (when id
     (with-current-buffer (exwm--id->buffer id)
       (exwm-input--grab-keyboard id)
@@ -617,7 +657,8 @@ This value should always be overwritten.")
 ;;;###autoload
 (defun exwm-input-release-keyboard (&optional id)
   "Switch to char-mode."
-  (interactive (list (exwm--buffer->id (window-buffer))))
+  (interactive (list (when (derived-mode-p 'exwm-mode)
+                       (exwm--buffer->id (window-buffer)))))
   (when id
     (with-current-buffer (exwm--id->buffer id)
       (exwm-input--release-keyboard id)
@@ -628,7 +669,8 @@ This value should always be overwritten.")
 ;;;###autoload
 (defun exwm-input-toggle-keyboard (&optional id)
   "Toggle between 'line-mode' and 'char-mode'."
-  (interactive (list (exwm--buffer->id (window-buffer))))
+  (interactive (list (when (derived-mode-p 'exwm-mode)
+                       (exwm--buffer->id (window-buffer)))))
   (when id
     (with-current-buffer (exwm--id->buffer id)
       (if exwm--keyboard-grabbed
@@ -664,9 +706,14 @@ This value should always be overwritten.")
     (xcb:flush exwm--connection)))
 
 ;;;###autoload
-(defun exwm-input-send-next-key (times)
-  "Send next key to client window."
+(cl-defun exwm-input-send-next-key (times)
+  "Send next key to client window.
+
+EXWM will prompt for the key to send.  This command can be prefixed to send
+multiple keys."
   (interactive "p")
+  (unless (derived-mode-p 'exwm-mode)
+    (cl-return-from 'exwm-input-send-next-key))
   (when (> times 12) (setq times 12))
   (let (key keys)
     (dotimes (i times)
@@ -686,9 +733,6 @@ This value should always be overwritten.")
 ;;   (unless (listp last-input-event)      ;not a key event
 ;;     (exwm-input--fake-key last-input-event)))
 
-(defvar exwm-input--local-simulation-keys nil
-  "Whether simulation keys are local.")
-
 (defun exwm-input--update-simulation-prefix-keys ()
   "Update the list of prefix keys of simulation keys."
   (setq exwm-input--simulation-prefix-keys nil)
@@ -718,9 +762,13 @@ Its usage is the same with `exwm-input-set-simulation-keys'."
     (exwm-input-set-simulation-keys simulation-keys)))
 
 ;;;###autoload
-(defun exwm-input-send-simulation-key (times)
-  "Fake a key event according to last input key sequence."
+(cl-defun exwm-input-send-simulation-key (times)
+  "Fake a key event according to the last input key sequence.
+
+Sending multiple fake keys at once is only supported by Emacs 27 and later."
   (interactive "p")
+  (unless (derived-mode-p 'exwm-mode)
+    (cl-return-from 'exwm-input-send-simulation-key))
   (let ((pair (assoc (this-single-command-keys) exwm-input--simulation-keys)))
     (when pair
       (setq pair (cdr pair))
@@ -738,11 +786,6 @@ Its usage is the same with `exwm-input-set-simulation-keys'."
   "Run in `post-command-hook'."
   (setq exwm-input--during-command nil))
 
-(declare-function exwm-floating--stop-moveresize "exwm-floating.el"
-                  (&rest _args))
-(declare-function exwm-floating--do-moveresize "exwm-floating.el"
-                  (data _synthetic))
-
 (defun exwm-input--init ()
   "Initialize the keyboard module."
   ;; Refresh keyboard mapping