iced: propagate pane drag destinations
This commit is contained in:
parent
1fb7e08f23
commit
a489a6b790
9 changed files with 142 additions and 15 deletions
|
|
@ -224,6 +224,16 @@ impl DndDestinationRectangles {
|
|||
|
||||
/// Pushes a new rectangle to the list of DnD destination rectangles.
|
||||
pub fn push(&mut self, rectangle: DndDestinationRectangle) {
|
||||
log::debug!(
|
||||
"clipboard: register dnd rectangle id={} rect=({}, {}, {}, {}) mimes={:?} actions={:?}",
|
||||
rectangle.id,
|
||||
rectangle.rectangle.x,
|
||||
rectangle.rectangle.y,
|
||||
rectangle.rectangle.width,
|
||||
rectangle.rectangle.height,
|
||||
rectangle.mime_types,
|
||||
rectangle.actions
|
||||
);
|
||||
self.rectangles.push(rectangle);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ use crate::core::{
|
|||
self, Background, Border, Clipboard, Color, Element, Event, Layout, Length,
|
||||
Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget,
|
||||
};
|
||||
use log::trace;
|
||||
|
||||
const DRAG_DEADBAND_DISTANCE: f32 = 10.0;
|
||||
const THICKNESS_RATIO: f32 = 25.0;
|
||||
|
|
@ -1030,6 +1031,35 @@ where
|
|||
|
||||
(!children.is_empty()).then(|| Group::with_children(children).overlay())
|
||||
}
|
||||
|
||||
fn drag_destinations(
|
||||
&self,
|
||||
state: &Tree,
|
||||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
dnd_rectangles: &mut crate::core::clipboard::DndDestinationRectangles,
|
||||
) {
|
||||
self.contents
|
||||
.iter()
|
||||
.zip(state.children.iter())
|
||||
.zip(layout.children())
|
||||
.for_each(|((content, tree), child_layout)| {
|
||||
trace!(
|
||||
target: "iced::widget::pane_grid",
|
||||
"pane drag layout bounds=({:.2},{:.2},{:.2},{:.2})",
|
||||
child_layout.bounds().x,
|
||||
child_layout.bounds().y,
|
||||
child_layout.bounds().width,
|
||||
child_layout.bounds().height
|
||||
);
|
||||
content.drag_destinations(
|
||||
tree,
|
||||
child_layout.with_virtual_offset(layout.virtual_offset()),
|
||||
renderer,
|
||||
dnd_rectangles,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> From<PaneGrid<'a, Message, Theme, Renderer>>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::core::renderer;
|
|||
use crate::core::widget::{self, Tree};
|
||||
use crate::core::{
|
||||
self, Clipboard, Element, Event, Layout, Point, Rectangle, Shell, Size,
|
||||
Vector,
|
||||
Vector, event,
|
||||
};
|
||||
use crate::pane_grid::{Draggable, TitleBar};
|
||||
|
||||
|
|
@ -308,6 +308,51 @@ where
|
|||
None
|
||||
}
|
||||
|
||||
pub(crate) fn drag_destinations(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
dnd_rectangles: &mut core::clipboard::DndDestinationRectangles,
|
||||
) {
|
||||
let mut body_layout = layout;
|
||||
if self.title_bar.is_some() {
|
||||
let mut children = layout.children();
|
||||
let title_bar_layout = children.next();
|
||||
body_layout = children.next().unwrap_or(layout);
|
||||
if let Some(title_bar_layout) = title_bar_layout {
|
||||
log::trace!(
|
||||
target: "iced::widget::pane_grid::content",
|
||||
"title_bar bounds=({:.2},{:.2},{:.2},{:.2}) body_bounds=({:.2},{:.2},{:.2},{:.2})",
|
||||
title_bar_layout.bounds().x,
|
||||
title_bar_layout.bounds().y,
|
||||
title_bar_layout.bounds().width,
|
||||
title_bar_layout.bounds().height,
|
||||
body_layout.bounds().x,
|
||||
body_layout.bounds().y,
|
||||
body_layout.bounds().width,
|
||||
body_layout.bounds().height,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log::trace!(
|
||||
target: "iced::widget::pane_grid::content",
|
||||
"body_bounds=({:.2},{:.2},{:.2},{:.2})",
|
||||
body_layout.bounds().x,
|
||||
body_layout.bounds().y,
|
||||
body_layout.bounds().width,
|
||||
body_layout.bounds().height,
|
||||
);
|
||||
}
|
||||
|
||||
self.body.as_widget().drag_destinations(
|
||||
&tree.children[0],
|
||||
body_layout,
|
||||
renderer,
|
||||
dnd_rectangles,
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn mouse_interaction(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ iced_accessibility.features = ["accesskit_winit"]
|
|||
log.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
thiserror.workspace = true
|
||||
tracing.workspace = true
|
||||
window_clipboard.workspace = true
|
||||
dnd.workspace = true
|
||||
winit.workspace = true
|
||||
|
|
|
|||
|
|
@ -402,7 +402,13 @@ impl crate::core::Clipboard for Clipboard {
|
|||
sender,
|
||||
..
|
||||
} => {
|
||||
log::debug!(
|
||||
"clipboard::start_dnd queued internal={} source={:?}",
|
||||
internal,
|
||||
source_surface
|
||||
);
|
||||
_ = sender.sender.unbounded_send(Control::StartDnd);
|
||||
|
||||
queued_events.push(StartDnd {
|
||||
internal,
|
||||
source_surface,
|
||||
|
|
@ -422,6 +428,25 @@ impl crate::core::Clipboard for Clipboard {
|
|||
) {
|
||||
match &self.state {
|
||||
State::Connected { clipboard, .. } => {
|
||||
trace!(
|
||||
target: "iced::winit::clipboard",
|
||||
"register destination surface={:?} count={}",
|
||||
surface,
|
||||
rectangles.len()
|
||||
);
|
||||
for rect in &rectangles {
|
||||
trace!(
|
||||
target: "iced::winit::clipboard",
|
||||
"rect id={:?} bounds=({:.2},{:.2},{:.2},{:.2}) actions={:?} preferred={:?}",
|
||||
rect.id,
|
||||
rect.rectangle.x,
|
||||
rect.rectangle.y,
|
||||
rect.rectangle.width,
|
||||
rect.rectangle.height,
|
||||
rect.actions,
|
||||
rect.preferred
|
||||
);
|
||||
}
|
||||
_ = clipboard.register_dnd_destination(surface, rectangles)
|
||||
}
|
||||
State::Unavailable => {}
|
||||
|
|
|
|||
|
|
@ -1491,6 +1491,9 @@ async fn run_instance<P>(
|
|||
Event::Exit => break,
|
||||
Event::Dnd(e) => {
|
||||
use winit::raw_window_handle::HasWindowHandle;
|
||||
|
||||
log::trace!(target: "iced::winit::program", "Dnd event {:?}", e);
|
||||
|
||||
match &e {
|
||||
dnd::DndEvent::Offer(_, dnd::OfferEvent::Leave) => {
|
||||
events.push((cur_dnd_surface, core::Event::Dnd(e)));
|
||||
|
|
@ -1577,7 +1580,7 @@ async fn run_instance<P>(
|
|||
let compositor = match compositor.as_mut() {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
tracing::error!("No compositor for DnD");
|
||||
log::error!("No compositor for DnD");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
|
@ -1592,10 +1595,20 @@ async fn run_instance<P>(
|
|||
{
|
||||
let Some(window_id) = source_surface.and_then(|source| {
|
||||
match source {
|
||||
core::clipboard::DndSource::Surface(s) => Some(s),
|
||||
core::clipboard::DndSource::Surface(s) => {
|
||||
log::trace!(
|
||||
"start_dnd: using explicit surface {:?}",
|
||||
s
|
||||
);
|
||||
Some(s)
|
||||
}
|
||||
core::clipboard::DndSource::Widget(w) => {
|
||||
log::debug!(
|
||||
"start_dnd: searching for widget {:?}",
|
||||
w
|
||||
);
|
||||
// search windows for widget with operation
|
||||
user_interfaces.iter_mut().find_map(
|
||||
let result = user_interfaces.iter_mut().find_map(
|
||||
|(ui_id, ui)| {
|
||||
let Some(ui_renderer) = window_manager
|
||||
.get_mut(ui_id.clone())
|
||||
|
|
@ -1642,7 +1655,14 @@ async fn run_instance<P>(
|
|||
}
|
||||
None
|
||||
},
|
||||
)
|
||||
);
|
||||
if result.is_none() {
|
||||
log::warn!(
|
||||
"start_dnd: widget {:?} not found; drag will fail",
|
||||
w
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
}) else {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ use std::{
|
|||
collections::{HashMap, HashSet},
|
||||
fmt::Debug,
|
||||
};
|
||||
use tracing::error;
|
||||
use log::error;
|
||||
use wayland_backend::client::Backend;
|
||||
use wayland_client::globals::GlobalError;
|
||||
use wayland_protocols::wp::keyboard_shortcuts_inhibit::zv1::client::zwp_keyboard_shortcuts_inhibit_manager_v1;
|
||||
|
|
|
|||
|
|
@ -1444,7 +1444,7 @@ impl SctkState {
|
|||
platform_specific::wayland::session_lock::Action::LockSurface { id, output } => {
|
||||
// Should we panic if the id does not match?
|
||||
if self.lock_surfaces.iter().any(|s| s.output == output) {
|
||||
tracing::warn!("Cannot create multiple lock surfaces for a single output.");
|
||||
log::warn!("Cannot create multiple lock surfaces for a single output.");
|
||||
return Ok(());
|
||||
}
|
||||
// TODO how to handle this when there's no lock?
|
||||
|
|
@ -1488,13 +1488,13 @@ impl SctkState {
|
|||
Action::OverlapNotify(id, enabled) => {
|
||||
if let Some(layer_surface) = self.layer_surfaces.iter_mut().find(|l| l.id == id) {
|
||||
let Some(overlap_notify_state) = self.overlap_notify.as_ref() else {
|
||||
tracing::error!("Overlap notify is not supported.");
|
||||
log::error!("Overlap notify is not supported.");
|
||||
return Ok(());
|
||||
};
|
||||
let my_id = layer_surface.surface.wl_surface().id();
|
||||
if enabled && !self.overlap_notifications.contains_key(&my_id) {
|
||||
let SurfaceKind::Wlr(wlr) = &layer_surface.surface.kind() else {
|
||||
tracing::error!("Overlap notify is not supported for non wlr surface.");
|
||||
log::error!("Overlap notify is not supported for non wlr surface.");
|
||||
return Ok(());
|
||||
};
|
||||
let notification = overlap_notify_state.notify.notify_on_overlap(wlr, &self.queue_handle, OverlapNotificationV1 { surface: layer_surface.surface.wl_surface().clone() });
|
||||
|
|
@ -1503,7 +1503,7 @@ impl SctkState {
|
|||
_ = self.overlap_notifications.remove(&my_id);
|
||||
}
|
||||
} else {
|
||||
tracing::error!("Overlap notify subscription cannot be created for surface. No matching layer surface found.");
|
||||
log::error!("Overlap notify subscription cannot be created for surface. No matching layer surface found.");
|
||||
}
|
||||
},
|
||||
Action::Subsurface(action) => match action {
|
||||
|
|
|
|||
|
|
@ -242,9 +242,7 @@ impl winit::window::Window for SctkWinitWindow {
|
|||
}
|
||||
|
||||
fn current_monitor(&self) -> Option<winit::monitor::MonitorHandle> {
|
||||
tracing::warn!(
|
||||
"current_monitor is not implemented for wayland windows."
|
||||
);
|
||||
log::warn!("current_monitor is not implemented for wayland windows.");
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -255,7 +253,7 @@ impl winit::window::Window for SctkWinitWindow {
|
|||
}
|
||||
|
||||
fn has_focus(&self) -> bool {
|
||||
tracing::warn!("has_focus is not implemented for wayland windows.");
|
||||
log::warn!("has_focus is not implemented for wayland windows.");
|
||||
false
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue