7

I am working with Emacs on Cygwin, which actually has 3 types of Emacsen:

  • Win32 Emacs, which is a graphical Emacs compiled to use native Windows GUI (so no X windows is required)
  • Terminal Emacs, which displays in the mintty terminal by default
  • X Windows Emacs (requires X, and not relevant to this question)

I am trying to bind the APPS key (the one with the little menu on it, usually to the right of the right-hand Windows key, I think it is properly known as the MENU key, https://en.wikipedia.org/wiki/Menu_key) to the "super" modifier (gotta love those short key sequences). In Win32 Emacs this is pretty easy:

(when (equal window-system 'w32)
    (setq w32-pass-apps-to-system nil
          w32-apps-modifier 'super))

This makes Emacs treat APPS as super and stops it passing it onto the OS. It then becomes trivial to make bindings such as

(define-key global-map (kbd "s-r") 'recentf-open-files)

Problem

How to make terminal mode Emacs also treat APPS as super? Firstly it was necessary to have mintty changed to pass through the APPS key to Emacs; this has been done already by the maintainer (see https://github.com/mintty/mintty/issues/494) and we can now configure mintty to send any escape sequence we want through to Emacs.

As I said in the issue, the initial suggestion of Key_Menu=29 (which results in ESC [ 2 9 ~ appearing in the view-lossage log), appears to be interpreted by Emacs as the "<print>" key, so that I can succesfully bind using

(global-set-key (kbd "<print> r") 'recentf-open-files)

The above, while it is a great advance, is not ideal because 2 sets of bindings would be required, one for terminal mode and one for graphical windowed mode.

Things that I don't know

  • How does Emacs translate a sequence of input characters into a logical key?
  • Why does terminal Emacs think the ESC 29 sequence is the print key?
  • Does terminal Emacs even know about the APPS key?

Question

  • How can I configure W32 Emacs and terminal Emacs so that they both treat APPS/MENU as the super modifier, thus enabling a single set of keybindings to be used in both cases?
Philip Daniels
  • 221
  • 1
  • 5
  • 1
    Please edit the post so that it asks one clear question. If you have multiple questions, feel free to make multiple posts. – Dan Nov 20 '15 at 10:57
  • Interesting question! I don't have an answer, but if you're using mintty, this page may have part of your answer: https://code.google.com/p/mintty/wiki/Keycodes . – Sue D. Nymme Nov 20 '15 at 13:42
  • 1
    I found out why Emacs thinks it is the `print` key. There is a line in list\term\xterm.el.gz which maps that sequence to print: `(define-key map "\e[29~" [print])` – Philip Daniels Nov 22 '15 at 11:22
  • Please consider accepting your own answer. This question still shows up on the unanswered list. Thx. – Drew Feb 11 '19 at 17:55

1 Answers1

6

I made quite a bit of progress on this. Reading up on key translation I found this Emacs manual page on Translation keymaps which has an interesting hyperify function

(defun hyperify (prompt)
  (let ((e (read-event)))
    (vector (if (numberp e)
                (logior (lsh 1 24) e)
              (if (memq 'hyper (event-modifiers e))
                  e
                (add-event-modifier "H-" e))))))

(defun add-event-modifier (string e)
  (let ((symbol (if (symbolp e) e (car e))))
    (setq symbol (intern (concat string
                                 (symbol-name symbol))))
    (if (symbolp e)
        symbol
      (cons symbol (cdr e)))))

(define-key local-function-key-map "\C-ch" 'hyperify)

An equivalent superify function can be written by replacing the lsh 1 24 with lsh 1 23 (see Emacs page on character modifier bits). However, googling hyperify resulted in a hit on the Emacs wiki called "StickyModifiers" which mentions a built in function to achieve this called event-apply-super-modifier. I guess the manual is a bit out of date or it was just for pedagogical purposes. In any case, this will make APPS/MENU into a super key in both terminal and W32 Emacs under mintty:

(if (equal system-type 'cygwin)
     (if (equal window-system 'w32)
         (setq w32-pass-apps-to-system nil
               w32-apps-modifier 'super)
       (define-key local-function-key-map (kbd "<print>") 'event-apply-super-modifier)))

 (define-key global-map (kbd "s-h") (lambda () (interactive) (message "hello from menu key via s- prefix")))

Problem It is not perfect however, because holding the APPS key down results in the string [29~ being repeatedly written into the buffer, so you have to be quick. Contrast this with the way that the Alt key works: you can hold it down for as long as you want.

Alternative Technique Over at ErgoEmacs I found an article talking about leader keys, which unfortunately I cannot post because reputation is no longer high enough having given it all to bounty. SIGH. Anyway, it is called "emacs_menu_app_keys". Using this technique:

(if (equal system-type 'cygwin)
     (if (equal window-system 'w32)
         (setq w32-pass-apps-to-system nil
               w32-apps-modifier nil)
       (progn ;; force all alternatives to <apps> so we can write one set of keybindings.
         (define-key key-translation-map (kbd "<print>") (kbd "<apps>"))
         (define-key key-translation-map (kbd "<menu>") (kbd "<apps>")))))

 (define-key global-map (kbd "<apps> h")
    (lambda () (interactive) (message "hello from menu key via <apps> leader key")))

This works great, you press and release APPS before pressing H. I think I prefer it to the first technique as it is easier to type and this prefix key will be reserved for mnemonic-style, one-shot function bindings anyway i.e. nothing that I need to press repeatedly like C-n.

Bounty If anybody can come up with something better, especially if they can get the first technique to work as perfectly as using the Alt or Ctrl keys I will still award the bounty to them.

Philip Daniels
  • 221
  • 1
  • 5
  • Sadly, I don't have a menu/apps key, and I can't seem to reproduce the problem without it. – PythonNut Nov 26 '15 at 22:28
  • Late comment: for some other keys I have written "debouncing" code in AutoHotKey outside of emacs. used for a PTT Push(-and-hold) To Talk key with a speech recognition system, so it wasn't emitting modified characters, just turning the microphone on and off, and had to kill the multiple key down events produced by autorepeat. I am not sure that I recommend this because it is timing sensitive, but it solved my immediate problem - but eventually I found a completely different non-PTT approach and I'm no longer using PTT. // Unfortunately, I cannot try it on your AppsKey right now. – Krazy Glew Jan 17 '22 at 22:22