diff options
| author | Cecilio Pardo | 2024-12-02 17:30:42 +0100 |
|---|---|---|
| committer | Stefan Monnier | 2025-06-30 11:34:54 -0400 |
| commit | ba02efb85e403a55d321e3d213f1449246ad9484 (patch) | |
| tree | 59689a9187907215c6f0ac3ecc1057f59f11f328 | |
| parent | 67aed063f6460e8add0fcfdebf562a3062cc26a2 (diff) | |
| download | emacs-scratch/low-level-key.tar.gz emacs-scratch/low-level-key.zip | |
Go through normal keymapsscratch/low-level-key
In this new version I changed the way events are handled.
Now llk-handle generates input events to be used with normal
keymaps, instead of running a command. The function llk-bind
activates event generation for a key and a combination of
events press, release, double, triple.
I also made changes following your notes, such as:
- Clarification on the event's time, documentation of
keysyms variables moved, don't limit to GUI systems.
- cl-defstruct for the event payload.
- Format and naming conventions.
- Default timeout to mouse double click timeout.
You suggested to auto generate the keysym table, but we
would still need a table to relate the Windows keys to the X
equivalent.
* doc/lispref/commands.texi (Misc Events): Adjust to new semantics.
* src/keyboard.c (syms_of_keyboard): Adust docstring.
FIXME: Old commit msg.
* lisp/low-level-key.el (New file).
(low-level-key): Struct with event data.
(llk-bindings): User bindings for low level key events.
(llk-tap-timeout): User option.
(llk-keysyms): List of available keysyms.
(llk--define-xk): Macro for defining keysyms.
(llk--define-keysyms): Build llk-keysyms.
(llk-bind): Function to create a binding.
(llk--event-history-for-tap): Event history for tap detection.
(llk--detect-n-tap): Function to detect taps.
(describe-low-level-key): Command to get information about a key.
(llk--describe): Show help buffer with information
about an event.
(llk-handle): Handler for key events.
(llk--generate-event): Generate input event for key.
(llk--generate-events): Generate input events for key.
| -rw-r--r-- | doc/lispref/commands.texi | 41 | ||||
| -rw-r--r-- | lisp/low-level-key.el | 615 | ||||
| -rw-r--r-- | src/keyboard.c | 9 |
3 files changed, 342 insertions, 323 deletions
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 32b4df6b3bf..01565727e15 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi | |||
| @@ -2670,35 +2670,28 @@ size of the object beneath the gesture: image, window, etc. | |||
| 2670 | 2670 | ||
| 2671 | @cindex @code{low-level-key} event | 2671 | @cindex @code{low-level-key} event |
| 2672 | @item (low-level-key @var{is-key-press} @var{key} @var{modifier} @var{time} @var{frame}) | 2672 | @item (low-level-key @var{is-key-press} @var{key} @var{modifier} @var{time} @var{frame}) |
| 2673 | This event is sent on the physical press or release of keys, only on GUI | 2673 | This event is sent on the physical press or release of keys, only on |
| 2674 | systems, currently X, MS-Windows and PGTK, and only if the variable | 2674 | systems where it is supported, currently X, MS-Windows and PGTK, and |
| 2675 | @code{enable-low-level-key-events} has a non-@code{nil} value. See its | 2675 | only if the variable @code{enable-low-level-key-events} has a |
| 2676 | documentation for the values it can take, that allow to filter which | 2676 | non-@code{nil} value. See its documentation for the values to use, that |
| 2677 | keys should generate this kind of event. | 2677 | can activate the events for all or some keys. |
| 2678 | 2678 | ||
| 2679 | @var{is-key-press} is @code{t} for a key press, @code{nil} for a key release. | 2679 | @var{is-key-press} is @code{t} for a key press, @code{nil} for a key |
| 2680 | @var{time} is the event's time in milliseconds, @var{frame} is the | 2680 | release. @var{time} is the event's time in milliseconds, as reported by |
| 2681 | frame receiving it. @var{modifier} is @code{nil} if the key is not a | 2681 | the underlying platform, and should only be used to measure time |
| 2682 | intervals between events of this same kind. @var{frame} is the frame | ||
| 2683 | receiving the event. @var{modifier} is @code{nil} if the key is not a | ||
| 2682 | modifier key, @code{t} if it is, but it is unknown which one, or one of | 2684 | modifier key, @code{t} if it is, but it is unknown which one, or one of |
| 2683 | @code{shift}, @code{control}, @code{meta}, @code{alt}, @code{super}, | 2685 | @code{shift}, @code{control}, @code{meta}, @code{alt}, @code{super}, |
| 2684 | @code{hyper}. | 2686 | @code{hyper}. |
| 2685 | 2687 | ||
| 2686 | @var{key}, an integer, identifies the key pressed or released. This | 2688 | @var{key}, an integer, identifies the key pressed or released. This |
| 2687 | number is platform dependent, but there are variables for most keys that | 2689 | number is platform dependent. |
| 2688 | can be used in place of the numbers to identify them. For example, the | 2690 | |
| 2689 | variable @code{xk-backspace} identifies the @key{backspace} key. | 2691 | This is a special event (@pxref{Special Events}), ignored by |
| 2690 | 2692 | default. Loading @file{low-level-key.el} sets a handler | |
| 2691 | The names are parallel to those for KeySyms on X, as defined in | 2693 | that can generate normal input events for key press, release and multi |
| 2692 | @file{xkeysymdef.h}. For example, @code{XK_Shift_L} (the left shift | 2694 | tap. See the function @code{llk-bind}. |
| 2693 | key), corresponds to @code{xk-shift-l}. The @file{xkeysymdef.h} file | ||
| 2694 | defines different KeySyms for capital and small versions of letters. | ||
| 2695 | For this event, only the capital version is used, with the variables | ||
| 2696 | @code{xk-a}, @code{xk-b}, etc. | ||
| 2697 | |||
| 2698 | These variables are initialized by calling the function @code{llk-init}. | ||
| 2699 | This function also binds a handler to this event, which allows to detect | ||
| 2700 | double taps on keys (normally modifier keys) and bind commands or | ||
| 2701 | functions to be run. See the function @code{llk-bind}. | ||
| 2702 | 2695 | ||
| 2703 | @cindex @code{preedit-text} event | 2696 | @cindex @code{preedit-text} event |
| 2704 | @item (preedit-text @var{arg}) | 2697 | @item (preedit-text @var{arg}) |
diff --git a/lisp/low-level-key.el b/lisp/low-level-key.el index bc9311f82d0..8a8d912977d 100644 --- a/lisp/low-level-key.el +++ b/lisp/low-level-key.el | |||
| @@ -1,26 +1,74 @@ | |||
| 1 | ;;; -*- lexical-binding: t -*- | 1 | ;;; low-level-key.el --- Handling of key press/release events -*- lexical-binding: t -*- |
| 2 | 2 | ||
| 3 | ;; The physical-key event is like this: | 3 | ;; Copyright (C) 2025 Free Software Foundation, Inc. |
| 4 | ;; (low-level-key IS-KEY-PRESS KEY MODIFIER TIME FRAME) | 4 | |
| 5 | ;; IS-KEY-PRESS is t if the key has been pressed, nil if it has been released. | 5 | ;; This file is part of GNU Emacs. |
| 6 | ;; KEY is the keysym number. | 6 | |
| 7 | ;; MODIFIER is the modifier associated with this key. It is nil if the key is | 7 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
| 8 | ;; not a modifier. It can be one of the following symbols: shift, control, meta, | 8 | ;; it under the terms of the GNU General Public License as published by |
| 9 | ;; super, hyper, alt. It can also be t if the key is a modifier but it can't be | 9 | ;; the Free Software Foundation, either version 3 of the License, or |
| 10 | ;; identified, as in the PGTK backend. | 10 | ;; (at your option) any later version. |
| 11 | ;; TIME is the timestamp in milliseconds of the event. | 11 | |
| 12 | ;; FRAME is the frame where the event happened. | 12 | ;; GNU Emacs is distributed in the hope that it will be useful, |
| 13 | ;; | 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | ;; After calling 'llk-init' and setting a non-nil value for | 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | ;; 'enable-low-level-key-events', events begin to be handled by 'llk-handler', | 15 | ;; GNU General Public License for more details. |
| 16 | ;; which tries to detect n-taps and calls the corresponding function. | 16 | |
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ;;; Commentary: | ||
| 21 | |||
| 22 | ;; Emacs can send low-level key events, that correspond to key presses | ||
| 23 | ;; and releases. These events are by default disabled. | ||
| 24 | |||
| 25 | ;; When enabled by setting `enable-low-level-key-events' to a non-nil | ||
| 26 | ;; value, emacs will begin sending them, and they will be ignored as | ||
| 27 | ;; low-level-key is bound to `ignore' on `special-event-map'. | ||
| 28 | |||
| 29 | ;; This file sets a handler for them (`llk-handle') which generates | ||
| 30 | ;; input events for key presses, key releases and double and triple | ||
| 31 | ;; taps. These events can be bound to commands on normal keymaps. | ||
| 32 | |||
| 33 | ;; Because generating these events for all keys would interfere with | ||
| 34 | ;; normal keyboard input, they must be activated individually by calling | ||
| 35 | ;; the function `llk-bind'. | ||
| 36 | |||
| 37 | ;; The low-level-key event payload is described by the 'low-level-key' | ||
| 38 | ;; struct. Use 'cl-describe-type' to get more information about it. | ||
| 17 | ;; | 39 | ;; |
| 18 | ;; To implement other functionalities, you can replace llk-handler with | 40 | ;; After loading this file and setting a non-nil value for |
| 19 | ;; your own function. | 41 | ;; 'enable-low-level-key-events', events begin to be handled by |
| 42 | ;; 'llk-handle', which tries to detect n-taps, and creates input | ||
| 43 | ;; events. See 'llk-bind'. | ||
| 44 | |||
| 45 | ;; Code: | ||
| 20 | 46 | ||
| 21 | (require 'cl-lib) | 47 | (require 'cl-lib) |
| 22 | 48 | ||
| 23 | ;; User options | 49 | (defvar llk-tap-timeout (let ((time (mouse-double-click-time))) |
| 50 | (if (> time 0) time 800)) | ||
| 51 | "Time in milliseconds between key presses/releases to consider a double tap. | ||
| 52 | For triple taps, the time is twice this value.") | ||
| 53 | |||
| 54 | (cl-defstruct (low-level-key (:type list)) | ||
| 55 | "Structure for low level key events. | ||
| 56 | Received as low-level-key on `special-event-map'." | ||
| 57 | (event-type nil :type symbol | ||
| 58 | :documentation "Type of event: low-level-key") | ||
| 59 | (is-key-press nil :type boolean | ||
| 60 | :documentation "t if the key has been pressed, nil if it has been released.") | ||
| 61 | (key nil :type integer | ||
| 62 | :documentation "The keysym number.") | ||
| 63 | (modifier nil :type symbol | ||
| 64 | :documentation "Modifier associated with this key. It is nil if the key is | ||
| 65 | not a modifier. It can be one of the following symbols: shift, control, meta, | ||
| 66 | super, hyper, alt. It can also be t if the key is a modifier but it can't be | ||
| 67 | identified, as in the PGTK backend.") | ||
| 68 | (time nil :type integer | ||
| 69 | :documentation "Timestamp in milliseconds of the event.") | ||
| 70 | (frame nil :type frame | ||
| 71 | :documentation "Frame where the event happened.")) | ||
| 24 | 72 | ||
| 25 | (defvar llk-bindings nil | 73 | (defvar llk-bindings nil |
| 26 | "List of bindings for low level key events (press/release/tap). | 74 | "List of bindings for low level key events (press/release/tap). |
| @@ -28,315 +76,298 @@ | |||
| 28 | Use the `llk-bind' function to add bindings. See its documentation for | 76 | Use the `llk-bind' function to add bindings. See its documentation for |
| 29 | a description of the binding information.") | 77 | a description of the binding information.") |
| 30 | 78 | ||
| 31 | (defvar llk-tap-count 2 | 79 | (defvar llk-keysyms nil |
| 32 | "Number or key press/releases to consider a tap.") | 80 | "List of keysyms and their names. |
| 81 | Each element has the form (CODE . KEYSYM), where code is a NUMBER and | ||
| 82 | KEYSYM a symbol, such as `xk-shift-l'") | ||
| 33 | 83 | ||
| 34 | (defvar llk-tap-timeout 1000 | 84 | ;; TODO docstring. |
| 35 | "Time (ms) between consecutive key presses/releases to consider a tap.") | 85 | (defun llk-bind (key &rest events) |
| 86 | "Activates low level event generation for a key. | ||
| 36 | 87 | ||
| 37 | (defvar llk-tap-keys | 88 | KEY can be a number or a symbol. The symbols `shift', `control', |
| 38 | '(xk-shift-l xk-shift-r xk-control-l xk-control-r meta) | 89 | `meta', `super', `hyper', `alt' activate events for the corresponding |
| 39 | "Keys that can generate taps.") | 90 | modifier keys. A number activates events for the corresponding KeySym. |
| 40 | 91 | ||
| 41 | (defvar llk-keysyms nil | 92 | EVENTS are symbols that activate one event. Possible values are `press', |
| 42 | "List of keysym numbers and their corresponding symbols. | 93 | `release', `double' and `triple'. |
| 94 | |||
| 95 | See `llk-keysyms' for a list of known values for KEY and their names. | ||
| 96 | For each of those, there is a corresponding variable. It is better to | ||
| 97 | use the variables to specify keys, as numerical values are | ||
| 98 | platform-dependent. The names are parallel to those for KeySyms on X, | ||
| 99 | as defined in `xkeysymdef.h'. For example, `XK_Shift_L' (the left shift | ||
| 100 | key), corresponds to `xk-shift-l'. | ||
| 101 | |||
| 102 | The `xkeysymdef.h' file defines different KeySyms for capital and small | ||
| 103 | versions of latin letters. For this event, only the capital version is | ||
| 104 | used, with the variables `xk-a', `xk-b', etc. | ||
| 105 | |||
| 106 | Low level key events must be enabled with the variable | ||
| 107 | `enable-low-level-key-events'. | ||
| 108 | |||
| 109 | Once a key is activated with this function, input events will be | ||
| 110 | generated for them, and can be bound to commands using normal keymaps. | ||
| 43 | 111 | ||
| 44 | Each element has the form (KEYSYM . SYMBOL). The variable value for | 112 | For example, activating the double tap for the left shift key: |
| 45 | each symbol is the keysym. This list is initialized by `llk-init'.") | ||
| 46 | 113 | ||
| 47 | (defvar llk-describe-next-press nil | 114 | (llk-bind xk-shift-l \\='double) |
| 48 | "Internal variable to mark that next key press should be described.") | ||
| 49 | 115 | ||
| 50 | (defmacro define-xk (name x-keysym w32-keysym) | 116 | will generate the event `double-xk-shift-l', than can be bound to a |
| 117 | command with: | ||
| 118 | |||
| 119 | (keymap-global-set [double-xk-shift-l] COMMAND) | ||
| 120 | |||
| 121 | Prefixes for events are `press-key-', `release-key-', `double-' and | ||
| 122 | `triple-'. | ||
| 123 | |||
| 124 | If you use a KeySym number that is not on `llk-keysyms', the events will | ||
| 125 | use its numerical value." | ||
| 126 | (setq llk-bindings | ||
| 127 | (cl-delete-if (lambda (x) (eq (car x) key)) llk-bindings)) | ||
| 128 | (push (append (list key) events) llk-bindings)) | ||
| 129 | |||
| 130 | ;; We store the last events (key/modifier is-press timestamp) here to | ||
| 131 | ;; test for multitap. This is not the use the low-level-key struct. | ||
| 132 | (defvar llk--event-history-for-tap nil | ||
| 133 | "Internal variable for detecting taps.") | ||
| 134 | |||
| 135 | (defun llk--detect-n-tap (n timeout) | ||
| 136 | "Internal function to detect n-tap keys." | ||
| 137 | ;; Only care about last 2xN events | ||
| 138 | (ntake (* 2 n) llk--event-history-for-tap) | ||
| 139 | ;; If we have: | ||
| 140 | ;; - Exactly 2 * n events. | ||
| 141 | ;; - down, up, down, up, ... | ||
| 142 | ;; - not two much time between first and last | ||
| 143 | (and (eq (* 2 n) (length llk--event-history-for-tap)) | ||
| 144 | (cl-every #'eq | ||
| 145 | (ntake (* 2 n) | ||
| 146 | (list nil t nil t nil t nil t | ||
| 147 | nil t nil t nil t nil t)) | ||
| 148 | (mapcar 'cl-second llk--event-history-for-tap)) | ||
| 149 | (< (- (cl-third (cl-first llk--event-history-for-tap)) | ||
| 150 | (cl-third (car (last llk--event-history-for-tap)))) | ||
| 151 | timeout) | ||
| 152 | (progn (setq llk--event-history-for-tap nil) t))) | ||
| 153 | |||
| 154 | (defun llk--generate-event (key event-type) | ||
| 155 | (when (numberp key) | ||
| 156 | (let ((sym (cdr (assoc key llk-keysyms)))) | ||
| 157 | (when sym | ||
| 158 | (setq key sym)))) | ||
| 159 | (push (intern (format "%s-%s" event-type key)) | ||
| 160 | unread-command-events)) | ||
| 161 | |||
| 162 | (defun llk--generate-events (key is-press binding timestamp) | ||
| 163 | (if is-press | ||
| 164 | (when (member 'press binding) | ||
| 165 | (llk--generate-event key 'press-key)) | ||
| 166 | (when (member 'release binding) | ||
| 167 | (llk--generate-event key 'release-key))) | ||
| 168 | |||
| 169 | (let ((double (member 'double binding)) | ||
| 170 | (triple (member 'triple binding))) | ||
| 171 | ;; a non-tap key clears the event history. | ||
| 172 | (if (or double triple) | ||
| 173 | (progn | ||
| 174 | ;; Clear the event history if it has events from another key. | ||
| 175 | (unless (equal (car (car llk--event-history-for-tap)) key) | ||
| 176 | (setq llk--event-history-for-tap nil)) | ||
| 177 | (push (list key is-press timestamp) llk--event-history-for-tap) | ||
| 178 | (and double | ||
| 179 | (llk--detect-n-tap 2 llk-tap-timeout) | ||
| 180 | (llk--generate-event key 'double-key)) | ||
| 181 | (and triple | ||
| 182 | (llk--detect-n-tap 3 (* 2 llk-tap-timeout)) | ||
| 183 | (llk--generate-event key 'triple-key))) | ||
| 184 | ;; A non-tap key clears the event history. | ||
| 185 | (setq llk--event-history-for-tap nil)))) | ||
| 186 | |||
| 187 | (defun llk-handle () | ||
| 188 | (interactive) | ||
| 189 | (let* ((key (low-level-key-key last-input-event)) | ||
| 190 | (modifier (low-level-key-modifier last-input-event)) | ||
| 191 | (timestamp (low-level-key-time last-input-event)) | ||
| 192 | (is-press (low-level-key-is-key-press last-input-event)) | ||
| 193 | (binding (assoc key llk-bindings)) | ||
| 194 | (binding-modifier (assoc modifier llk-bindings))) | ||
| 195 | (if binding | ||
| 196 | (llk--generate-events key is-press binding timestamp) | ||
| 197 | (when binding-modifier | ||
| 198 | (llk--generate-events modifier is-press binding-modifier timestamp))))) | ||
| 199 | |||
| 200 | (defmacro llk--define-xk (name x-keysym w32-keysym) | ||
| 51 | "Internal macro to define keysyms." | 201 | "Internal macro to define keysyms." |
| 52 | `(let ((ksym (pcase (window-system) | 202 | `(let ((ksym (pcase (window-system) |
| 53 | ('pgtk ,x-keysym) | 203 | ((or 'pgtk 'x) ,x-keysym) |
| 54 | ('x ,x-keysym) | ||
| 55 | ('w32 ,w32-keysym)))) | 204 | ('w32 ,w32-keysym)))) |
| 56 | (defconst ,name ksym "Constant for a keysym value.") | 205 | (defconst ,name ksym "Constant for a keysym value.") |
| 57 | (push (cons ksym ',name) llk-keysyms))) | 206 | (push (cons ksym ',name) llk-keysyms))) |
| 58 | 207 | ||
| 59 | (defun llk-define-keysyms () | 208 | (defun llk--define-keysyms () |
| 60 | "Initialize the keysym list, `llk-keysyms'. | 209 | "Initialize the keysym list, `llk-keysyms'." |
| 61 | |||
| 62 | Called from `llk-init'." | ||
| 63 | (setq llk-keysyms nil) | 210 | (setq llk-keysyms nil) |
| 64 | 211 | ||
| 65 | ;; tty keys | 212 | ;; tty keys |
| 66 | (define-xk xk-backspace #xff08 #x08) ;; XK_BackSpace VK_BACK | 213 | (llk--define-xk xk-backspace #xff08 #x08) ;; XK_BackSpace VK_BACK |
| 67 | (define-xk xk-tab #xff09 #x09) ;; XK_Tab VK_TAB | 214 | (llk--define-xk xk-tab #xff09 #x09) ;; XK_Tab VK_TAB |
| 68 | (define-xk xk-clear #xff0b #x0C) ;; XK_Clear VK_CLEAR | 215 | (llk--define-xk xk-clear #xff0b #x0C) ;; XK_Clear VK_CLEAR |
| 69 | (define-xk xk-return #xff0d #x0D) ;; XK_Return VK_RETURN | 216 | (llk--define-xk xk-return #xff0d #x0D) ;; XK_Return VK_RETURN |
| 70 | (define-xk xk-pause #xff13 #x13) ;; XK_Pause VK_PAUSE | 217 | (llk--define-xk xk-pause #xff13 #x13) ;; XK_Pause VK_PAUSE |
| 71 | (define-xk xk-scroll-lock #xff14 #x91) ;; XK_Scroll_Lock VK_SCROLL | 218 | (llk--define-xk xk-scroll-lock #xff14 #x91) ;; XK_Scroll_Lock VK_SCROLL |
| 72 | (define-xk xk-escape #xff1B #x1B) ;; XK_Escape VK_ESCAPE | 219 | (llk--define-xk xk-escape #xff1B #x1B) ;; XK_Escape VK_ESCAPE |
| 73 | (define-xk xk-delete #xffff #x2E) ;; XK_Delete VK_DELETE | 220 | (llk--define-xk xk-delete #xffff #x2E) ;; XK_Delete VK_DELETE |
| 74 | 221 | ||
| 75 | ;; Cursor control and motion | 222 | ;; Cursor control and motion |
| 76 | (define-xk xk-home #xff50 #x24) ;; XK_Home VK_HOME | 223 | (llk--define-xk xk-home #xff50 #x24) ;; XK_Home VK_HOME |
| 77 | (define-xk xk-left #xff51 #x25) ;; XK_Left VK_LEFT | 224 | (llk--define-xk xk-left #xff51 #x25) ;; XK_Left VK_LEFT |
| 78 | (define-xk xk-up #xff52 #x26) ;; XK_Up VK_UP | 225 | (llk--define-xk xk-up #xff52 #x26) ;; XK_Up VK_UP |
| 79 | (define-xk xk-right #xff53 #x27) ;; XK_Right VK_RIGHT | 226 | (llk--define-xk xk-right #xff53 #x27) ;; XK_Right VK_RIGHT |
| 80 | (define-xk xk-down #xff54 #x28) ;; XK_Down VK_DOWN | 227 | (llk--define-xk xk-down #xff54 #x28) ;; XK_Down VK_DOWN |
| 81 | (define-xk xk-page-up #xff55 #x21) ;; XK_Page_Up VK_PRIOR | 228 | (llk--define-xk xk-page-up #xff55 #x21) ;; XK_Page_Up VK_PRIOR |
| 82 | (define-xk xk-page-down #xff56 #x22) ;; XK_Page_Down VK_NEXT | 229 | (llk--define-xk xk-page-down #xff56 #x22) ;; XK_Page_Down VK_NEXT |
| 83 | (define-xk xk-end #xff57 #x23) ;; XK_End VK_END | 230 | (llk--define-xk xk-end #xff57 #x23) ;; XK_End VK_END |
| 84 | (define-xk xk-begin #xff58 #x24) ;; XK_Begin VK_HOME | 231 | (llk--define-xk xk-begin #xff58 #x24) ;; XK_Begin VK_HOME |
| 85 | 232 | ||
| 86 | ;; Special Windows keyboard keys | 233 | ;; Special Windows keyboard keys |
| 87 | (define-xk xk-win-l #xFF5B #x5B) ;; XK_Win_L VK_LWIN | 234 | (llk--define-xk xk-win-l #xFF5B #x5B) ;; XK_Win_L VK_LWIN |
| 88 | (define-xk xk-win-r #xFF5C #x5C) ;; XK_Win_R VK_RWIN | 235 | (llk--define-xk xk-win-r #xFF5C #x5C) ;; XK_Win_R VK_RWIN |
| 89 | (define-xk xk-app #xFF5D #x5D) ;; XK_App VK_APPS | 236 | (llk--define-xk xk-app #xFF5D #x5D) ;; XK_App VK_APPS |
| 90 | 237 | ||
| 91 | ;; Misc functions | 238 | ;; Misc functions |
| 92 | (define-xk xk-select #xff60 #x29) ;; XK_Select VK_SELECT | 239 | (llk--define-xk xk-select #xff60 #x29) ;; XK_Select VK_SELECT |
| 93 | (define-xk xk-print #xff61 #x2A) ;; XK_Print VK_PRINT | 240 | (llk--define-xk xk-print #xff61 #x2A) ;; XK_Print VK_PRINT |
| 94 | (define-xk xk-insert #xff64 #x2D) ;; XK_Insert VK_INSERT | 241 | (llk--define-xk xk-insert #xff64 #x2D) ;; XK_Insert VK_INSERT |
| 95 | (define-xk xk-num-lock #xff7f #x90) ;; XK_Num_Lock VK_NUMLOCK | 242 | (llk--define-xk xk-num-lock #xff7f #x90) ;; XK_Num_Lock VK_NUMLOCK |
| 96 | 243 | ||
| 97 | ;; Keypad | 244 | ;; Keypad |
| 98 | ;; TODO: Check values for MS-Windows | 245 | ;; TODO: Check values for MS-Windows |
| 99 | (define-xk xk-kp-enter #xff8d nil) ;; XK_KP_Enter ??? | 246 | (llk--define-xk xk-kp-enter #xff8d nil) ;; XK_KP_Enter ??? |
| 100 | (define-xk xk-kp-multiply #xffaa nil) ;; XK_KP_Multiply ??? | 247 | (llk--define-xk xk-kp-multiply #xffaa nil) ;; XK_KP_Multiply ??? |
| 101 | (define-xk xk-kp-add #xffab nil) ;; XK_KP_Add ??? | 248 | (llk--define-xk xk-kp-add #xffab nil) ;; XK_KP_Add ??? |
| 102 | (define-xk xk-kp-subtract #xffad nil) ;; XK_KP_Subtract ??? | 249 | (llk--define-xk xk-kp-subtract #xffad nil) ;; XK_KP_Subtract ??? |
| 103 | (define-xk xk-kp-decimal #xffae nil) ;; XK_KP_Decimal ??? | 250 | (llk--define-xk xk-kp-decimal #xffae nil) ;; XK_KP_Decimal ??? |
| 104 | (define-xk xk-kp-divide #xffaf nil) ;; XK_KP_Divide ??? | 251 | (llk--define-xk xk-kp-divide #xffaf nil) ;; XK_KP_Divide ??? |
| 105 | (define-xk xk-kp-0 #xffb0 #x60) ;; XK_KP_0 VK_NUMPAD0 | 252 | (llk--define-xk xk-kp-0 #xffb0 #x60) ;; XK_KP_0 VK_NUMPAD0 |
| 106 | (define-xk xk-kp-1 #xffb1 #x61) ;; XK_KP_1 VK_NUMPAD1 | 253 | (llk--define-xk xk-kp-1 #xffb1 #x61) ;; XK_KP_1 VK_NUMPAD1 |
| 107 | (define-xk xk-kp-2 #xffb2 #x62) ;; XK_KP_2 VK_NUMPAD2 | 254 | (llk--define-xk xk-kp-2 #xffb2 #x62) ;; XK_KP_2 VK_NUMPAD2 |
| 108 | (define-xk xk-kp-3 #xffb3 #x63) ;; XK_KP_3 VK_NUMPAD3 | 255 | (llk--define-xk xk-kp-3 #xffb3 #x63) ;; XK_KP_3 VK_NUMPAD3 |
| 109 | (define-xk xk-kp-4 #xffb4 #x64) ;; XK_KP_4 VK_NUMPAD4 | 256 | (llk--define-xk xk-kp-4 #xffb4 #x64) ;; XK_KP_4 VK_NUMPAD4 |
| 110 | (define-xk xk-kp-5 #xffb5 #x65) ;; XK_KP_5 VK_NUMPAD5 | 257 | (llk--define-xk xk-kp-5 #xffb5 #x65) ;; XK_KP_5 VK_NUMPAD5 |
| 111 | (define-xk xk-kp-6 #xffb6 #x66) ;; XK_KP_6 VK_NUMPAD6 | 258 | (llk--define-xk xk-kp-6 #xffb6 #x66) ;; XK_KP_6 VK_NUMPAD6 |
| 112 | (define-xk xk-kp-7 #xffb7 #x67) ;; XK_KP_7 VK_NUMPAD7 | 259 | (llk--define-xk xk-kp-7 #xffb7 #x67) ;; XK_KP_7 VK_NUMPAD7 |
| 113 | (define-xk xk-kp-8 #xffb8 #x68) ;; XK_KP_8 VK_NUMPAD8 | 260 | (llk--define-xk xk-kp-8 #xffb8 #x68) ;; XK_KP_8 VK_NUMPAD8 |
| 114 | (define-xk xk-kp-9 #xffb9 #x69) ;; XK_KP_9 VK_NUMPAD9 | 261 | (llk--define-xk xk-kp-9 #xffb9 #x69) ;; XK_KP_9 VK_NUMPAD9 |
| 115 | 262 | ||
| 116 | ;; Function keys | 263 | ;; Function keys |
| 117 | (define-xk xk-f1 #xffbe #x70) ;; XK_F1 VK_F1 | 264 | (llk--define-xk xk-f1 #xffbe #x70) ;; XK_F1 VK_F1 |
| 118 | (define-xk xk-f2 #xffbf #x71) ;; XK_F2 VK_F2 | 265 | (llk--define-xk xk-f2 #xffbf #x71) ;; XK_F2 VK_F2 |
| 119 | (define-xk xk-f3 #xffc0 #x72) ;; XK_F3 VK_F3 | 266 | (llk--define-xk xk-f3 #xffc0 #x72) ;; XK_F3 VK_F3 |
| 120 | (define-xk xk-f4 #xffc1 #x73) ;; XK_F4 VK_F4 | 267 | (llk--define-xk xk-f4 #xffc1 #x73) ;; XK_F4 VK_F4 |
| 121 | (define-xk xk-f5 #xffc2 #x74) ;; XK_F5 VK_F5 | 268 | (llk--define-xk xk-f5 #xffc2 #x74) ;; XK_F5 VK_F5 |
| 122 | (define-xk xk-f6 #xffc3 #x75) ;; XK_F6 VK_F6 | 269 | (llk--define-xk xk-f6 #xffc3 #x75) ;; XK_F6 VK_F6 |
| 123 | (define-xk xk-f7 #xffc4 #x76) ;; XK_F7 VK_F7 | 270 | (llk--define-xk xk-f7 #xffc4 #x76) ;; XK_F7 VK_F7 |
| 124 | (define-xk xk-f8 #xffc5 #x77) ;; XK_F8 VK_F8 | 271 | (llk--define-xk xk-f8 #xffc5 #x77) ;; XK_F8 VK_F8 |
| 125 | (define-xk xk-f9 #xffc6 #x78) ;; XK_F9 VK_F9 | 272 | (llk--define-xk xk-f9 #xffc6 #x78) ;; XK_F9 VK_F9 |
| 126 | (define-xk xk-f10 #xffc7 #x79) ;; XK_F10 VK_F10 | 273 | (llk--define-xk xk-f10 #xffc7 #x79) ;; XK_F10 VK_F10 |
| 127 | (define-xk xk-f11 #xffc8 #x7A) ;; XK_F11 VK_F11 | 274 | (llk--define-xk xk-f11 #xffc8 #x7A) ;; XK_F11 VK_F11 |
| 128 | (define-xk xk-f12 #xffc9 #x7B) ;; XK_F12 VK_F12 | 275 | (llk--define-xk xk-f12 #xffc9 #x7B) ;; XK_F12 VK_F12 |
| 129 | (define-xk xk-f13 #xffca #x7C) ;; XK_F13 VK_F13 | 276 | (llk--define-xk xk-f13 #xffca #x7C) ;; XK_F13 VK_F13 |
| 130 | (define-xk xk-f14 #xffcb #x7D) ;; XK_F14 VK_F14 | 277 | (llk--define-xk xk-f14 #xffcb #x7D) ;; XK_F14 VK_F14 |
| 131 | (define-xk xk-f15 #xffcc #x7E) ;; XK_F15 VK_F15 | 278 | (llk--define-xk xk-f15 #xffcc #x7E) ;; XK_F15 VK_F15 |
| 132 | (define-xk xk-f16 #xffcd #x7F) ;; XK_F16 VK_F16 | 279 | (llk--define-xk xk-f16 #xffcd #x7F) ;; XK_F16 VK_F16 |
| 133 | (define-xk xk-f17 #xffce #x80) ;; XK_F17 VK_F17 | 280 | (llk--define-xk xk-f17 #xffce #x80) ;; XK_F17 VK_F17 |
| 134 | (define-xk xk-f18 #xffcf #x81) ;; XK_F18 VK_F18 | 281 | (llk--define-xk xk-f18 #xffcf #x81) ;; XK_F18 VK_F18 |
| 135 | (define-xk xk-f19 #xffd0 #x82) ;; XK_F19 VK_F19 | 282 | (llk--define-xk xk-f19 #xffd0 #x82) ;; XK_F19 VK_F19 |
| 136 | (define-xk xk-f20 #xffd1 #x83) ;; XK_F20 VK_F20 | 283 | (llk--define-xk xk-f20 #xffd1 #x83) ;; XK_F20 VK_F20 |
| 137 | (define-xk xk-f21 #xffd2 #x84) ;; XK_F21 VK_F21 | 284 | (llk--define-xk xk-f21 #xffd2 #x84) ;; XK_F21 VK_F21 |
| 138 | (define-xk xk-f22 #xffd3 #x85) ;; XK_F22 VK_F22 | 285 | (llk--define-xk xk-f22 #xffd3 #x85) ;; XK_F22 VK_F22 |
| 139 | (define-xk xk-f23 #xffd4 #x86) ;; XK_F23 VK_F23 | 286 | (llk--define-xk xk-f23 #xffd4 #x86) ;; XK_F23 VK_F23 |
| 140 | (define-xk xk-f24 #xffd5 #x87) ;; XK_F24 VK_F24 | 287 | (llk--define-xk xk-f24 #xffd5 #x87) ;; XK_F24 VK_F24 |
| 141 | 288 | ||
| 142 | ;; Modifier keys | 289 | ;; Modifier keys |
| 143 | (define-xk xk-shift-l #xffe1 #xA0) ;; XK_Shift_L VK_LSHIFT | 290 | (llk--define-xk xk-shift-l #xffe1 #xA0) ;; XK_Shift_L VK_LSHIFT |
| 144 | (define-xk xk-shift-r #xffe2 #xA1) ;; XK_Shift_R VK_RSHIFT | 291 | (llk--define-xk xk-shift-r #xffe2 #xA1) ;; XK_Shift_R VK_RSHIFT |
| 145 | (define-xk xk-control-l #xffe3 #xA2) ;; XK_Control_L VK_LCONTROL | 292 | (llk--define-xk xk-control-l #xffe3 #xA2) ;; XK_Control_L VK_LCONTROL |
| 146 | (define-xk xk-control-r #xffe4 #xA3) ;; XK_Control_R VK_RCONTROL | 293 | (llk--define-xk xk-control-r #xffe4 #xA3) ;; XK_Control_R VK_RCONTROL |
| 147 | (define-xk xk-caps-lock #xffe5 #x14) ;; XK_Caps_Lock VK_CAPITAL | 294 | (llk--define-xk xk-caps-lock #xffe5 #x14) ;; XK_Caps_Lock VK_CAPITAL |
| 148 | (define-xk xk-metal-l #xffe7 nil) ;; XK_Meta_L | 295 | (llk--define-xk xk-meta-l #xffe7 nil) ;; XK_Meta_L |
| 149 | (define-xk xk-metal-t #xffee nil) ;; XK_Meta_R | 296 | (llk--define-xk xk-meta-r #xffee nil) ;; XK_Meta_R |
| 150 | (define-xk xk-alt-l #xffe9 #xA4) ;; XK_Alt_L VK_LMENU | 297 | (llk--define-xk xk-alt-l #xffe9 #xA4) ;; XK_Alt_L VK_LMENU |
| 151 | (define-xk xk-alt-r #xffea #xA5) ;; XK_Alt_R VK_RMENU | 298 | (llk--define-xk xk-alt-r #xffea #xA5) ;; XK_Alt_R VK_RMENU |
| 152 | (define-xk xk-super-l #xffeb nil) ;; XK_Super_L | 299 | (llk--define-xk xk-super-l #xffeb nil) ;; XK_Super_L |
| 153 | (define-xk xk-super-r #xffec nil) ;; XK_Super_R | 300 | (llk--define-xk xk-super-r #xffec nil) ;; XK_Super_R |
| 154 | (define-xk xk-hyper-l #xffed nil) ;; XK_Hyper_L | 301 | (llk--define-xk xk-hyper-l #xffed nil) ;; XK_Hyper_L |
| 155 | (define-xk xk-hyper-r #xffee nil) ;; XK_Hyper_R | 302 | (llk--define-xk xk-hyper-r #xffee nil) ;; XK_Hyper_R |
| 156 | 303 | ||
| 157 | ;; Latin 1 | 304 | ;; Latin 1 |
| 158 | ;; For numbers and letters, MS-Windows does not define constant names. | 305 | ;; For numbers and letters, MS-Windows does not define constant names. |
| 159 | ;; X11 defines distinct keysyms for lowercase and uppercase | 306 | ;; X11 defines distinct keysyms for lowercase and uppercase |
| 160 | ;; letters. We use only the uppercase ones. Events with lowercase | 307 | ;; letters. We use only the uppercase ones. Events with lowercase |
| 161 | ;; letters are converted to uppercase. | 308 | ;; letters are converted to uppercase. |
| 162 | (define-xk xk-space #x0020 #x20) ;; XK_space VK_SPACE | 309 | (llk--define-xk xk-space #x0020 #x20) ;; XK_space VK_SPACE |
| 163 | (define-xk xk-0 #x0030 #x30) ;; XK_0 | 310 | (llk--define-xk xk-0 #x0030 #x30) ;; XK_0 |
| 164 | (define-xk xk-1 #x0031 #x31) ;; XK_1 | 311 | (llk--define-xk xk-1 #x0031 #x31) ;; XK_1 |
| 165 | (define-xk xk-2 #x0032 #x32) ;; XK_2 | 312 | (llk--define-xk xk-2 #x0032 #x32) ;; XK_2 |
| 166 | (define-xk xk-3 #x0033 #x33) ;; XK_3 | 313 | (llk--define-xk xk-3 #x0033 #x33) ;; XK_3 |
| 167 | (define-xk xk-4 #x0034 #x34) ;; XK_4 | 314 | (llk--define-xk xk-4 #x0034 #x34) ;; XK_4 |
| 168 | (define-xk xk-5 #x0035 #x35) ;; XK_5 | 315 | (llk--define-xk xk-5 #x0035 #x35) ;; XK_5 |
| 169 | (define-xk xk-6 #x0036 #x36) ;; XK_6 | 316 | (llk--define-xk xk-6 #x0036 #x36) ;; XK_6 |
| 170 | (define-xk xk-7 #x0037 #x37) ;; XK_7 | 317 | (llk--define-xk xk-7 #x0037 #x37) ;; XK_7 |
| 171 | (define-xk xk-8 #x0038 #x38) ;; XK_8 | 318 | (llk--define-xk xk-8 #x0038 #x38) ;; XK_8 |
| 172 | (define-xk xk-9 #x0039 #x39) ;; XK_9 | 319 | (llk--define-xk xk-9 #x0039 #x39) ;; XK_9 |
| 173 | (define-xk xk-a #x0041 #x41) ;; XK_A | 320 | (llk--define-xk xk-a #x0041 #x41) ;; XK_A |
| 174 | (define-xk xk-b #x0042 #x42) ;; XK_B | 321 | (llk--define-xk xk-b #x0042 #x42) ;; XK_B |
| 175 | (define-xk xk-c #x0043 #x43) ;; XK_C | 322 | (llk--define-xk xk-c #x0043 #x43) ;; XK_C |
| 176 | (define-xk xk-d #x0044 #x44) ;; XK_D | 323 | (llk--define-xk xk-d #x0044 #x44) ;; XK_D |
| 177 | (define-xk xk-e #x0045 #x45) ;; XK_E | 324 | (llk--define-xk xk-e #x0045 #x45) ;; XK_E |
| 178 | (define-xk xk-f #x0046 #x46) ;; XK_F | 325 | (llk--define-xk xk-f #x0046 #x46) ;; XK_F |
| 179 | (define-xk xk-g #x0047 #x47) ;; XK_G | 326 | (llk--define-xk xk-g #x0047 #x47) ;; XK_G |
| 180 | (define-xk xk-h #x0048 #x48) ;; XK_H | 327 | (llk--define-xk xk-h #x0048 #x48) ;; XK_H |
| 181 | (define-xk xk-i #x0049 #x49) ;; XK_I | 328 | (llk--define-xk xk-i #x0049 #x49) ;; XK_I |
| 182 | (define-xk xk-j #x004A #x4A) ;; XK_J | 329 | (llk--define-xk xk-j #x004A #x4A) ;; XK_J |
| 183 | (define-xk xk-k #x004B #x4B) ;; XK_K | 330 | (llk--define-xk xk-k #x004B #x4B) ;; XK_K |
| 184 | (define-xk xk-l #x004C #x4C) ;; XK_L | 331 | (llk--define-xk xk-l #x004C #x4C) ;; XK_L |
| 185 | (define-xk xk-m #x004D #x4D) ;; XK_M | 332 | (llk--define-xk xk-m #x004D #x4D) ;; XK_M |
| 186 | (define-xk xk-n #x004E #x4E) ;; XK_N | 333 | (llk--define-xk xk-n #x004E #x4E) ;; XK_N |
| 187 | (define-xk xk-o #x004F #x4F) ;; XK_O | 334 | (llk--define-xk xk-o #x004F #x4F) ;; XK_O |
| 188 | (define-xk xk-p #x0050 #x50) ;; XK_P | 335 | (llk--define-xk xk-p #x0050 #x50) ;; XK_P |
| 189 | (define-xk xk-q #x0051 #x51) ;; XK_Q | 336 | (llk--define-xk xk-q #x0051 #x51) ;; XK_Q |
| 190 | (define-xk xk-r #x0052 #x52) ;; XK_R | 337 | (llk--define-xk xk-r #x0052 #x52) ;; XK_R |
| 191 | (define-xk xk-s #x0053 #x53) ;; XK_S | 338 | (llk--define-xk xk-s #x0053 #x53) ;; XK_S |
| 192 | (define-xk xk-t #x0054 #x54) ;; XK_T | 339 | (llk--define-xk xk-t #x0054 #x54) ;; XK_T |
| 193 | (define-xk xk-u #x0055 #x55) ;; XK_U | 340 | (llk--define-xk xk-u #x0055 #x55) ;; XK_U |
| 194 | (define-xk xk-v #x0056 #x56) ;; XK_V | 341 | (llk--define-xk xk-v #x0056 #x56) ;; XK_V |
| 195 | (define-xk xk-w #x0057 #x57) ;; XK_W | 342 | (llk--define-xk xk-w #x0057 #x57) ;; XK_W |
| 196 | (define-xk xk-x #x0058 #x58) ;; XK_X | 343 | (llk--define-xk xk-x #x0058 #x58) ;; XK_X |
| 197 | (define-xk xk-y #x0059 #x59) ;; XK_Y | 344 | (llk--define-xk xk-y #x0059 #x59) ;; XK_Y |
| 198 | (define-xk xk-z #x005A #x5A));; XK_Z | 345 | (llk--define-xk xk-z #x005A #x5A));; XK_Z |
| 199 | |||
| 200 | (defun llk-init () | ||
| 201 | "Initialize low level key events. | ||
| 202 | |||
| 203 | Fills the `llk-keysyms' list, and binds the `low-level-key' event | ||
| 204 | to the `llk-handle' function. Resets the `llk-bindings' list. | ||
| 205 | Besides calling this function, you need to set `enable-low-level-key-events' | ||
| 206 | to a non-nil value." | ||
| 207 | (interactive) | ||
| 208 | (llk-define-keysyms) | ||
| 209 | (define-key special-event-map [low-level-key] 'llk-handle) | ||
| 210 | (setq llk-bindings nil)) | ||
| 211 | |||
| 212 | (defsubst event-is-key-press (event) | ||
| 213 | "Return the value of the IS-KEY-PRESS field of the EVENT, a low level key event." | ||
| 214 | (declare (side-effect-free t)) | ||
| 215 | (if (consp event) (nth 1 event))) | ||
| 216 | |||
| 217 | (defsubst event-keysym (event) | ||
| 218 | "Return the value of the KEY field of the EVENT, a low level key event." | ||
| 219 | (declare (side-effect-free t)) | ||
| 220 | (if (consp event) (nth 2 event))) | ||
| 221 | |||
| 222 | (defsubst event-modifier (event) | ||
| 223 | "Return the value of the MODIFIER field of the EVENT, a low level key event." | ||
| 224 | (declare (side-effect-free t)) | ||
| 225 | (if (consp event) (nth 3 event))) | ||
| 226 | |||
| 227 | (defsubst event-time (event) | ||
| 228 | "Return the value of the TIME field of the EVENT, a low level key event." | ||
| 229 | (declare (side-effect-free t)) | ||
| 230 | (if (consp event) (nth 4 event))) | ||
| 231 | |||
| 232 | ;; For example: | ||
| 233 | ;; Bind key tap to command | ||
| 234 | ;; (llk-bind 'tap 'xk-shift-l 'delete-other-windows) | ||
| 235 | ;; Bind modifier tap to command | ||
| 236 | ;; (llk-bind 'tap 'shift 'delete-other-windows) | ||
| 237 | ;; Bind tap to hyper modifier | ||
| 238 | ;; (llk-bind 'tap 'xk-shift-r (lambda () | ||
| 239 | ;; (message "H-...") | ||
| 240 | ;; (setq unread-command-events | ||
| 241 | ;; (append (event-apply-hyper-modifier nil) nil)))) | ||
| 242 | ;; Can bind to a command or function | ||
| 243 | (defun llk-bind (action key function) | ||
| 244 | "Bind a command or function to a low level key event. | ||
| 245 | |||
| 246 | The only action supported currently is `tap'. The key can be a keysym | ||
| 247 | symbol, or a modifier symbol (shift, control, alt, meta, hyper, super). | ||
| 248 | If there is no keysym symbol for a key, use the keysym number." | ||
| 249 | (push (list action key function) llk-bindings)) | ||
| 250 | |||
| 251 | ;; We store the last events (key/modifier is-press timestamp) here to | ||
| 252 | ;; test for multitap. | ||
| 253 | (defvar llk-events nil | ||
| 254 | "Internal variable for detecting taps.") | ||
| 255 | |||
| 256 | ;; If positive, return key (xk-shift-l, etc) else return nil. | ||
| 257 | (defun llk-detect-n-tap (n timeout) | ||
| 258 | "Internal function to detect n-tap keys." | ||
| 259 | (let (key | ||
| 260 | (is-press (event-is-key-press last-input-event)) | ||
| 261 | ;; convert number to keysym symbol | ||
| 262 | (keysym (cdr (assoc (event-keysym last-input-event) llk-keysyms))) | ||
| 263 | (timestamp (event-time last-input-event)) | ||
| 264 | (modifier (event-modifier last-input-event))) | ||
| 265 | |||
| 266 | ;; if ehte is no symbol for this key, use its keysym number | ||
| 267 | (unless keysym (setq keysym (event-keysym last-input-event))) | ||
| 268 | |||
| 269 | ;; look in llk-tap-keys for the key, then the modifier | ||
| 270 | (if (member keysym llk-tap-keys) | ||
| 271 | (setq key keysym) | ||
| 272 | (if (member modifier llk-tap-keys) | ||
| 273 | (setq key modifier))) | ||
| 274 | |||
| 275 | (if (not key) | ||
| 276 | ;; Key not in tap list, clear history | ||
| 277 | (setq llk-events nil) | ||
| 278 | ;; Clear it also if the first element is from a different key | ||
| 279 | (and llk-events | ||
| 280 | (not (equal (car (car llk-events)) key)) | ||
| 281 | (setq llk-events nil)) | ||
| 282 | (push (list key is-press timestamp) llk-events) | ||
| 283 | ;; Only care about last 2xN events | ||
| 284 | (ntake (* 2 n) llk-events) | ||
| 285 | ;; If we have: | ||
| 286 | ;; - Exactly 2 * n events. | ||
| 287 | ;; - down, up, down, up, ... | ||
| 288 | ;; - not two much time between first and last | ||
| 289 | (and (eq (* 2 n) (length llk-events)) | ||
| 290 | (cl-every 'eq | ||
| 291 | (ntake (* 2 n) | ||
| 292 | (list nil t nil t nil t nil t | ||
| 293 | nil t nil t nil t nil t)) | ||
| 294 | (mapcar 'cl-second llk-events)) | ||
| 295 | (< (- (cl-third (cl-first llk-events)) | ||
| 296 | (cl-third (car (last llk-events)))) | ||
| 297 | timeout) | ||
| 298 | (progn | ||
| 299 | (setq llk-events nil) | ||
| 300 | key))))) | ||
| 301 | 346 | ||
| 302 | (defun describe-low-level-key () | 347 | (defun describe-low-level-key () |
| 303 | "Wait for key press and describe the low level key event it generates." | 348 | "Wait for key press and describe the low-level key event it generates." |
| 304 | (interactive) | 349 | (interactive) |
| 305 | (setq llk-describe-next-press t)) | 350 | (define-key special-event-map [low-level-key] 'llk--describe)) |
| 306 | |||
| 307 | (defun llk-show-event-description () | ||
| 308 | "Show information about the last low level key event." | ||
| 309 | (setq llk-describe-next-press nil) | ||
| 310 | (with-help-window (help-buffer) | ||
| 311 | (insert "\n") | ||
| 312 | (let* ((xk (event-keysym last-input-event)) | ||
| 313 | (sym (assoc xk llk-keysyms))) | ||
| 314 | (insert (format "Keysym number: %d (#x%X),\n" xk xk)) | ||
| 315 | (if sym | ||
| 316 | (insert (format "which corresponds to named key %s.\n\n" (cdr sym))) | ||
| 317 | (insert "which does not correspond to any known named key.\n\n")) | ||
| 318 | (if (event-modifier last-input-event) | ||
| 319 | (insert (format "This key corresponds to the %s modifier.\n\n" | ||
| 320 | (event-modifier last-input-event))) | ||
| 321 | (insert "This key does not correspond to a modifier.\n\n")) | ||
| 322 | (insert "See the value of the `llk-keysyms' variable for a list of known keys.\n")))) | ||
| 323 | 351 | ||
| 324 | (defun llk-handle () | 352 | (defun llk--describe () |
| 325 | "Internal function to handle low level key events." | 353 | "Internal function for `special-event-map' to describe low level key events." |
| 326 | (interactive) | 354 | (interactive) |
| 327 | (if (and (event-is-key-press last-input-event) | 355 | (when (low-level-key-is-key-press last-input-event) |
| 328 | llk-describe-next-press) | 356 | (define-key special-event-map [low-level-key] 'llk-handle) |
| 329 | (llk-show-event-description) | 357 | (with-help-window (help-buffer) |
| 330 | (let ((tap-key (llk-detect-n-tap | 358 | (insert "\n") |
| 331 | llk-tap-count | 359 | (let* ((xk (low-level-key-key last-input-event)) |
| 332 | llk-tap-timeout))) | 360 | (sym (assoc xk llk-keysyms))) |
| 333 | (when tap-key | 361 | (insert (format "Keysym number: %d (#x%X),\n" xk xk)) |
| 334 | (let ((func (cl-third | 362 | (if sym |
| 335 | (seq-find | 363 | (insert (format "which corresponds to named key %s.\n\n" (cdr sym))) |
| 336 | (lambda (b) | 364 | (insert "which does not correspond to any known named key.\n\n")) |
| 337 | (and (eq (cl-first b) 'tap) | 365 | (if (low-level-key-modifier last-input-event) |
| 338 | (eq (cl-second b) tap-key))) | 366 | (insert (format "This key corresponds to the %s modifier.\n\n" |
| 339 | llk-bindings)))) | 367 | (low-level-key-modifier last-input-event))) |
| 340 | (cond | 368 | (insert "This key does not correspond to a modifier.\n\n")) |
| 341 | ((commandp func) (call-interactively func)) | 369 | (insert "See the value of the `llk-keysyms' variable for a list of known keys.\n"))))) |
| 342 | ((functionp func) (funcall func)))))))) | 370 | |
| 371 | (llk--define-keysyms) | ||
| 372 | (define-key special-event-map [low-level-key] 'llk-handle) | ||
| 373 | (setq llk-bindings nil) | ||
diff --git a/src/keyboard.c b/src/keyboard.c index 4bf02a06696..f5e9dc40a33 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -13158,13 +13158,8 @@ The value configures the set of keys that are handled: | |||
| 13158 | 13158 | ||
| 13159 | If t, send events for all keys. | 13159 | If t, send events for all keys. |
| 13160 | 13160 | ||
| 13161 | If a number, send events for the corresponding keysym. When calling | 13161 | If a number, send events for the corresponding keysym. This numbers are |
| 13162 | `llk-init', a set of variables with the xk- prefix is initialized with | 13162 | platform dependente. See `llk-keysyms'. |
| 13163 | the numeric values for keysyms. Because this number are platform | ||
| 13164 | dependent, only the variables should be used to refer to a key. For | ||
| 13165 | example, the 'xk-backspace' variable refer to the backspace key, with | ||
| 13166 | the numeric value 0xff08 on X, and the 0x08 on MS-Windows. You can see | ||
| 13167 | all defined variables on the variable `llk-keysyms'. | ||
| 13168 | 13163 | ||
| 13169 | If a symbol, a predefined set of keys is selected. The only currently | 13164 | If a symbol, a predefined set of keys is selected. The only currently |
| 13170 | valid symbol is 'modifiers. | 13165 | valid symbol is 'modifiers. |