Merge pull request #893 from jasonrhansen/box-select-fixes
Simplify and fix drag selection and auto scroll
This commit is contained in:
commit
fa4da5ce8a
4 changed files with 65 additions and 109 deletions
|
|
@ -15,7 +15,6 @@ use cosmic::iced::{
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use cosmic::iced_winit::commands::overlap_notify::overlap_notify;
|
use cosmic::iced_winit::commands::overlap_notify::overlap_notify;
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
action,
|
|
||||||
app::{self, context_drawer, Core, Task},
|
app::{self, context_drawer, Core, Task},
|
||||||
cosmic_config, cosmic_theme, executor,
|
cosmic_config, cosmic_theme, executor,
|
||||||
iced::{
|
iced::{
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
app::{self, context_drawer, cosmic::Cosmic, Core, Task},
|
app::{context_drawer, cosmic::Cosmic, Core, Task},
|
||||||
cosmic_config, cosmic_theme, executor,
|
cosmic_config, cosmic_theme, executor,
|
||||||
iced::{
|
iced::{
|
||||||
event,
|
self, event,
|
||||||
futures::{self, SinkExt},
|
futures::{self, SinkExt},
|
||||||
keyboard::{Event as KeyEvent, Key, Modifiers},
|
keyboard::{Event as KeyEvent, Key, Modifiers},
|
||||||
stream, window, Alignment, Event, Length, Size, Subscription,
|
mouse, stream, window, Alignment, Event, Length, Point, Size, Subscription,
|
||||||
},
|
},
|
||||||
theme,
|
theme,
|
||||||
widget::{
|
widget::{
|
||||||
|
|
@ -375,6 +375,7 @@ enum Message {
|
||||||
Cancel,
|
Cancel,
|
||||||
Choice(usize, usize),
|
Choice(usize, usize),
|
||||||
Config(Config),
|
Config(Config),
|
||||||
|
CursorMoved(Point),
|
||||||
DialogCancel,
|
DialogCancel,
|
||||||
DialogComplete,
|
DialogComplete,
|
||||||
DialogUpdate(DialogPage),
|
DialogUpdate(DialogPage),
|
||||||
|
|
@ -389,6 +390,7 @@ enum Message {
|
||||||
Open,
|
Open,
|
||||||
Preview,
|
Preview,
|
||||||
Save(bool),
|
Save(bool),
|
||||||
|
ScrollTab(i16),
|
||||||
SearchActivate,
|
SearchActivate,
|
||||||
SearchClear,
|
SearchClear,
|
||||||
SearchInput(String),
|
SearchInput(String),
|
||||||
|
|
@ -409,6 +411,7 @@ impl From<AppMessage> for Message {
|
||||||
AppMessage::None => Message::None,
|
AppMessage::None => Message::None,
|
||||||
AppMessage::Preview(_entity_opt) => Message::Preview,
|
AppMessage::Preview(_entity_opt) => Message::Preview,
|
||||||
AppMessage::SearchActivate => Message::SearchActivate,
|
AppMessage::SearchActivate => Message::SearchActivate,
|
||||||
|
AppMessage::ScrollTab(scroll_speed) => Message::ScrollTab(scroll_speed),
|
||||||
AppMessage::TabMessage(_entity_opt, tab_message) => Message::TabMessage(tab_message),
|
AppMessage::TabMessage(_entity_opt, tab_message) => Message::TabMessage(tab_message),
|
||||||
AppMessage::TabView(_entity_opt, view) => Message::TabView(view),
|
AppMessage::TabView(_entity_opt, view) => Message::TabView(view),
|
||||||
AppMessage::ToggleFoldersFirst => Message::ToggleFoldersFirst,
|
AppMessage::ToggleFoldersFirst => Message::ToggleFoldersFirst,
|
||||||
|
|
@ -469,6 +472,7 @@ struct App {
|
||||||
tab: Tab,
|
tab: Tab,
|
||||||
key_binds: HashMap<KeyBind, Action>,
|
key_binds: HashMap<KeyBind, Action>,
|
||||||
watcher_opt: Option<(Debouncer<RecommendedWatcher, FileIdMap>, HashSet<PathBuf>)>,
|
watcher_opt: Option<(Debouncer<RecommendedWatcher, FileIdMap>, HashSet<PathBuf>)>,
|
||||||
|
auto_scroll_speed: Option<i16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -896,6 +900,7 @@ impl Application for App {
|
||||||
tab,
|
tab,
|
||||||
key_binds,
|
key_binds,
|
||||||
watcher_opt: None,
|
watcher_opt: None,
|
||||||
|
auto_scroll_speed: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let commands = Task::batch([
|
let commands = Task::batch([
|
||||||
|
|
@ -1214,6 +1219,9 @@ impl Application for App {
|
||||||
return self.update_config();
|
return self.update_config();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::CursorMoved(pos) => {
|
||||||
|
return self.update(Message::TabMessage(tab::Message::CursorMoved(pos)));
|
||||||
|
}
|
||||||
Message::DialogCancel => {
|
Message::DialogCancel => {
|
||||||
self.dialog_pages.pop_front();
|
self.dialog_pages.pop_front();
|
||||||
}
|
}
|
||||||
|
|
@ -1480,6 +1488,11 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::ScrollTab(scroll_speed) => {
|
||||||
|
return self.update(Message::TabMessage(tab::Message::ScrollTab(
|
||||||
|
(scroll_speed as f32) / 10.0,
|
||||||
|
)));
|
||||||
|
}
|
||||||
Message::SearchActivate => {
|
Message::SearchActivate => {
|
||||||
return if self.search_get().is_none() {
|
return if self.search_get().is_none() {
|
||||||
self.search_set(Some(String::new()))
|
self.search_set(Some(String::new()))
|
||||||
|
|
@ -1545,6 +1558,15 @@ impl Application for App {
|
||||||
tab::Command::WindowToggleMaximize => {
|
tab::Command::WindowToggleMaximize => {
|
||||||
commands.push(window::toggle_maximize(self.flags.window_id));
|
commands.push(window::toggle_maximize(self.flags.window_id));
|
||||||
}
|
}
|
||||||
|
tab::Command::AutoScroll(scroll_speed) => {
|
||||||
|
// converting an f32 to an i16 here by multiplying by 10 and casting to i16
|
||||||
|
// further resolution isn't necessary
|
||||||
|
if let Some(scroll_speed_float) = scroll_speed {
|
||||||
|
self.auto_scroll_speed = Some((scroll_speed_float * 10.0) as i16);
|
||||||
|
} else {
|
||||||
|
self.auto_scroll_speed = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
unsupported => {
|
unsupported => {
|
||||||
log::warn!("{unsupported:?} not supported in dialog mode");
|
log::warn!("{unsupported:?} not supported in dialog mode");
|
||||||
}
|
}
|
||||||
|
|
@ -1728,6 +1750,9 @@ impl Application for App {
|
||||||
Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
|
Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => {
|
||||||
Some(Message::Modifiers(modifiers))
|
Some(Message::Modifiers(modifiers))
|
||||||
}
|
}
|
||||||
|
Event::Mouse(mouse::Event::CursorMoved { position: pos }) => {
|
||||||
|
Some(Message::CursorMoved(pos))
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}),
|
}),
|
||||||
Config::subscription().map(|update| {
|
Config::subscription().map(|update| {
|
||||||
|
|
@ -1825,6 +1850,14 @@ impl Application for App {
|
||||||
.map(Message::TabMessage),
|
.map(Message::TabMessage),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if let Some(scroll_speed) = self.auto_scroll_speed {
|
||||||
|
subscriptions.push(
|
||||||
|
iced::time::every(time::Duration::from_millis(10))
|
||||||
|
.with(scroll_speed)
|
||||||
|
.map(|(scroll_speed, _)| Message::ScrollTab(scroll_speed)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for (key, mounter) in MOUNTERS.iter() {
|
for (key, mounter) in MOUNTERS.iter() {
|
||||||
subscriptions.push(
|
subscriptions.push(
|
||||||
mounter.subscription().with(*key).map(
|
mounter.subscription().with(*key).map(
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ pub struct MouseArea<'a, Message> {
|
||||||
on_enter: Option<Box<dyn OnEnterExit<'a, Message>>>,
|
on_enter: Option<Box<dyn OnEnterExit<'a, Message>>>,
|
||||||
on_exit: Option<Box<dyn OnEnterExit<'a, Message>>>,
|
on_exit: Option<Box<dyn OnEnterExit<'a, Message>>>,
|
||||||
show_drag_rect: bool,
|
show_drag_rect: bool,
|
||||||
cursor_offset: Option<Point>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message> MouseArea<'a, Message> {
|
impl<'a, Message> MouseArea<'a, Message> {
|
||||||
|
|
@ -185,11 +184,6 @@ impl<'a, Message> MouseArea<'a, Message> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor_offset(mut self, offset: Option<Point>) -> Self {
|
|
||||||
self.cursor_offset = offset;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the widget's unique identifier.
|
/// Sets the widget's unique identifier.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_id(mut self, id: Id) -> Self {
|
pub fn with_id(mut self, id: Id) -> Self {
|
||||||
|
|
@ -221,8 +215,6 @@ impl<'a, Message, F> OnEnterExit<'a, Message> for F where F: Fn() -> Message + '
|
||||||
struct State {
|
struct State {
|
||||||
last_position: Option<Point>,
|
last_position: Option<Point>,
|
||||||
last_virtual_position: Option<Point>,
|
last_virtual_position: Option<Point>,
|
||||||
last_in_bounds_position: Option<Point>,
|
|
||||||
last_cursor_offset: Option<Point>,
|
|
||||||
drag_initiated: Option<Point>,
|
drag_initiated: Option<Point>,
|
||||||
modifiers: Modifiers,
|
modifiers: Modifiers,
|
||||||
prev_click: Option<(mouse::Click, Instant)>,
|
prev_click: Option<(mouse::Click, Instant)>,
|
||||||
|
|
@ -300,7 +292,6 @@ impl<'a, Message> MouseArea<'a, Message> {
|
||||||
on_exit: None,
|
on_exit: None,
|
||||||
on_scroll: None,
|
on_scroll: None,
|
||||||
show_drag_rect: false,
|
show_drag_rect: false,
|
||||||
cursor_offset: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -431,6 +422,7 @@ where
|
||||||
let mut bg_color = cosmic.accent_color();
|
let mut bg_color = cosmic.accent_color();
|
||||||
//TODO: get correct alpha
|
//TODO: get correct alpha
|
||||||
bg_color.alpha = 0.2;
|
bg_color.alpha = 0.2;
|
||||||
|
renderer.start_layer(*viewport);
|
||||||
renderer.fill_quad(
|
renderer.fill_quad(
|
||||||
Quad {
|
Quad {
|
||||||
bounds,
|
bounds,
|
||||||
|
|
@ -443,6 +435,7 @@ where
|
||||||
},
|
},
|
||||||
Color::from(bg_color),
|
Color::from(bg_color),
|
||||||
);
|
);
|
||||||
|
renderer.end_layer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -515,65 +508,7 @@ fn update<Message: Clone>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if offset differs to calculate virtual position
|
if let Event::Mouse(mouse::Event::CursorMoved { position }) = event {
|
||||||
let mut need_to_recalculate = false;
|
|
||||||
match (state.last_cursor_offset, widget.cursor_offset) {
|
|
||||||
// check if offset has changed between updates
|
|
||||||
(Some(last_cursor_offset), Some(cursor_offset)) => {
|
|
||||||
if last_cursor_offset != cursor_offset {
|
|
||||||
state.last_cursor_offset = Some(cursor_offset);
|
|
||||||
need_to_recalculate = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we've started moving out of bounds
|
|
||||||
(None, Some(cursor_offset)) => {
|
|
||||||
state.last_cursor_offset = Some(cursor_offset);
|
|
||||||
need_to_recalculate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we've moved inbounds
|
|
||||||
(Some(_), None) => {
|
|
||||||
state.last_cursor_offset = None;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if need_to_recalculate {
|
|
||||||
// if we have a cursor_offset, we need to calculate our "virtual" position
|
|
||||||
// (where we think the ABSOLUTE cursor is) - we'll take the last in bounds position and
|
|
||||||
// clamp it to the layout bounds
|
|
||||||
if let Some(offset) = widget.cursor_offset {
|
|
||||||
if let Some(in_bounds_pos) = state.last_in_bounds_position {
|
|
||||||
let mut new_virtual_pos = Point {
|
|
||||||
x: in_bounds_pos.x + offset.x,
|
|
||||||
y: in_bounds_pos.y + offset.y,
|
|
||||||
};
|
|
||||||
|
|
||||||
// clamp to the viewport
|
|
||||||
new_virtual_pos.x = if new_virtual_pos.x > (layout_bounds.width + layout_bounds.x) {
|
|
||||||
layout_bounds.width + layout_bounds.x
|
|
||||||
} else if new_virtual_pos.x < 0.0 {
|
|
||||||
0.0
|
|
||||||
} else {
|
|
||||||
new_virtual_pos.x
|
|
||||||
};
|
|
||||||
|
|
||||||
new_virtual_pos.y = if new_virtual_pos.y > (layout_bounds.height + layout_bounds.y)
|
|
||||||
{
|
|
||||||
layout_bounds.height + layout_bounds.y
|
|
||||||
} else if new_virtual_pos.y < 0.0 {
|
|
||||||
0.0
|
|
||||||
} else {
|
|
||||||
new_virtual_pos.y
|
|
||||||
};
|
|
||||||
|
|
||||||
state.last_virtual_position = Some(new_virtual_pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Event::Mouse(mouse::Event::CursorMoved { .. }) = event {
|
|
||||||
let position_in = cursor.position_in(layout_bounds);
|
let position_in = cursor.position_in(layout_bounds);
|
||||||
match (position_in, state.last_position) {
|
match (position_in, state.last_position) {
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
|
|
@ -590,10 +525,10 @@ fn update<Message: Clone>(
|
||||||
}
|
}
|
||||||
state.last_position = position_in;
|
state.last_position = position_in;
|
||||||
|
|
||||||
// set the last in bounds position to be the ABSOLUTE version of position_in
|
state.last_virtual_position = Some(Point::new(
|
||||||
if position_in.is_some() {
|
viewport.x - layout_bounds.x + position.x,
|
||||||
state.last_in_bounds_position = cursor.position_over(layout_bounds);
|
viewport.y - layout_bounds.y + position.y,
|
||||||
}
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.drag_initiated.is_none() && !cursor.is_over(layout_bounds) {
|
if state.drag_initiated.is_none() && !cursor.is_over(layout_bounds) {
|
||||||
|
|
|
||||||
55
src/tab.rs
55
src/tab.rs
|
|
@ -1160,7 +1160,6 @@ pub enum Message {
|
||||||
DoubleClick(Option<usize>),
|
DoubleClick(Option<usize>),
|
||||||
ClickRelease(Option<usize>),
|
ClickRelease(Option<usize>),
|
||||||
CursorMoved(Point),
|
CursorMoved(Point),
|
||||||
MouseAreaResized(Size, Rectangle),
|
|
||||||
DragEnd(Option<usize>),
|
DragEnd(Option<usize>),
|
||||||
Config(TabConfig),
|
Config(TabConfig),
|
||||||
ContextAction(Action),
|
ContextAction(Action),
|
||||||
|
|
@ -1824,10 +1823,10 @@ pub struct Tab {
|
||||||
search_context: Option<SearchContext>,
|
search_context: Option<SearchContext>,
|
||||||
global_cursor_position: Option<Point>,
|
global_cursor_position: Option<Point>,
|
||||||
current_drag_rect: Option<Rectangle>,
|
current_drag_rect: Option<Rectangle>,
|
||||||
viewport_rect: Option<Rectangle>,
|
|
||||||
virtual_cursor_offset: Option<Point>,
|
virtual_cursor_offset: Option<Point>,
|
||||||
last_scroll_position: Option<Point>,
|
last_scroll_position: Option<Point>,
|
||||||
last_scroll_offset: Option<Point>,
|
last_scroll_offset: Option<Point>,
|
||||||
|
scroll_bounds_opt: Option<Rectangle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
||||||
|
|
@ -1914,10 +1913,10 @@ impl Tab {
|
||||||
search_context: None,
|
search_context: None,
|
||||||
global_cursor_position: None,
|
global_cursor_position: None,
|
||||||
current_drag_rect: None,
|
current_drag_rect: None,
|
||||||
viewport_rect: None,
|
|
||||||
virtual_cursor_offset: None,
|
virtual_cursor_offset: None,
|
||||||
last_scroll_position: None,
|
last_scroll_position: None,
|
||||||
last_scroll_offset: None,
|
last_scroll_offset: None,
|
||||||
|
scroll_bounds_opt: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2217,6 +2216,7 @@ impl Tab {
|
||||||
self.items_opt = None;
|
self.items_opt = None;
|
||||||
//TODO: remember scroll by location?
|
//TODO: remember scroll by location?
|
||||||
self.scroll_opt = None;
|
self.scroll_opt = None;
|
||||||
|
self.scroll_bounds_opt = None;
|
||||||
self.select_focus = None;
|
self.select_focus = None;
|
||||||
self.search_context = None;
|
self.search_context = None;
|
||||||
if let Some(history_i) = history_i_opt {
|
if let Some(history_i) = history_i_opt {
|
||||||
|
|
@ -2281,21 +2281,23 @@ impl Tab {
|
||||||
|
|
||||||
// we're currently dragging
|
// we're currently dragging
|
||||||
if self.current_drag_rect.is_some() {
|
if self.current_drag_rect.is_some() {
|
||||||
if let Some(viewport) = self.viewport_rect {
|
if let Some(scroll_bounds) = self.scroll_bounds_opt {
|
||||||
if !viewport.contains(pos) {
|
if !scroll_bounds.contains(pos) {
|
||||||
if pos.y < viewport.y || pos.y > (viewport.y + viewport.height) {
|
if pos.y < scroll_bounds.y
|
||||||
// if our mouse is above the scrollable viewport, we want to scroll up
|
|| pos.y > (scroll_bounds.y + scroll_bounds.height)
|
||||||
|
{
|
||||||
|
// if our mouse is above the scroll bounds, we want to scroll up
|
||||||
let drag_start_point = Point {
|
let drag_start_point = Point {
|
||||||
x: viewport.x,
|
x: scroll_bounds.x,
|
||||||
y: viewport.y,
|
y: scroll_bounds.y,
|
||||||
};
|
};
|
||||||
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
||||||
// and positive when below the viewport
|
// and positive when below the scroll bounds
|
||||||
let diff_y = pos.y - drag_start_point.y;
|
let diff_y = pos.y - drag_start_point.y;
|
||||||
let scroll_y: f32 = if diff_y > 0.0 {
|
let scroll_y: f32 = if diff_y > 0.0 {
|
||||||
DRAG_SCROLL_DISTANCE
|
DRAG_SCROLL_DISTANCE
|
||||||
} else if diff_y < 0.0 {
|
} else if diff_y < 0.0 {
|
||||||
DRAG_SCROLL_DISTANCE * -1.0
|
-DRAG_SCROLL_DISTANCE
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
@ -2334,20 +2336,6 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::MouseAreaResized(_size, viewport) => {
|
|
||||||
// if we have a scroll position, we want to subtract it from the viewport
|
|
||||||
// so that we don't desync when swapping
|
|
||||||
if let Some(scroll_pos) = self.scroll_opt {
|
|
||||||
self.viewport_rect = Some(Rectangle {
|
|
||||||
x: viewport.x - scroll_pos.x,
|
|
||||||
y: viewport.y - scroll_pos.y,
|
|
||||||
width: viewport.width,
|
|
||||||
height: viewport.height,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
self.viewport_rect = Some(viewport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Message::DragEnd(_) => {
|
Message::DragEnd(_) => {
|
||||||
self.clicked = None;
|
self.clicked = None;
|
||||||
self.virtual_cursor_offset = None;
|
self.virtual_cursor_offset = None;
|
||||||
|
|
@ -2604,11 +2592,15 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Drag(rect_opt) => {
|
Message::Drag(rect_opt) => {
|
||||||
self.current_drag_rect = rect_opt;
|
if self.mode.multiple() {
|
||||||
|
self.current_drag_rect = rect_opt;
|
||||||
|
}
|
||||||
if let Some(rect) = rect_opt {
|
if let Some(rect) = rect_opt {
|
||||||
self.context_menu = None;
|
self.context_menu = None;
|
||||||
self.location_context_menu_index = None;
|
self.location_context_menu_index = None;
|
||||||
self.select_rect(rect, mod_ctrl, mod_shift);
|
if self.mode.multiple() {
|
||||||
|
self.select_rect(rect, mod_ctrl, mod_shift);
|
||||||
|
}
|
||||||
if self.select_focus.take().is_some() {
|
if self.select_focus.take().is_some() {
|
||||||
// Unfocus currently focused button
|
// Unfocus currently focused button
|
||||||
commands.push(Command::Iced(
|
commands.push(Command::Iced(
|
||||||
|
|
@ -3005,6 +2997,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::Scroll(viewport) => {
|
Message::Scroll(viewport) => {
|
||||||
|
self.scroll_bounds_opt = Some(viewport.bounds());
|
||||||
self.scroll_opt = Some(viewport.absolute_offset());
|
self.scroll_opt = Some(viewport.absolute_offset());
|
||||||
}
|
}
|
||||||
Message::ScrollTab(scroll_speed) => {
|
Message::ScrollTab(scroll_speed) => {
|
||||||
|
|
@ -4312,10 +4305,8 @@ impl Tab {
|
||||||
.on_press(|_| Message::Click(None))
|
.on_press(|_| Message::Click(None))
|
||||||
.on_drag(Message::Drag)
|
.on_drag(Message::Drag)
|
||||||
.on_drag_end(|_| Message::DragEnd(None))
|
.on_drag_end(|_| Message::DragEnd(None))
|
||||||
.show_drag_rect(true)
|
.show_drag_rect(self.mode.multiple())
|
||||||
.on_release(|_| Message::ClickRelease(None))
|
.on_release(|_| Message::ClickRelease(None))
|
||||||
.on_resize(Message::MouseAreaResized)
|
|
||||||
.cursor_offset(self.virtual_cursor_offset)
|
|
||||||
.into(),
|
.into(),
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
|
@ -4647,10 +4638,8 @@ impl Tab {
|
||||||
.on_press(|_| Message::Click(None))
|
.on_press(|_| Message::Click(None))
|
||||||
.on_drag(Message::Drag)
|
.on_drag(Message::Drag)
|
||||||
.on_drag_end(|_| Message::DragEnd(None))
|
.on_drag_end(|_| Message::DragEnd(None))
|
||||||
.show_drag_rect(true)
|
.show_drag_rect(self.mode.multiple())
|
||||||
.on_release(|_| Message::ClickRelease(None))
|
.on_release(|_| Message::ClickRelease(None))
|
||||||
.on_resize(Message::MouseAreaResized)
|
|
||||||
.cursor_offset(self.virtual_cursor_offset)
|
|
||||||
.into(),
|
.into(),
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue