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

feat: support mouse event #1038

Merged
merged 1 commit into from
Jun 3, 2024
Merged

feat: support mouse event #1038

merged 1 commit into from
Jun 3, 2024

Conversation

qsdrqs
Copy link
Contributor

@qsdrqs qsdrqs commented May 15, 2024

screenshot-000232.mp4

Hi. Thanks for this amazing project! This is an attempt to add mouse support to yazi. I make it as a draft PR because I think it still needs tasks to be done before it can be merged. But I would appreciate it if I could get some early feedback from reviewing and help me to know what is the next step.

This PR tries to enable capturing MouseEvent in the terminal and spawn it to the App struct, then App will try to dispatch this event and route this event to the mouse method in different components (Header, Manager, and Status), based on coordination comparison between mouse event and Rect from Layout. The Manager is a special case. Because in LAYOUT, Manager is divided into Current, Parent and Preview. So I create a new enum ManagerComponent to indicate which specific component in Manager this MouseEvent belongs to and pass it as an argument. The mouse method will finally encapsulate the MouseEvent as lua object and invoke the corresponding mouse method in lua field.

In the lua field, I create a new type named MouseEvent, which contains the following attributes:

Field Description
x Column offset relative to the triggered component
y Row offset relative to the triggered component
kind Kind of mouse event
button Triggered button of mouse event, will be nil for events that are not Down, Up, and Drag
modifiers Key Modifiers of mouse event, passed as u8 value

The different kind and button are indicated as different numbers, specifically:

For kind:

Kind Value
Down 0
Up 1
Drag 2
Moved 3
ScrollDown 4
ScrollUp 5
ScrollLeft 6
ScrollRight 7

For button

Button Value
Left 0
Right 1
Middle 2

button will be nil for events other than Down, Up, and Drag.


Currently, only "left click to jump" is fully supported by lua script, which is implemented by ya.manager_emit("reveal", { f.url }). For scrolling, only Current window supports item-based scrolling. Scrolling in Preview will invoke the seek in the preview window.

Here are some potential things that people may like to see:

  • Support page-based scrolling like ranger
  • Support scrolling in Preview and Parent window

AFAIK, both of them need a new API for ya.manager_emit to invoke. If you think that's a good idea, I will try to implement these. Before that, it would be great if you could review the current implementation and provide some feedback.

@sxyazi
Copy link
Owner

sxyazi commented May 15, 2024

Thank you for the awesome work!

Mouse support is a feature I've been wanting to add for a while, and I'm very happy to see it implemented now! It definitely deserves a separate version to be released ;)

@sxyazi
Copy link
Owner

sxyazi commented May 15, 2024

Here are some change requests:

  • Dispatch Down(MouseButton) and Up(MouseButton) to the click method of each component, e.g.:

    function Current:click(event, up)
      -- event = MouseEvent { column = 10, row = 20, modifiers = 0 }
      -- up = true/false
    end
  • Dispatch ScrollDown, and ScrollUp to the scroll method of each component, e.g.:

    function Current:scroll(event, step)
      -- event = MouseEvent { column = 10, row = 20, modifiers = 0 }
      -- step = 1 (Down), step = -1 (Up)
    end
  • Dispatch ScrollLeft, and ScrollRight to the touch method of each component, e.g.:

    function Current:touch(event, step)
      -- event = MouseEvent { column = 10, row = 20, modifiers = 0 }
      -- step = 1 (Right), step = -1 (Left)
    end
  • Dispatch Moved to the move method of the Manager component:

    function Manager:move(event)
      -- event = MouseEvent { column = 10, row = 20, modifiers = 0 }
    end
  • Dispatch Drag(MouseButton) to the drag method of the Manager component:

    function Manager:drag(event, start)
      -- event = MouseEvent { column = 10, row = 20, modifiers = 0 }
      -- start = MouseEvent { column = 10, row = 20, modifiers = 0 }, we need to save the position of the last `Down(MouseButton)` here
    end

And the MouseEvent userdata contains 3 additional fields:

  • is_left (Boolean)
  • is_right (Boolean)
  • is_middle (Boolean)

When the event type is Moved, ScrollDown, ScrollUp, ScrollLeft, or ScrollRight, the values of these 3 fields are all false since these types do not support mouse buttons.

@qsdrqs
Copy link
Contributor Author

qsdrqs commented May 16, 2024

* Dispatch `ScrollDown`, `ScrollUp`, `ScrollLeft`, `ScrollRight` to the `scroll` method of _each_ component, e.g.:
  ```lua
  function Current:scroll(event, step)
    -- event = MouseEvent { column = 10, row = 20, modifiers = 0 }
    -- step = 1 (Down), step = -1 (Up)
  end
  ```

How to deal with ScrollLeft, ScrollRight in this scoll function?

@sxyazi
Copy link
Owner

sxyazi commented May 16, 2024

I've updated the comment

@qsdrqs
Copy link
Contributor Author

qsdrqs commented May 17, 2024

I've finished the requested change, could you have a look at it?

cx: &crate::context::Ctx,
) {
let position = Position { x: event.column, y: event.row };
let comp = if layout.preview.contains(position) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Manager component should only include the logic for Moved and Drag(MouseButton), all others should be dispatched to specific components (Parent, Current, Preview). There are no parent.rs and current.rs currently, please create them.

yazi-config/src/layout.rs Outdated Show resolved Hide resolved
@qsdrqs
Copy link
Contributor Author

qsdrqs commented Jun 1, 2024

Finished the review requests as described (if I understand correctly).

@sxyazi
Copy link
Owner

sxyazi commented Jun 2, 2024

Thanks for the change! I will review it in the next 1 or 2 days

@sxyazi sxyazi changed the title feat: Attempt to add basic mouse support feat: support mouse event Jun 3, 2024
Copy link
Owner

@sxyazi sxyazi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good now, let me merge it then.

Thank you so much for contributing this awesome feature!

@aspauldingcode
Copy link

aspauldingcode commented Jun 12, 2024

Does click and drag work for selecting items? Like spacebar selection

@qsdrqs
Copy link
Contributor Author

qsdrqs commented Jun 13, 2024

Does click and drag work for selecting items? Like spacebar selection

I didn't implement these in this PR. This PR only has built-in support for scroll and click. However I think it should be easy to implement through the current Lua API.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants