Skip to content

Commit 85c7963

Browse files
committed
feat: redesign lua API of mouse support
1 parent 4974eb3 commit 85c7963

File tree

15 files changed

+216
-92
lines changed

15 files changed

+216
-92
lines changed

yazi-config/src/layout.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use ratatui::layout::Rect;
44
pub struct Layout {
55
pub header: Rect,
66

7+
pub manager: Rect,
8+
79
pub parent: Rect,
810
pub current: Rect,
911
pub preview: Rect,

yazi-fm/src/app/app.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use std::{collections::VecDeque, sync::atomic::Ordering};
22

33
use anyhow::Result;
4+
use components::{Header, Manager, Status};
45
use crossterm::event::{KeyEvent, MouseEvent};
5-
use yazi_config::{keymap::Key, LAYOUT};
66
use ratatui::layout::Position;
7+
use yazi_config::{keymap::Key, LAYOUT};
78
use yazi_core::input::InputMode;
89
use yazi_shared::{emit, event::{Cmd, Event, NEED_RENDER}, term::Term, Layer};
9-
use components::{ManagerComponent, Manager, Header, Status};
1010

1111
use crate::{components, lives::Lives, Ctx, Executor, Router, Signals};
1212

@@ -87,19 +87,13 @@ impl App {
8787

8888
#[inline]
8989
fn dispatch_mouse(&self, mouse: MouseEvent) {
90-
let mouse_position = Position {
91-
x: mouse.column,
92-
y: mouse.row,
93-
};
90+
let mouse_position = Position { x: mouse.column, y: mouse.row };
9491
let layout = LAYOUT.load();
92+
9593
if layout.header.contains(mouse_position) {
9694
Header.mouse(mouse, layout.header, &self.cx)
97-
} else if layout.parent.contains(mouse_position) {
98-
Manager.mouse(mouse, layout.parent, ManagerComponent::Parent, &self.cx)
99-
} else if layout.current.contains(mouse_position) {
100-
Manager.mouse(mouse, layout.current, ManagerComponent::Current, &self.cx)
101-
} else if layout.preview.contains(mouse_position) {
102-
Manager.mouse(mouse, layout.preview, ManagerComponent::Preview, &self.cx)
95+
} else if layout.manager.contains(mouse_position) {
96+
Manager.mouse(mouse, layout.as_ref(), &self.cx);
10397
} else if layout.status.contains(mouse_position) {
10498
Status.mouse(mouse, layout.status, &self.cx)
10599
} else {

yazi-fm/src/components/header.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crossterm::event::MouseEventKind;
12
use mlua::{Table, TableExt};
23
use ratatui::{buffer::Buffer, widgets::Widget};
34
use tracing::error;
@@ -22,18 +23,32 @@ impl Widget for Header {
2223
}
2324

2425
impl Header {
25-
pub fn mouse(self, mouse: crossterm::event::MouseEvent, area: ratatui::layout::Rect, cx: &crate::context::Ctx) {
26+
pub fn mouse(
27+
self,
28+
event: crossterm::event::MouseEvent,
29+
area: ratatui::layout::Rect,
30+
cx: &crate::context::Ctx,
31+
) {
2632
let f = || {
27-
let mouse = crossterm::event::MouseEvent {
28-
kind: mouse.kind,
29-
column: mouse.column - area.x,
30-
row: mouse.row - area.y,
31-
modifiers: mouse.modifiers,
33+
let event = crossterm::event::MouseEvent {
34+
kind: event.kind,
35+
column: event.column - area.x,
36+
row: event.row - area.y,
37+
modifiers: event.modifiers,
3238
};
33-
let mouse = MouseEvent::cast(&LUA, mouse)?;
39+
let kind = event.kind;
40+
let event = MouseEvent::cast(&LUA, event)?;
3441
let comp: Table = LUA.globals().raw_get("Header")?;
3542
_ = Lives::scope(cx, |_| {
36-
comp.call_method("mouse", mouse)?;
43+
match kind {
44+
MouseEventKind::Down(_) => comp.call_method("click", (event, false))?,
45+
MouseEventKind::Up(_) => comp.call_method("click", (event, true))?,
46+
MouseEventKind::ScrollDown => comp.call_method("scroll", (event, 1))?,
47+
MouseEventKind::ScrollUp => comp.call_method("scroll", (event, -1))?,
48+
MouseEventKind::ScrollRight => comp.call_method("touch", (event, 1))?,
49+
MouseEventKind::ScrollLeft => comp.call_method("touch", (event, -1))?,
50+
_ => (),
51+
}
3752
Ok(())
3853
});
3954
Ok::<_, anyhow::Error>(())

yazi-fm/src/components/manager.rs

Lines changed: 79 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
use mlua::{Table, TableExt};
2-
use ratatui::{buffer::Buffer, widgets::Widget};
1+
use crossterm::event::MouseEventKind;
2+
use mlua::{IntoLua, Table, TableExt, Value};
3+
use ratatui::{buffer::Buffer, layout::Position, widgets::Widget};
34
use tracing::error;
5+
use yazi_config::Layout;
46
use yazi_plugin::{bindings::{Cast, MouseEvent}, elements::{render_widgets, Rect}, LUA};
57

68
use crate::lives::Lives;
79

810
pub(crate) struct Manager;
911

1012
#[derive(PartialEq, Eq)]
11-
pub enum ManagerComponent {
12-
Parent = 0,
13-
Current = 1,
14-
Preview = 2,
13+
enum ManagerComponent {
14+
Parent,
15+
Current,
16+
Preview,
17+
Outside,
1518
}
1619

1720
impl Widget for Manager {
@@ -29,20 +32,79 @@ impl Widget for Manager {
2932
}
3033

3134
impl Manager {
32-
pub fn mouse(self, mouse: crossterm::event::MouseEvent, area: ratatui::layout::Rect, comp: ManagerComponent, cx: &crate::context::Ctx) {
35+
pub fn mouse(
36+
self,
37+
event: crossterm::event::MouseEvent,
38+
layout: &Layout,
39+
cx: &crate::context::Ctx,
40+
) {
41+
let position = Position { x: event.column, y: event.row };
42+
let comp = if layout.preview.contains(position) {
43+
ManagerComponent::Preview
44+
} else if layout.current.contains(position) {
45+
ManagerComponent::Current
46+
} else if layout.parent.contains(position) {
47+
ManagerComponent::Parent
48+
} else {
49+
ManagerComponent::Outside
50+
};
51+
52+
let area = match event.kind {
53+
MouseEventKind::Moved | MouseEventKind::Drag(_) => layout.manager,
54+
_ => match comp {
55+
ManagerComponent::Parent => layout.parent,
56+
ManagerComponent::Current => layout.current,
57+
ManagerComponent::Preview => layout.preview,
58+
ManagerComponent::Outside => return,
59+
},
60+
};
61+
let event = crossterm::event::MouseEvent {
62+
kind: event.kind,
63+
column: event.column - area.x,
64+
row: event.row - area.y,
65+
modifiers: event.modifiers,
66+
};
3367
let f = || {
34-
let mouse = crossterm::event::MouseEvent {
35-
kind: mouse.kind,
36-
column: mouse.column - area.x,
37-
row: mouse.row - area.y,
38-
modifiers: mouse.modifiers,
68+
let kind = event.kind;
69+
let event = MouseEvent::cast(&LUA, event)?;
70+
let comp: Table = match comp {
71+
ManagerComponent::Parent => LUA.globals().raw_get("Parent")?,
72+
ManagerComponent::Current => LUA.globals().raw_get("Current")?,
73+
ManagerComponent::Preview => LUA.globals().raw_get("Preview")?,
74+
ManagerComponent::Outside => return Ok(()),
3975
};
40-
let mouse = MouseEvent::cast(&LUA, mouse)?;
41-
let lua_comp: Table = LUA.globals().raw_get("Manager")?;
42-
_ = Lives::scope(cx, |_| {
43-
lua_comp.call_method("mouse", (mouse, comp as u8))?;
76+
let manager: Table = LUA.globals().raw_get("Manager")?;
77+
Lives::scope(cx, |_| {
78+
match kind {
79+
// invoke `click(event, up)`
80+
MouseEventKind::Down(_) => {
81+
comp.call_method("click", (event.clone(), false))?;
82+
manager.raw_set("drag_start", event)?; // store the event for dragging
83+
}
84+
MouseEventKind::Up(_) => {
85+
comp.call_method("click", (event, true))?;
86+
manager.raw_set("drag_start", Value::Nil)?;
87+
}
88+
// invoke `scroll(event, step)`, 1 for down, -1 for up
89+
MouseEventKind::ScrollDown => comp.call_method("scroll", (event, 1))?,
90+
MouseEventKind::ScrollUp => comp.call_method("scroll", (event, -1))?,
91+
// invoke `touch(event, step)`, 1 for right, -1 for left
92+
MouseEventKind::ScrollRight => comp.call_method("touch", (event, 1))?,
93+
MouseEventKind::ScrollLeft => comp.call_method("touch", (event, -1))?,
94+
// invoke `move(event)`
95+
MouseEventKind::Moved => manager.call_method("move", event)?,
96+
// invoke `drag(event, start)`
97+
MouseEventKind::Drag(_) => {
98+
let mut start: Value = manager.raw_get("drag_start")?;
99+
if start.is_nil() {
100+
start = event.clone().into_lua(&LUA)?;
101+
manager.raw_set("drag_start", start.clone())?;
102+
}
103+
manager.call_method("drag", (event, start))?;
104+
}
105+
}
44106
Ok(())
45-
});
107+
})?;
46108
Ok::<_, anyhow::Error>(())
47109
};
48110
if let Err(e) = f() {

yazi-fm/src/components/status.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crossterm::event::MouseEventKind;
12
use mlua::{Table, TableExt};
23
use ratatui::widgets::Widget;
34
use tracing::error;
@@ -22,18 +23,32 @@ impl Widget for Status {
2223
}
2324

2425
impl Status {
25-
pub fn mouse(self, mouse: crossterm::event::MouseEvent, area: ratatui::layout::Rect, cx: &crate::context::Ctx) {
26+
pub fn mouse(
27+
self,
28+
event: crossterm::event::MouseEvent,
29+
area: ratatui::layout::Rect,
30+
cx: &crate::context::Ctx,
31+
) {
2632
let f = || {
27-
let mouse = crossterm::event::MouseEvent {
28-
kind: mouse.kind,
29-
column: mouse.column - area.x,
30-
row: mouse.row - area.y,
31-
modifiers: mouse.modifiers,
33+
let event = crossterm::event::MouseEvent {
34+
kind: event.kind,
35+
column: event.column - area.x,
36+
row: event.row - area.y,
37+
modifiers: event.modifiers,
3238
};
33-
let mouse = MouseEvent::cast(&LUA, mouse)?;
39+
let kind = event.kind;
40+
let event = MouseEvent::cast(&LUA, event)?;
3441
let comp: Table = LUA.globals().raw_get("Status")?;
3542
_ = Lives::scope(cx, |_| {
36-
comp.call_method("mouse", mouse)?;
43+
match kind {
44+
MouseEventKind::Down(_) => comp.call_method("click", (event, false))?,
45+
MouseEventKind::Up(_) => comp.call_method("click", (event, true))?,
46+
MouseEventKind::ScrollDown => comp.call_method("scroll", (event, 1))?,
47+
MouseEventKind::ScrollUp => comp.call_method("scroll", (event, -1))?,
48+
MouseEventKind::ScrollRight => comp.call_method("touch", (event, 1))?,
49+
MouseEventKind::ScrollLeft => comp.call_method("touch", (event, -1))?,
50+
_ => (),
51+
}
3752
Ok(())
3853
});
3954
Ok::<_, anyhow::Error>(())

yazi-fm/src/lives/lives.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ impl Lives {
5555

5656
LAYOUT.store(Arc::new(yazi_config::Layout {
5757
header: *globals.raw_get::<_, Table>("Header")?.raw_get::<_, RectRef>("area")?,
58+
manager: *globals.raw_get::<_, Table>("Manager")?.raw_get::<_, RectRef>("area")?,
5859
parent: *globals.raw_get::<_, Table>("Parent")?.raw_get::<_, RectRef>("area")?,
5960
current: *globals.raw_get::<_, Table>("Current")?.raw_get::<_, RectRef>("area")?,
6061
preview: *globals.raw_get::<_, Table>("Preview")?.raw_get::<_, RectRef>("area")?,

yazi-fm/src/signals.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crossterm::event::{Event as CrosstermEvent, EventStream, KeyEvent, KeyEventK
33
use futures::StreamExt;
44
use tokio::{select, task::JoinHandle};
55
use tokio_util::sync::CancellationToken;
6-
use yazi_shared::event::Event;
76
use yazi_config::MANAGER;
7+
use yazi_shared::event::Event;
88

99
pub(super) struct Signals {
1010
ct: CancellationToken,

yazi-plugin/preset/components/current.lua

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,26 @@ function Current:render(area)
4343
}
4444
end
4545

46-
function Current:mouse(mouse)
47-
if mouse.kind == 0 and mouse.button == 0 then
46+
function Current:click(event, up)
47+
if not up and event.is_left then
4848
-- left click
4949
local files = Folder:by_kind(Folder.CURRENT).window
50-
if mouse.y + 1 <= #files then
51-
local f = files[mouse.y + 1]
50+
if event.row + 1 <= #files then
51+
local f = files[event.row + 1]
5252
ya.manager_emit("reveal", { f.url })
5353
end
54-
elseif mouse.kind == 4 then
54+
end
55+
end
56+
57+
function Current:scroll(event, step)
58+
if step == 1 then
5559
-- Scroll down
5660
ya.manager_emit("arrow", { 1 })
57-
elseif mouse.kind == 5 then
61+
elseif step == -1 then
5862
-- Scroll up
5963
ya.manager_emit("arrow", { -1 })
6064
end
6165
end
66+
67+
function Current:touch(event, step)
68+
end

yazi-plugin/preset/components/header.lua

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,5 +87,11 @@ function Header:render(area)
8787
}
8888
end
8989

90-
function Header:mouse(mouse)
90+
function Header:click(event, up)
91+
end
92+
93+
function Header:scroll(event, step)
94+
end
95+
96+
function Header:touch(event, step)
9197
end

yazi-plugin/preset/components/manager.lua

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,8 @@ function Manager:render(area)
3232
}
3333
end
3434

35-
function Manager:mouse(mouse, comp)
36-
if comp == 0 then
37-
Parent:mouse(mouse)
38-
elseif comp == 1 then
39-
Current:mouse(mouse)
40-
elseif comp == 2 then
41-
Preview:mouse(mouse)
42-
end
35+
function Manager:move(event)
36+
end
37+
38+
function Manager:drag(event, start)
4339
end

0 commit comments

Comments
 (0)