1

The problem in brief

I want to redefine what clicking (on an org link) does. My code works, if I click slowly enough, but for a normal (fast) click it does not -- instead I get the default behavior. Changing ordinary keyboard shortcuts in the org-mode keymap works fine.

[Sidenote: If I could instead change the behavior of org-open-at-point, to call delete-other-windows after running, that would be a more natural, if less declarative, solution.]

I'm finding nothing in the Emacs docs about click duration, although I do see that events have timestamps.

My code, and the reasoning behind it

I've tried both of the following:

(define-key org-mode-map [mouse-1]         'jbb-org-open-at-point)
(define-key org-mode-map (kbd "<mouse-1>") 'jbb-org-open-at-point)

Both have the same effect. Slow-clicking on a link runs jbb-org-open-at-point, like I hoped, but fast-clicking runs the default org-open-at-point.

Thanks to @Drew I understand that mouse-1 represents releasing the button, and down-mouse-1 represents pressing the button. Since I want to preserve the default down-mouse-1 behavior, which is to move the cursor to wherever the mouse is, I'm not mentioning down-mouse-1 in my code.

I tried replacing mouse-1 in the above code with up-mouse-1. That was no good -- short clicks still had the default behavior, but long clicks had no effect.

Details that might not be important

My definition of jbb-org-open-at-point

It's just like org-open-at-point, except the new buffer occupies the entire window, rather than half of it. It does nothing if org-mode is not the major mode.

(defun jbb-org-open-at-point ()
  (interactive)
  (if ;; TODO ? Maybe I should simplify this.
      ;; This if-else clause testing the major mode is unnecessary,
      ;; because `jbb-org-open-at-point`
      ;; will only be called via the shortcut defined next,
      ;; which is only available from org-mode.
      (equal "org-mode" (symbol-name major-mode))
      (progn (call-interactively 'org-open-at-point)
         (delete-other-windows))
    (message ("jbb-org-open-at-point does nothing outside of org-mode."))
))

Remapping keyboard (as opposed to mouse) shortcuts works as expected

I can successfully redefine C-c C-o in the org-mode keyboard map, so that it uses the new jbb-org-open-at-point instead of the default org-open-at-point:

(define-key org-mode-map (kbd "C-c C-o")   'jbb-org-open-at-point)

I know that works because after doing that, if I type C-c C-o while the cursor is on an org link, the new buffer occupies the entire window, rather than half of it.

1 Answers1

2

A mouse click results in multiple events.

If you want the action to take place upon the button press, and the button-release to be ignored, you can use this, for example:

(define-key org-mode-map [down-mouse-1] 'jbb-org-open-at-point)
(define-key org-mode-map [mouse-1]      'ignore)

Or if you want the action to take place upon release and the press to be ignored, then reverse those two "keys".

Also, your command needs to have an interactive spec that corresponds to a mouse event - something like this:

(defun jbb-org-open-at-point (_event)
  "..."
  (interactive "e") ; Event is ignored.
  ...)

Your code seems to ignore the mouse event, beyond the fact of it happening. But if, for example, you wanted to use the mouse-point position and not point, then you could use something like this:

(defun jbb-org-open-at-point (event)
  "..."
  (interactive "e")
  (let* ((mouse-pos  (event-start event))
         (mouse-win  (posn-window mouse-pos))
         (mouse-pt   (posn-point  mouse-pos)))
    (with-current-buffer (window-buffer mouse-win)
      (save-excursion
        (goto-char mouse-pt)
        ... ; do stuff at click position
   ...))))

See the Elisp manual, node Accessing Mouse.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Related Q&A: https://emacs.stackexchange.com/questions/64964/difference-between-mouse-1-and-down-mouse-1 – phils Apr 07 '23 at 01:17
  • Thanks, Drew! (I can't seem to @ you.) It's more complicated than I thought. Today I edited my OP to reflect the discovery, which you led me to, that my code works if I click slowly. The `org-mode` `keymap` appears to move point to where the click happened on mouse-down, which behavior I still want, so I'm not defining any new behavior of `down-mouse-1`. When I modify the function definition to use `interactive "e"` and accept but ignore an `_event` argument, like you suggest, I see no change in behavior -- slow clicks still work, and fast (normal) clicks still don't. – Jeffrey Benjamin Brown Apr 07 '23 at 17:25