8

Is there a way, via some command that can be invoked by the keyboard, of making Emacs think that I clicked at a particular point (so that it does whatever it would have done if I clicked there, e.g. follow link or pop up a menu)? Or that I hovered mouse at point (so that tool tip pops up)?

[Motivation: Some modes decorate the buffer, turning some text into links and so on. I may know how to do something with the mouse (e.g. click on it), but not the equivalent keyboard shortcut/command to invoke. Of course I should read documentation for the mode and learn it, but thought it's an interesting question.]

  • 2
    I am especially interested in whether you can simulate a hover with the keyboard. It is not uncommon for a tool-tip to be the easiest place to find the information I am looking for. – nispio Oct 9 '14 at 19:20
  • @nispio you can preview the tooltip at point with display-local-help – Malabarba Oct 10 '14 at 1:19
  • @Malabarba: Thanks very much; that seems to work! – ShreevatsaR Oct 10 '14 at 1:46
5

Often, navigating to a location and pressing some key will have the same effect as clicking at that location. There's no built-in mechanism that ensures this, it's just that modes are typically written that way.

You can generate mouse events (click, double/triple/… click, button down/up, drag, motion). All mouse events have the form (TYPE POSITION . EXTRA-DATA) where TYPE is a symbol that encodes the mouse button, the nature of the action (click, drag, etc.), and the modifiers. TYPE is mouse-movement for a motion event. Call posn-at-point to generate the POSITION for the location of the point in the current buffer.

Here's some proof-of-concept code that simulates a mouse click at the cursor position when you press f11 followed by a digit. Modifiers are taken into account.

(defun make-mouse-event-at-point (base-event)
  (let ((posn (posn-at-point))
        (prefix "")
        (basic-type (event-basic-type base-event))
        (modifiers (event-modifiers base-event)))
    (cond
     ((and (integerp basic-type) (>= basic-type ?0) (<= basic-type ?9))
      ;; click
      (let* ((mouse-type (intern (format "%smouse-%d" prefix (- basic-type ?0))))
             (click-count 1)
             (type (event-convert-list (append modifiers (list mouse-type)))))
        (list type posn click-count)))
     (t
      (error "Unsupported key for mouse event: %s" (event-basic-type base-event))))))
(defun simulate-mouse-event-at-point ()
  (interactive)
  (let ((event (make-mouse-event-at-point last-input-event)))
    (setq unread-command-events (cons event unread-command-events))))

(defvar simulate-mouse-event-map (make-sparse-keymap))
(global-set-key [f11] simulate-mouse-event-map)
(define-key simulate-mouse-event-map [t] 'simulate-mouse-event-at-point)

Simulating hover looks more difficult.

  • 1
    This doesn't simulate hover, but if all you want is to see a tooltip, you can preview the tooltip at point with display-local-help – Malabarba Oct 10 '14 at 1:20
  • I'm still trying this out, but in response to the first couple of sentences: the reason I asked this question is that I'm working in a mode where the "some key" is not clear (it happens to be C-c C-, RET, but I had to look up the mode's documentation for that). – ShreevatsaR Oct 10 '14 at 1:45
  • Actually this doesn't quite work. In the mode I'm working in, some piece of code is turned into a link, and clicking with the mouse opens up a menu at the point. Doing the above with f11 1 doesn't do that (it prints something in the minibuffer but it's not the equivalent of a mouse click on the link) though f11 3 does seem to be equivalent to <mouse-3> and so on. – ShreevatsaR Oct 10 '14 at 1:52
  • @ShreevatsaR Maybe the mouse click action you want is bound to down-mouse-1 and not mouse-1? How can I find out in which keymap a key is bound? may help investigate this. – Gilles 'SO- stop being evil' Oct 10 '14 at 7:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.