diff --git a/CHANGELOG.md b/CHANGELOG.md index a38321e4..6a02f545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Custom tab name ([#3666]) - New `--in` for `search` action to set search directory ([#3696]) - Hover cursor over the new file after copying/cutting/linking/hardlinking/extracting ([#3846], [#3854]) +- Drag-resize panes with mouse ([#3890]) - Multi-file spotter ([#3733]) - New `app:theme` action that hot-reload user themes/flavors ([#3906]) - Dynamic open/opener Lua API ([#3901]) @@ -1703,6 +1704,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): [#3846]: https://github.com/sxyazi/yazi/pull/3846 [#3854]: https://github.com/sxyazi/yazi/pull/3854 [#3862]: https://github.com/sxyazi/yazi/pull/3862 +[#3890]: https://github.com/sxyazi/yazi/pull/3890 [#3891]: https://github.com/sxyazi/yazi/pull/3891 [#3894]: https://github.com/sxyazi/yazi/pull/3894 [#3901]: https://github.com/sxyazi/yazi/pull/3901 diff --git a/yazi-actor/src/app/mouse.rs b/yazi-actor/src/app/mouse.rs index c7717806..cc49e45d 100644 --- a/yazi-actor/src/app/mouse.rs +++ b/yazi-actor/src/app/mouse.rs @@ -4,7 +4,6 @@ use mlua::{ObjectLike, Table}; use tracing::error; use yazi_actor::lives::Lives; use yazi_binding::runtime_scope; -use yazi_config::YAZI; use yazi_macro::succ; use yazi_parser::app::MouseForm; use yazi_plugin::LUA; @@ -30,10 +29,6 @@ impl Actor for Mouse { LUA.globals().raw_get::("Root")?.call_method::
("new", area) })?; - if matches!(event.kind, MouseEventKind::Down(_) if YAZI.mgr.mouse_events.get().draggable()) { - root.raw_set("_drag_start", event)?; - } - match event.kind { MouseEventKind::Down(_) => root.call_method("click", (event, false))?, MouseEventKind::Up(_) => root.call_method("click", (event, true))?, diff --git a/yazi-binding/src/elements/pad.rs b/yazi-binding/src/elements/pad.rs index 97c7ecba..c7eb25b4 100644 --- a/yazi-binding/src/elements/pad.rs +++ b/yazi-binding/src/elements/pad.rs @@ -1,6 +1,6 @@ use std::ops::{Add, AddAssign, Deref}; -use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value}; +use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, Value}; #[derive(Clone, Copy, Default, FromLua)] pub struct Pad(ratatui::widgets::Padding); @@ -52,7 +52,7 @@ impl Pad { } impl UserData for Pad { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { fields.add_field_method_get("left", |_, me| Ok(me.left)); fields.add_field_method_get("right", |_, me| Ok(me.right)); fields.add_field_method_get("top", |_, me| Ok(me.top)); diff --git a/yazi-binding/src/elements/pos.rs b/yazi-binding/src/elements/pos.rs index 4e701c4c..d509d945 100644 --- a/yazi-binding/src/elements/pos.rs +++ b/yazi-binding/src/elements/pos.rs @@ -1,6 +1,6 @@ use std::{ops::Deref, str::FromStr}; -use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value}; use yazi_shim::strum::IntoStr; use super::Pad; @@ -81,7 +81,7 @@ impl Pos { } impl UserData for Pos { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { // TODO: cache fields.add_field_method_get("1", |_, me| Ok(me.origin.into_str())); fields.add_field_method_get("x", |_, me| Ok(me.offset.x)); diff --git a/yazi-binding/src/elements/rect.rs b/yazi-binding/src/elements/rect.rs index 0a280c8d..6c21d678 100644 --- a/yazi-binding/src/elements/rect.rs +++ b/yazi-binding/src/elements/rect.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value}; use super::Pad; @@ -48,10 +48,19 @@ impl Rect { r.height = r.height.saturating_sub(pad.top + pad.bottom); Self(r) } + + fn patch(self, t: Table) -> mlua::Result { + Ok(Self(ratatui::layout::Rect { + x: t.raw_get::>("x")?.unwrap_or(self.x), + y: t.raw_get::>("y")?.unwrap_or(self.y), + width: t.raw_get::>("w")?.unwrap_or(self.width), + height: t.raw_get::>("h")?.unwrap_or(self.height), + })) + } } impl UserData for Rect { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { fields.add_field_method_get("x", |_, me| Ok(me.x)); fields.add_field_method_get("y", |_, me| Ok(me.y)); fields.add_field_method_get("w", |_, me| Ok(me.width)); @@ -71,5 +80,7 @@ impl UserData for Rect { fn add_methods>(methods: &mut M) { methods.add_method("pad", |_, me, pad: Pad| Ok(me.pad(pad))); methods.add_method("contains", |_, me, Self(rect)| Ok(me.contains(rect.into()))); + + methods.add_meta_method(MetaMethod::Call, |_, me, t: Table| me.patch(t)); } } diff --git a/yazi-binding/src/id.rs b/yazi-binding/src/id.rs index 1b38b478..ca608ef8 100644 --- a/yazi-binding/src/id.rs +++ b/yazi-binding/src/id.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, Value}; +use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, UserDataFields, Value}; #[derive(Clone, Copy, Default)] pub struct Id(pub yazi_shared::Id); @@ -22,7 +22,7 @@ impl FromLua for Id { } impl UserData for Id { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { fields.add_field_method_get("value", |_, me| Ok(me.0.get())); } } diff --git a/yazi-binding/src/image.rs b/yazi-binding/src/image.rs index ff21c70b..4a5bdfa9 100644 --- a/yazi-binding/src/image.rs +++ b/yazi-binding/src/image.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use mlua::{MetaMethod, UserData, UserDataMethods}; +use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods}; pub struct ImageInfo(yazi_adapter::ImageInfo); @@ -15,7 +15,7 @@ impl From for ImageInfo { } impl UserData for ImageInfo { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { fields.add_field_method_get("w", |_, me| Ok(me.width)); fields.add_field_method_get("h", |_, me| Ok(me.height)); fields.add_field_method_get("ori", |_, me| Ok(me.orientation.map(|o| o.to_exif()))); diff --git a/yazi-binding/src/process/output.rs b/yazi-binding/src/process/output.rs index f0892486..97508849 100644 --- a/yazi-binding/src/process/output.rs +++ b/yazi-binding/src/process/output.rs @@ -1,6 +1,6 @@ use std::mem; -use mlua::{UserData, Value}; +use mlua::{UserData, UserDataFields, Value}; use super::Status; use crate::{cached_field, cached_field_mut}; @@ -20,7 +20,7 @@ impl Output { } impl UserData for Output { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { cached_field!(fields, status, |_, me| Ok(Status::new(me.inner.status))); cached_field_mut!(fields, stdout, |lua, me| { lua.create_external_string(mem::take(&mut me.inner.stdout)) diff --git a/yazi-binding/src/process/status.rs b/yazi-binding/src/process/status.rs index a81025e0..7a47024f 100644 --- a/yazi-binding/src/process/status.rs +++ b/yazi-binding/src/process/status.rs @@ -1,4 +1,4 @@ -use mlua::UserData; +use mlua::{UserData, UserDataFields}; pub struct Status { inner: std::process::ExitStatus, @@ -9,7 +9,7 @@ impl Status { } impl UserData for Status { - fn add_fields>(fields: &mut F) { + fn add_fields>(fields: &mut F) { fields.add_field_method_get("success", |_, me| Ok(me.inner.success())); fields.add_field_method_get("code", |_, me| Ok(me.inner.code())); } diff --git a/yazi-config/preset/yazi-default.toml b/yazi-config/preset/yazi-default.toml index 8b486c16..f6566e5c 100644 --- a/yazi-config/preset/yazi-default.toml +++ b/yazi-config/preset/yazi-default.toml @@ -14,7 +14,7 @@ linemode = "none" show_hidden = false show_symlink = true scrolloff = 5 -mouse_events = [ "click", "scroll" ] +mouse_events = [ "click", "scroll", "drag" ] [preview] wrap = "no" diff --git a/yazi-config/src/mgr/mouse.rs b/yazi-config/src/mgr/mouse.rs index b1d68b7f..218d4967 100644 --- a/yazi-config/src/mgr/mouse.rs +++ b/yazi-config/src/mgr/mouse.rs @@ -15,10 +15,6 @@ bitflags! { } } -impl MouseEvents { - pub const fn draggable(self) -> bool { self.contains(Self::DRAG) } -} - impl TryFrom> for MouseEvents { type Error = anyhow::Error; diff --git a/yazi-plugin/preset/components/current.lua b/yazi-plugin/preset/components/current.lua index d8364d90..74f73fe4 100644 --- a/yazi-plugin/preset/components/current.lua +++ b/yazi-plugin/preset/components/current.lua @@ -49,6 +49,10 @@ end -- Mouse events function Current:click(event, up) + if up or event.is_middle then + return + end + local y = event.y - self._area.y + 1 if self._folder.window[y] then Entity:new(self._folder.window[y]):click(event, up) diff --git a/yazi-plugin/preset/components/marker.lua b/yazi-plugin/preset/components/marker.lua index 19ccd8d7..74e3fba0 100644 --- a/yazi-plugin/preset/components/marker.lua +++ b/yazi-plugin/preset/components/marker.lua @@ -24,7 +24,7 @@ function Marker:redraw() local y = math.min(self._area.y + last[1], self._area.y + self._area.h) - 1 local rect = ui.Rect { - x = math.max(0, self._area.x - 1), + x = self._area.x, y = y, w = 1, h = math.min(1 + last[2] - last[1], self._area.y + self._area.h - y), diff --git a/yazi-plugin/preset/components/markers.lua b/yazi-plugin/preset/components/markers.lua new file mode 100644 index 00000000..6c4bdad1 --- /dev/null +++ b/yazi-plugin/preset/components/markers.lua @@ -0,0 +1,33 @@ +Markers = { + _id = "markers", +} + +function Markers:new(chunks, tab) + local me = setmetatable({ _chunks = chunks, _tab = tab }, { __index = self }) + me:build() + return me +end + +function Markers:build() + self._children = { + Marker:new(self._chunks[1], self._tab.parent), + Marker:new(self._chunks[2], self._tab.current), + } +end + +function Markers:reflow() return {} end + +function Markers:redraw() + local elements = {} + for _, child in ipairs(self._children) do + elements = ya.list_merge(elements, ui.redraw(child)) + end + return elements +end + +-- Mouse events +function Markers:click(event, up) end + +function Markers:scroll(event, step) end + +function Markers:touch(event, step) end diff --git a/yazi-plugin/preset/components/parent.lua b/yazi-plugin/preset/components/parent.lua index 3b0e0a0d..d96524d3 100644 --- a/yazi-plugin/preset/components/parent.lua +++ b/yazi-plugin/preset/components/parent.lua @@ -34,6 +34,10 @@ end -- Mouse events function Parent:click(event, up) + if up or event.is_middle then + return + end + local y = event.y - self._area.y + 1 local window = self._folder and self._folder.window or {} if window[y] then diff --git a/yazi-plugin/preset/components/preview.lua b/yazi-plugin/preset/components/preview.lua index 25caeb62..bbff77b8 100644 --- a/yazi-plugin/preset/components/preview.lua +++ b/yazi-plugin/preset/components/preview.lua @@ -16,6 +16,10 @@ function Preview:redraw() return {} end -- Mouse events function Preview:click(event, up) + if up or event.is_middle then + return + end + local y = event.y - self._area.y + 1 local window = self._folder and self._folder.window or {} if window[y] then diff --git a/yazi-plugin/preset/components/rail.lua b/yazi-plugin/preset/components/rail.lua index d932de45..40d938d8 100644 --- a/yazi-plugin/preset/components/rail.lua +++ b/yazi-plugin/preset/components/rail.lua @@ -1,32 +1,19 @@ -Rail = { - _id = "rail", -} +Rail = {} -function Rail:new(chunks, tab) - local me = setmetatable({ _chunks = chunks, _tab = tab }, { __index = self }) - me:build() - return me +function Rail:new(id, area, chunks) + return setmetatable({ + _id = id, + _area = area, + _chunks = chunks, + }, { __index = self }) end -function Rail:build() - self._base = { - ui.Bar(ui.Edge.RIGHT):area(self._chunks[1]):symbol(th.mgr.border_symbol):style(th.mgr.border_style), - ui.Bar(ui.Edge.LEFT):area(self._chunks[3]):symbol(th.mgr.border_symbol):style(th.mgr.border_style), - } - self._children = { - Marker:new(self._chunks[1], self._tab.parent), - Marker:new(self._chunks[2], self._tab.current), - } -end - -function Rail:reflow() return {} end +function Rail:reflow() return { self } end function Rail:redraw() - local elements = self._base or {} - for _, child in ipairs(self._children) do - elements = ya.list_merge(elements, ui.redraw(child)) - end - return elements + return { + ui.Bar(ui.Edge.LEFT):area(self._area):symbol(th.mgr.border_symbol):style(th.mgr.border_style), + } end -- Mouse events @@ -35,3 +22,24 @@ function Rail:click(event, up) end function Rail:scroll(event, step) end function Rail:touch(event, step) end + +function Rail:drag(event) + local c, x, parent, current, preview = self._chunks, 0, 0, 0, 0 + if self._id == "rail-left" then + x = math.min(event.x, c[2].right - 2) + parent = math.max(1, x - c[1].x) + current = math.max(1, c[1].w + c[2].w - parent) + preview = math.max(1, c[3].w) + else + x = math.max(event.x, c[2].x + 2) + preview = math.max(1, c[3].right - x) + current = math.max(1, c[2].w + c[3].w - preview) + parent = math.max(1, c[1].w) + end + + local r = rt.mgr.ratio + if r.parent ~= parent or r.current ~= current or r.preview ~= preview then + rt.mgr.ratio = { parent, current, preview } + ui.render() + end +end diff --git a/yazi-plugin/preset/components/rails.lua b/yazi-plugin/preset/components/rails.lua new file mode 100644 index 00000000..5487cb1b --- /dev/null +++ b/yazi-plugin/preset/components/rails.lua @@ -0,0 +1,44 @@ +Rails = { + _id = "rails", +} + +function Rails:new(chunks, tab) + local me = setmetatable({ _chunks = chunks, _tab = tab }, { __index = self }) + me:build() + return me +end + +function Rails:build() + local c, children = self._chunks, {} + if c[1].w > 0 then + children[#children + 1] = Rail:new("rail-left", c[2] { w = math.min(1, c[2].w) }, c) + end + if c[3].w > 0 then + children[#children + 1] = + Rail:new("rail-right", c[2] { x = math.max(0, c[2].right - 1), w = math.min(1, c[2].w) }, c) + end + self._children = children +end + +function Rails:reflow() + local components = {} + for _, child in ipairs(self._children) do + components = ya.list_merge(components, child:reflow()) + end + return components +end + +function Rails:redraw() + local elements = {} + for _, child in ipairs(self._children) do + elements = ya.list_merge(elements, ui.redraw(child)) + end + return elements +end + +-- Mouse events +function Rails:click(event, up) end + +function Rails:scroll(event, step) end + +function Rails:touch(event, step) end diff --git a/yazi-plugin/preset/components/root.lua b/yazi-plugin/preset/components/root.lua index 67824985..201d37fa 100644 --- a/yazi-plugin/preset/components/root.lua +++ b/yazi-plugin/preset/components/root.lua @@ -1,6 +1,6 @@ Root = { _id = "root", - _drag_start = ui.Rect {}, + _dragging = nil, } function Root:new(area) @@ -50,11 +50,12 @@ end -- Mouse events function Root:click(event, up) - if tostring(cx.layer) ~= "mgr" then - return + local c = Root._dragging or ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow()) + Root._dragging = not up and c or nil + + if tostring(cx.layer) == "mgr" then + return c and c:click(event, up) end - local c = ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow()) - return c and c:click(event, up) end function Root:scroll(event, step) @@ -75,4 +76,11 @@ end function Root:move(event) end -function Root:drag(event) end +function Root:drag(event) + if tostring(cx.layer) ~= "mgr" then + return + end + + local c = Root._dragging + return c and c.drag and c:drag(event) +end diff --git a/yazi-plugin/preset/components/tab.lua b/yazi-plugin/preset/components/tab.lua index 58d06747..357abaab 100644 --- a/yazi-plugin/preset/components/tab.lua +++ b/yazi-plugin/preset/components/tab.lua @@ -23,11 +23,13 @@ end function Tab:build() local c = self._chunks + local p = c[2].w > 0 and 0 or 1 self._children = { - Parent:new(c[1]:pad(ui.Pad.x(1)), self._tab), - Current:new(c[2]:pad(ui.Pad(0, c[3].w > 0 and 0 or 1, 0, c[1].w > 0 and 0 or 1)), self._tab), - Preview:new(c[3]:pad(ui.Pad.x(1)), self._tab), - Rail:new(c, self._tab), + Parent:new(c[1]:pad(ui.Pad(0, p, 0, 1)), self._tab), + Current:new(c[2]:pad(ui.Pad.x(1)), self._tab), + Preview:new(c[3]:pad(ui.Pad(0, 1, 0, p)), self._tab), + Rails:new(c, self._tab), + Markers:new(c, self._tab), } end diff --git a/yazi-plugin/preset/components/tasks.lua b/yazi-plugin/preset/components/tasks.lua index f13b9129..8b8ddefc 100644 --- a/yazi-plugin/preset/components/tasks.lua +++ b/yazi-plugin/preset/components/tasks.lua @@ -29,12 +29,7 @@ function Tasks:redraw() break end - elements[#elements + 1] = ui.Line({ self:icon(snap), snap.title }):area(ui.Rect { - x = self._area.x, - y = y, - w = self._area.w, - h = 1, - }) + elements[#elements + 1] = ui.Line({ self:icon(snap), snap.title }):area(self._area { y = y, h = 1 }) if i == cx.tasks.cursor + 1 then elements[#elements] = elements[#elements]:style(th.tasks.hovered) @@ -107,14 +102,14 @@ function Tasks:progress_redraw(snap, y) return { ui.Gauge() - :area(ui.Rect { x = self._chunks[1].x, y = y, w = self._chunks[1].w, h = 1 }) + :area(self._chunks[1] { y = y, h = 1 }) :percent(snap.percent) :label(ui.Span(label):style(th.status.progress_label)) :gauge_style(style), ui.Line(string.format("%d/%d", snap.prog.success_files, snap.prog.total_files)) :fg("gray") - :area(ui.Rect { x = self._chunks[2].x, y = y, w = self._chunks[2].w, h = 1 }) + :area(self._chunks[2] { y = y, h = 1 }) :align(ui.Align.RIGHT), } else @@ -127,7 +122,7 @@ function Tasks:progress_redraw(snap, y) text = "Failed, press Enter to view log…" end return { - ui.Line(text):fg("gray"):area(ui.Rect { x = self._chunks[1].x, y = y, w = self._chunks[1].w, h = 1 }), + ui.Line(text):fg("gray"):area(self._chunks[1] { y = y, h = 1 }), } end end diff --git a/yazi-plugin/preset/plugins/folder.lua b/yazi-plugin/preset/plugins/folder.lua index 43d75ab2..cbf65d18 100644 --- a/yazi-plugin/preset/plugins/folder.lua +++ b/yazi-plugin/preset/plugins/folder.lua @@ -30,10 +30,11 @@ function M:peek(job) left[#left]:truncate { max = max, ellipsis = entity:ellipsis(max) } end + local marker_area = job.area { x = math.max(0, job.area.x - 1) } ya.preview_widget(job, { ui.List(left):area(job.area), ui.Text(right):area(job.area):align(ui.Align.RIGHT), - table.unpack(Marker:new(job.area, folder):redraw()), + table.unpack(Marker:new(marker_area, folder):redraw()), }) end diff --git a/yazi-plugin/src/standard.rs b/yazi-plugin/src/standard.rs index dac2cc76..d2a9a0c4 100644 --- a/yazi-plugin/src/standard.rs +++ b/yazi-plugin/src/standard.rs @@ -47,11 +47,13 @@ fn stage_1(lua: &Lua) -> Result<()> { lua.load(preset!("components/linemode")).set_name("linemode.lua").exec()?; lua.load(preset!("components/marker")).set_name("marker.lua").exec()?; + lua.load(preset!("components/markers")).set_name("markers.lua").exec()?; lua.load(preset!("components/modal")).set_name("modal.lua").exec()?; lua.load(preset!("components/parent")).set_name("parent.lua").exec()?; lua.load(preset!("components/preview")).set_name("preview.lua").exec()?; lua.load(preset!("components/progress")).set_name("progress.lua").exec()?; lua.load(preset!("components/rail")).set_name("rail.lua").exec()?; + lua.load(preset!("components/rails")).set_name("rails.lua").exec()?; lua.load(preset!("components/root")).set_name("root.lua").exec()?; lua.load(preset!("components/status")).set_name("status.lua").exec()?; lua.load(preset!("components/tab")).set_name("tab.lua").exec()?; diff --git a/yazi-runner/src/loader/loader.rs b/yazi-runner/src/loader/loader.rs index e1726530..c8c38d6c 100644 --- a/yazi-runner/src/loader/loader.rs +++ b/yazi-runner/src/loader/loader.rs @@ -60,11 +60,13 @@ impl Default for Loader { ("header".to_owned(), [][..].into()), ("linemode".to_owned(), [][..].into()), ("marker".to_owned(), [][..].into()), + ("markers".to_owned(), [][..].into()), ("modal".to_owned(), [][..].into()), ("parent".to_owned(), [][..].into()), ("preview".to_owned(), [][..].into()), ("progress".to_owned(), [][..].into()), ("rail".to_owned(), [][..].into()), + ("rails".to_owned(), [][..].into()), ("root".to_owned(), [][..].into()), ("status".to_owned(), [][..].into()), ("tab".to_owned(), [][..].into()), diff --git a/yazi-widgets/src/clear.rs b/yazi-widgets/src/clear.rs index 805706ca..2b615fe5 100644 --- a/yazi-widgets/src/clear.rs +++ b/yazi-widgets/src/clear.rs @@ -30,7 +30,7 @@ impl Widget for Clear { } const fn is_overlapping(a: Rect, b: Rect) -> bool { - a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y + a.x < b.right() && a.right() > b.x && a.y < b.y + b.height && a.y + a.height > b.y } fn overlap(a: Rect, b: Rect) -> Option { @@ -40,7 +40,7 @@ fn overlap(a: Rect, b: Rect) -> Option { let x = a.x.max(b.x); let y = a.y.max(b.y); - let width = (a.x + a.width).min(b.x + b.width) - x; + let width = a.right().min(b.right()) - x; let height = (a.y + a.height).min(b.y + b.height) - y; Some(Rect { x, y, width, height }) }