diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | core/src/clipboard.rs | 29 | ||||
-rw-r--r-- | runtime/src/clipboard.rs | 49 | ||||
-rw-r--r-- | runtime/src/command/action.rs | 9 | ||||
-rw-r--r-- | widget/src/text_editor.rs | 11 | ||||
-rw-r--r-- | widget/src/text_input.rs | 19 | ||||
-rw-r--r-- | winit/src/application.rs | 20 | ||||
-rw-r--r-- | winit/src/clipboard.rs | 64 | ||||
-rw-r--r-- | winit/src/multi_window.rs | 20 |
9 files changed, 95 insertions, 128 deletions
@@ -160,5 +160,5 @@ web-sys = "=0.3.67" web-time = "0.2" wgpu = "0.19" winapi = "0.3" -window_clipboard = "0.4" +window_clipboard = "0.4.1" winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5" } diff --git a/core/src/clipboard.rs b/core/src/clipboard.rs index ff2e31d0..5df3e267 100644 --- a/core/src/clipboard.rs +++ b/core/src/clipboard.rs @@ -4,16 +4,21 @@ /// applications. pub trait Clipboard { /// Reads the current content of the [`Clipboard`] as text. - fn read(&self) -> Option<String>; + fn read(&self, kind: Kind) -> Option<String>; /// Writes the given text contents to the [`Clipboard`]. - fn write(&mut self, contents: String); - - /// Reads the current content of Primary as text. - fn read_primary(&self) -> Option<String>; + fn write(&mut self, kind: Kind, contents: String); +} - /// Writes the given text contents to Primary. - fn write_primary(&mut self, contents: String); +/// The kind of [`Clipboard`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Kind { + /// The standard clipboard. + Standard, + /// The primary clipboard. + /// + /// Normally only present in X11 and Wayland. + Primary, } /// A null implementation of the [`Clipboard`] trait. @@ -21,15 +26,9 @@ pub trait Clipboard { pub struct Null; impl Clipboard for Null { - fn read(&self) -> Option<String> { - None - } - - fn write(&mut self, _contents: String) {} - - fn read_primary(&self) -> Option<String> { + fn read(&self, _kind: Kind) -> Option<String> { None } - fn write_primary(&mut self, _contents: String) {} + fn write(&mut self, _kind: Kind, _contents: String) {} } diff --git a/runtime/src/clipboard.rs b/runtime/src/clipboard.rs index 49044a0f..dd47c47d 100644 --- a/runtime/src/clipboard.rs +++ b/runtime/src/clipboard.rs @@ -1,5 +1,6 @@ //! Access the clipboard. use crate::command::{self, Command}; +use crate::core::clipboard::Kind; use crate::futures::MaybeSend; use std::fmt; @@ -9,10 +10,10 @@ use std::fmt; /// [`Command`]: crate::Command pub enum Action<T> { /// Read the clipboard and produce `T` with the result. - Read(Box<dyn Fn(Option<String>) -> T>), + Read(Box<dyn Fn(Option<String>) -> T>, Kind), /// Write the given contents to the clipboard. - Write(String), + Write(String, Kind), } impl<T> Action<T> { @@ -25,8 +26,10 @@ impl<T> Action<T> { T: 'static, { match self { - Self::Read(o) => Action::Read(Box::new(move |s| f(o(s)))), - Self::Write(content) => Action::Write(content), + Self::Read(o, target) => { + Action::Read(Box::new(move |s| f(o(s))), target) + } + Self::Write(content, target) => Action::Write(content, target), } } } @@ -34,8 +37,8 @@ impl<T> Action<T> { impl<T> fmt::Debug for Action<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Read(_) => write!(f, "Action::Read"), - Self::Write(_) => write!(f, "Action::Write"), + Self::Read(_, target) => write!(f, "Action::Read{target:?}"), + Self::Write(_, target) => write!(f, "Action::Write({target:?})"), } } } @@ -44,24 +47,34 @@ impl<T> fmt::Debug for Action<T> { pub fn read<Message>( f: impl Fn(Option<String>) -> Message + 'static, ) -> Command<Message> { - Command::single(command::Action::Clipboard(Action::Read(Box::new(f)))) + Command::single(command::Action::Clipboard(Action::Read( + Box::new(f), + Kind::Standard, + ))) } -/// Write the given contents to the clipboard. -pub fn write<Message>(contents: String) -> Command<Message> { - Command::single(command::Action::Clipboard(Action::Write(contents))) -} - -/// Read the current contents of primary. +/// Read the current contents of the primary clipboard. pub fn read_primary<Message>( f: impl Fn(Option<String>) -> Message + 'static, ) -> Command<Message> { - Command::single(command::Action::ClipboardPrimary(Action::Read(Box::new( - f, - )))) + Command::single(command::Action::Clipboard(Action::Read( + Box::new(f), + Kind::Primary, + ))) +} + +/// Write the given contents to the clipboard. +pub fn write<Message>(contents: String) -> Command<Message> { + Command::single(command::Action::Clipboard(Action::Write( + contents, + Kind::Standard, + ))) } -/// Write the given contents to primary. +/// Write the given contents to the primary clipboard. pub fn write_primary<Message>(contents: String) -> Command<Message> { - Command::single(command::Action::ClipboardPrimary(Action::Write(contents))) + Command::single(command::Action::Clipboard(Action::Write( + contents, + Kind::Primary, + ))) } diff --git a/runtime/src/command/action.rs b/runtime/src/command/action.rs index f04c642c..c9ffe801 100644 --- a/runtime/src/command/action.rs +++ b/runtime/src/command/action.rs @@ -26,9 +26,6 @@ pub enum Action<T> { /// Run a clipboard action. Clipboard(clipboard::Action<T>), - /// Run a clipboard action on primary. - ClipboardPrimary(clipboard::Action<T>), - /// Run a window action. Window(window::Action<T>), @@ -69,9 +66,6 @@ impl<T> Action<T> { Self::Future(future) => Action::Future(Box::pin(future.map(f))), Self::Stream(stream) => Action::Stream(Box::pin(stream.map(f))), Self::Clipboard(action) => Action::Clipboard(action.map(f)), - Self::ClipboardPrimary(action) => { - Action::ClipboardPrimary(action.map(f)) - } Self::Window(window) => Action::Window(window.map(f)), Self::System(system) => Action::System(system.map(f)), Self::Widget(operation) => { @@ -94,9 +88,6 @@ impl<T> fmt::Debug for Action<T> { Self::Clipboard(action) => { write!(f, "Action::Clipboard({action:?})") } - Self::ClipboardPrimary(action) => { - write!(f, "Action::ClipboardPrimary({action:?})") - } Self::Window(action) => { write!(f, "Action::Window({action:?})") } diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index cbcab1eb..50f7fabb 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -1,4 +1,5 @@ //! Display a multi-line text input for text editing. +use crate::core::clipboard::{self, Clipboard}; use crate::core::event::{self, Event}; use crate::core::keyboard; use crate::core::keyboard::key; @@ -10,7 +11,7 @@ use crate::core::text::highlighter::{self, Highlighter}; use crate::core::text::{self, LineHeight}; use crate::core::widget::{self, Widget}; use crate::core::{ - Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, + Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, }; use std::cell::RefCell; @@ -448,17 +449,19 @@ where } Update::Copy => { if let Some(selection) = self.content.selection() { - clipboard.write(selection); + clipboard.write(clipboard::Kind::Standard, selection); } } Update::Cut => { if let Some(selection) = self.content.selection() { - clipboard.write(selection.clone()); + clipboard.write(clipboard::Kind::Standard, selection); shell.publish(on_edit(Action::Edit(Edit::Delete))); } } Update::Paste => { - if let Some(contents) = clipboard.read() { + if let Some(contents) = + clipboard.read(clipboard::Kind::Standard) + { shell.publish(on_edit(Action::Edit(Edit::Paste( Arc::new(contents), )))); diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 0a7ed014..f5b57422 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -12,6 +12,7 @@ pub use value::Value; use editor::Editor; use crate::core::alignment; +use crate::core::clipboard::{self, Clipboard}; use crate::core::event::{self, Event}; use crate::core::keyboard; use crate::core::keyboard::key; @@ -26,8 +27,8 @@ use crate::core::widget::operation::{self, Operation}; use crate::core::widget::tree::{self, Tree}; use crate::core::window; use crate::core::{ - Clipboard, Element, Layout, Length, Padding, Pixels, Point, Rectangle, - Shell, Size, Vector, Widget, + Element, Layout, Length, Padding, Pixels, Point, Rectangle, Shell, Size, + Vector, Widget, }; use crate::runtime::Command; @@ -864,8 +865,10 @@ where if let Some((start, end)) = state.cursor.selection(value) { - clipboard - .write(value.select(start, end).to_string()); + clipboard.write( + clipboard::Kind::Standard, + value.select(start, end).to_string(), + ); } } keyboard::Key::Character("x") @@ -874,8 +877,10 @@ where if let Some((start, end)) = state.cursor.selection(value) { - clipboard - .write(value.select(start, end).to_string()); + clipboard.write( + clipboard::Kind::Standard, + value.select(start, end).to_string(), + ); } let mut editor = Editor::new(value, &mut state.cursor); @@ -894,7 +899,7 @@ where Some(content) => content, None => { let content: String = clipboard - .read() + .read(clipboard::Kind::Standard) .unwrap_or_default() .chars() .filter(|c| !c.is_control()) diff --git a/winit/src/application.rs b/winit/src/application.rs index 2d3ac52c..0fc67adc 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -704,27 +704,15 @@ pub fn run_command<A, C, E>( runtime.run(stream); } command::Action::Clipboard(action) => match action { - clipboard::Action::Read(tag) => { - let message = tag(clipboard.read()); + clipboard::Action::Read(tag, kind) => { + let message = tag(clipboard.read(kind)); proxy .send_event(message) .expect("Send message to event loop"); } - clipboard::Action::Write(contents) => { - clipboard.write(contents); - } - }, - command::Action::ClipboardPrimary(action) => match action { - clipboard::Action::Read(tag) => { - let message = tag(clipboard.read_primary()); - - proxy - .send_event(message) - .expect("Send message to event loop"); - } - clipboard::Action::Write(contents) => { - clipboard.write_primary(contents); + clipboard::Action::Write(contents, kind) => { + clipboard.write(kind, contents); } }, command::Action::Window(action) => match action { diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index a1496fa3..5237ca01 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -1,5 +1,7 @@ //! Access the clipboard. +use crate::core::clipboard::Kind; + /// A buffer for short-term storage and transfer within and between /// applications. #[allow(missing_debug_implementations)] @@ -33,46 +35,32 @@ impl Clipboard { } /// Reads the current content of the [`Clipboard`] as text. - pub fn read(&self) -> Option<String> { + pub fn read(&self, kind: Kind) -> Option<String> { match &self.state { - State::Connected(clipboard) => clipboard.read().ok(), + State::Connected(clipboard) => match kind { + Kind::Standard => clipboard.read().ok(), + Kind::Primary => clipboard.read_primary().and_then(Result::ok), + }, State::Unavailable => None, } } /// Writes the given text contents to the [`Clipboard`]. - pub fn write(&mut self, contents: String) { + pub fn write(&mut self, kind: Kind, contents: String) { match &mut self.state { - State::Connected(clipboard) => match clipboard.write(contents) { - Ok(()) => {} - Err(error) => { - log::warn!("error writing to clipboard: {error}"); - } - }, - State::Unavailable => {} - } - } - - /// Reads the current content of primary as text. - pub fn read_primary(&self) -> Option<String> { - match &self.state { State::Connected(clipboard) => { - clipboard.read_primary().and_then(|r| r.ok()) - } - State::Unavailable => None, - } - } + let result = match kind { + Kind::Standard => clipboard.write(contents), + Kind::Primary => { + clipboard.write_primary(contents).unwrap_or(Ok(())) + } + }; - /// Writes the given text contents to primary. - pub fn write_primary(&mut self, contents: String) { - match &mut self.state { - State::Connected(clipboard) => { - match clipboard.write_primary(contents) { - Some(Ok(())) => {} - Some(Err(error)) => { - log::warn!("error writing to primary: {error}"); + match result { + Ok(()) => {} + Err(error) => { + log::warn!("error writing to clipboard: {error}"); } - None => {} } } State::Unavailable => {} @@ -81,19 +69,11 @@ impl Clipboard { } impl crate::core::Clipboard for Clipboard { - fn read(&self) -> Option<String> { - self.read() - } - - fn write(&mut self, contents: String) { - self.write(contents); - } - - fn read_primary(&self) -> Option<String> { - self.read_primary() + fn read(&self, kind: Kind) -> Option<String> { + self.read(kind) } - fn write_primary(&mut self, contents: String) { - self.write_primary(contents); + fn write(&mut self, kind: Kind, contents: String) { + self.write(kind, contents); } } diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 33f521c4..ed00abdf 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -876,27 +876,15 @@ fn run_command<A, C, E>( runtime.run(Box::pin(stream)); } command::Action::Clipboard(action) => match action { - clipboard::Action::Read(tag) => { - let message = tag(clipboard.read()); + clipboard::Action::Read(tag, kind) => { + let message = tag(clipboard.read(kind)); proxy .send_event(message) .expect("Send message to event loop"); } - clipboard::Action::Write(contents) => { - clipboard.write(contents); - } - }, - command::Action::ClipboardPrimary(action) => match action { - clipboard::Action::Read(tag) => { - let message = tag(clipboard.read_primary()); - - proxy - .send_event(message) - .expect("Send message to event loop"); - } - clipboard::Action::Write(contents) => { - clipboard.write_primary(contents); + clipboard::Action::Write(contents, kind) => { + clipboard.write(kind, contents); } }, command::Action::Window(action) => match action { |