iced: propagate pane drag destinations

This commit is contained in:
Stephan Buys 2025-11-19 15:44:21 +02:00 committed by Ashley Wulber
parent 1fb7e08f23
commit a489a6b790
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
9 changed files with 142 additions and 15 deletions

View file

@ -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 => {}

View file

@ -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 {

View file

@ -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;

View file

@ -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 {

View file

@ -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
}