Reconnect Clipboard on window close

Fixes #2564
This commit is contained in:
Héctor Ramón Jiménez 2024-09-03 11:23:54 +02:00
parent 9957481d41
commit 9628dc20d5
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
3 changed files with 46 additions and 22 deletions

View file

@ -2,7 +2,7 @@
use crate::core::clipboard::Kind; use crate::core::clipboard::Kind;
use std::sync::Arc; use std::sync::Arc;
use winit::window::Window; use winit::window::{Window, WindowId};
/// A buffer for short-term storage and transfer within and between /// A buffer for short-term storage and transfer within and between
/// applications. /// applications.
@ -83,6 +83,14 @@ impl Clipboard {
State::Unavailable => {} State::Unavailable => {}
} }
} }
/// Returns the identifier of the window used to create the [`Clipboard`], if any.
pub fn window_id(&self) -> Option<WindowId> {
match &self.state {
State::Connected { window, .. } => Some(window.id()),
State::Unavailable => None,
}
}
} }
impl crate::core::Clipboard for Clipboard { impl crate::core::Clipboard for Clipboard {

View file

@ -307,8 +307,6 @@ where
} }
}; };
let clipboard = Clipboard::connect(window.clone());
let finish_boot = async move { let finish_boot = async move {
let mut compositor = let mut compositor =
C::new(graphics_settings, window.clone()).await?; C::new(graphics_settings, window.clone()).await?;
@ -318,10 +316,7 @@ where
} }
sender sender
.send(Boot { .send(Boot { compositor })
compositor,
clipboard,
})
.ok() .ok()
.expect("Send boot event"); .expect("Send boot event");
@ -617,7 +612,6 @@ where
struct Boot<C> { struct Boot<C> {
compositor: C, compositor: C,
clipboard: Clipboard,
} }
#[derive(Debug)] #[derive(Debug)]
@ -662,10 +656,7 @@ async fn run_instance<P, C>(
use winit::event; use winit::event;
use winit::event_loop::ControlFlow; use winit::event_loop::ControlFlow;
let Boot { let Boot { mut compositor } = boot.await.expect("Receive boot");
mut compositor,
mut clipboard,
} = boot.await.expect("Receive boot");
let mut window_manager = WindowManager::new(); let mut window_manager = WindowManager::new();
let mut is_window_opening = !is_daemon; let mut is_window_opening = !is_daemon;
@ -676,6 +667,7 @@ async fn run_instance<P, C>(
let mut ui_caches = FxHashMap::default(); let mut ui_caches = FxHashMap::default();
let mut user_interfaces = ManuallyDrop::new(FxHashMap::default()); let mut user_interfaces = ManuallyDrop::new(FxHashMap::default());
let mut clipboard = Clipboard::unconnected();
debug.startup_finished(); debug.startup_finished();
@ -734,6 +726,10 @@ async fn run_instance<P, C>(
}), }),
)); ));
if clipboard.window_id().is_none() {
clipboard = Clipboard::connect(window.raw.clone());
}
let _ = on_open.send(id); let _ = on_open.send(id);
is_window_opening = false; is_window_opening = false;
} }
@ -979,14 +975,22 @@ async fn run_instance<P, C>(
winit::event::WindowEvent::CloseRequested winit::event::WindowEvent::CloseRequested
) && window.exit_on_close_request ) && window.exit_on_close_request
{ {
let _ = window_manager.remove(id); run_action(
let _ = user_interfaces.remove(&id); Action::Window(runtime::window::Action::Close(
let _ = ui_caches.remove(&id); id,
)),
events.push(( &program,
id, &mut compositor,
core::Event::Window(window::Event::Closed), &mut events,
)); &mut messages,
&mut clipboard,
&mut control_sender,
&mut debug,
&mut user_interfaces,
&mut window_manager,
&mut ui_caches,
&mut is_window_opening,
);
} else { } else {
window.state.update( window.state.update(
&window.raw, &window.raw,
@ -1223,10 +1227,18 @@ fn run_action<P, C>(
*is_window_opening = true; *is_window_opening = true;
} }
window::Action::Close(id) => { window::Action::Close(id) => {
let window = window_manager.remove(id);
let _ = ui_caches.remove(&id); let _ = ui_caches.remove(&id);
let _ = interfaces.remove(&id);
if let Some(window) = window_manager.remove(id) {
if clipboard.window_id() == Some(window.raw.id()) {
*clipboard = window_manager
.first()
.map(|window| window.raw.clone())
.map(Clipboard::connect)
.unwrap_or_else(Clipboard::unconnected);
}
if window.is_some() {
events.push(( events.push((
id, id,
core::Event::Window(core::window::Event::Closed), core::Event::Window(core::window::Event::Closed),

View file

@ -74,6 +74,10 @@ where
self.entries.is_empty() self.entries.is_empty()
} }
pub fn first(&self) -> Option<&Window<P, C>> {
self.entries.first_key_value().map(|(_id, window)| window)
}
pub fn iter_mut( pub fn iter_mut(
&mut self, &mut self,
) -> impl Iterator<Item = (Id, &mut Window<P, C>)> { ) -> impl Iterator<Item = (Id, &mut Window<P, C>)> {