Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Basic mouse support #166

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Conversation

iqbalansari
Copy link
Contributor

Hi,

This pull request adds really basic mouse support

  • The which-key pop-up is not hidden if the mouse events happen inside the pop-up
  • The mouse wheel can be used to navigate to the next and previous pages

I still have to figure out how to make this work with the minibuffer, minibuffer is always hidden by Emacs on mouse events, I need to see if Emacs provides a way to temporarily change this behavior, any ideas?

@justbur
Copy link
Owner

justbur commented Apr 11, 2017

Interesting. I just tried it and it doesn't seem to work with my trackpad. That could be something I'm overlooking right now.

Were you thinking about this issue?

@iqbalansari
Copy link
Contributor Author

Yes, #159 is what this pull request attempts to solve. I did not get a chance to try this on a trackpad, but I am surprised it is not working with trackpad, it seems Emacs handles it differently from the mouse wheel.

@iqbalansari
Copy link
Contributor Author

Hi @justbur, I tried this with trackpad and it worked, except that the popup would be hidden certain unhandled mouse events, I have pushed a fix to handle them. Could you try it?

Also in case it does not work, could you help me debug this, I debug the the issues by changing which-key--hide-popup to the following to log the events that cause the popup to be hidden

(defun which-key--hide-popup ()
  "This function is called to hide the which-key buffer."
  (unless (or (member real-this-command which-key--paging-functions)
              ;; Do not hide the popup the if the last event was a mouse
              ;; event and was inside which-key popup
              (and (or (mouse-event-p last-command-event)
                       ;; 'mwheel-scroll events are not recognized as mouse
                       ;; events
                       (equal real-this-command 'mwheel-scroll))
                   (which-key--mouse-event-inside-which-key-p last-command-event))
              ;; The mouse event was not handled by Emacs
              (and (not this-command)
                   (string-prefix-p "mouse-"
                                    ;; Using prin1-to-string since it can handle
                                    ;; all kinds of values returned by `event-basic-type'
                                    (prin1-to-string (event-basic-type last-command-event)))))
    (message "%s - %s" this-command last-command-event)
    (setq which-key--current-page-n nil
          which-key--current-prefix nil
          which-key--using-top-level nil
          which-key--using-show-keymap nil
          which-key--using-show-operator-keymap nil
          which-key--current-show-keymap-name nil
          which-key--prior-show-keymap-args nil
          which-key--on-last-page nil)
    (when (and which-key-idle-secondary-delay
               which-key--secondary-timer-active)
      (which-key--start-timer))
    (cl-case which-key-popup-type
      ;; Not necessary to hide minibuffer
      ;; (minibuffer (which-key--hide-buffer-minibuffer))
      (side-window (which-key--hide-buffer-side-window))
      (frame (which-key--hide-buffer-frame))
      (custom (funcall which-key-custom-hide-popup-function)))))

@justbur
Copy link
Owner

justbur commented Apr 17, 2017

Hi @iqbalansari, I haven't dug into the code yet, but I just tried it. The popup is not getting hidden on the mouse wheel events, but not all of them are being handled. If I scroll the wheel quickly, it seems like every third step or so triggers the page turn but the rest show up as something like C-x <mouse-4> is undefined.

@iqbalansari
Copy link
Contributor Author

iqbalansari commented Apr 17, 2017

You are right, it seems Emacs treats the scroll event as part of ongoing key sequence. It did not happen for me because I was testing it for toplevel binding (how stupid of me 🤦‍♂️). I wonder why it works for some scroll events though. Let me investigate a bit more.

I think the issue with undefined mouse bindings can be solved by adding keybinding for prefix + mouse[1-5], not sure we want to go that route though, would be incredibly hacky.

@iqbalansari
Copy link
Contributor Author

I realized why it works for alternate keybindings, the first scroll fails with undefined error and returns to the toplevel, but the which key popup is not hid and the which key state is not destroyed, since the mouse event was on the popup.

The next scroll event works since it is essentially invokes the global keybinding for mouse scroll, which causes the page to scroll using the preserved state from previous invocation and reloads whatever the key prefix was.

So this thing worked only by chance on non-toplevel popups. Sorry for the noise 😔

The only solution I can think at this point is adding extra keybinding for mouse events on the keymaps (like which-key does to support which-key-paging-key). We can create a local keymap for the popup buffer while displaying the popup, so that it does not affect rest of the system, not sure it would work just a thought. What do you think?

@justbur
Copy link
Owner

justbur commented Apr 18, 2017

The only solution I can think at this point is adding extra keybinding for mouse events on the keymaps (like which-key does to support which-key-paging-key).

This seems like the only option. which-key-define-key-recursively works pretty well for this purpose, but it's still a little cumbersome.

We can create a local keymap for the popup buffer while displaying the popup, so that it does not affect rest of the system, not sure it would work just a thought. What do you think?

I believe the local keymap will only work when you are not already in the middle of a key sequence (ie at the top level)

@iqbalansari
Copy link
Contributor Author

iqbalansari commented Apr 18, 2017

I believe the local keymap will only work when you are not already in the middle of a key sequence (ie at the top level)

I just did a quick test, using the following snippet

(progn
  ;; Make sure there is no keybinding for C-x left-click
  (global-set-key (kbd "C-x <mouse-1>") nil)
  ;; Set keybinding after 1 second, so that the keybinding is set after the C-x
  ;; input
  (run-at-time 1 nil
               (lambda ()
                 (message "Setup the binding, now click ...")
                 (global-set-key (kbd "C-x <mouse-1>") (lambda (&rest ignored)
                                                         (interactive "e")
                                                         (message "Worked")))))
  ;; Fake 'C-x' input
  (setq unread-command-events (listify-key-sequence (kbd "C-x"))))

Now doing a left click after the message "Setup the binding, now click ..." echoes "Worked" as expected, so I guess this can work, am I missing something?

@justbur
Copy link
Owner

justbur commented Apr 21, 2017 via email

@iqbalansari
Copy link
Contributor Author

You seem to be right, I have hit some wierd issue, even though example above works for me (changes to global as well as local keymap are picked up), Emacs does not seem to be picking up the modified binding, if I do it after/while the which-key popup is displayed (there are some nuances, I will post later), any ideas?

Also assuming the strategy of updating the keybindings does not work, what other options do we have?

@justbur
Copy link
Owner

justbur commented Apr 21, 2017 via email

@Compro-Prasad
Copy link

Compro-Prasad commented Jan 20, 2018

I am not an elisp guy but I can suggest a thing. Don't know whether it will work or not. Whenever which-key is triggered can the mode line be changed? If that is a yes then backward and forward buttons on the model-ine can be placed to scroll the page instead of using the mouse wheel or trackpad. And another button for undo can also be placed IMO. Can this be done?

@Compro-Prasad
Copy link

Compro-Prasad commented Aug 15, 2018

Any updates on this?

@danielkrajnik
Copy link

danielkrajnik commented Mar 18, 2023

If I understand correctly this hasn't been resolved in the end? It would be really useful though - quite often there are more keybindings than you can fit in the side-window, often C-h is bound to something else, so you can't "unroll" the list. An option to scroll the list with a mouse would be really helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants