From cf357f8b68dd37caea04cae92469ab82be5b676f Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Wed, 3 Jul 2024 16:54:56 +0800 Subject: [PATCH] feat(clipboard): handle clipboard message --- Cargo.lock | 169 +++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 1 + src/window.rs | 38 ++++++++++++ 3 files changed, 198 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18fe5857..50329ba0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,6 +143,24 @@ dependencies = [ "serde", ] +[[package]] +name = "arboard" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89" +dependencies = [ + "clipboard-win", + "core-graphics 0.23.2", + "image 0.25.1", + "log", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation", + "parking_lot", + "windows-sys 0.48.0", + "x11rb", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -388,7 +406,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" dependencies = [ "block-sys", - "objc2", + "objc2 0.4.1", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", ] [[package]] @@ -678,6 +705,15 @@ dependencies = [ "libloading", ] +[[package]] +name = "clipboard-win" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79f4473f5144e20d9aceaf2972478f06ddf687831eafeeb434fbaf0acc4144ad" +dependencies = [ + "error-code", +] + [[package]] name = "cocoa" version = "0.24.1" @@ -765,7 +801,7 @@ dependencies = [ "fonts", "fonts_traits", "gleam", - "image", + "image 0.24.9", "ipc-channel", "keyboard-types", "libc", @@ -1447,6 +1483,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-code" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" + [[package]] name = "etagere" version = "0.2.13" @@ -2244,9 +2286,9 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" dependencies = [ - "block2", + "block2 0.3.0", "dispatch", - "objc2", + "objc2 0.4.1", ] [[package]] @@ -2425,6 +2467,19 @@ dependencies = [ "tiff", ] +[[package]] +name = "image" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +dependencies = [ + "bytemuck", + "byteorder", + "num-traits", + "png", + "tiff", +] + [[package]] name = "imsz" version = "0.2.2" @@ -3372,7 +3427,7 @@ dependencies = [ "http", "hyper", "hyper_serde", - "image", + "image 0.24.9", "ipc-channel", "lazy_static", "log", @@ -3537,7 +3592,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" dependencies = [ "objc-sys", - "objc2-encode", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode 4.0.3", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", + "objc2-metal", ] [[package]] @@ -3546,6 +3651,49 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", + "objc2-metal", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -3812,7 +3960,7 @@ version = "0.0.1" source = "git+https://github.com/servo/servo.git?rev=ad01342#ad01342f00089cbddb252d54ed55f90a20ce43da" dependencies = [ "euclid", - "image", + "image 0.24.9", "ipc-channel", "log", "malloc_size_of", @@ -4322,7 +4470,7 @@ dependencies = [ "html5ever", "http", "hyper_serde", - "image", + "image 0.24.9", "indexmap", "ipc-channel", "itertools 0.13.0", @@ -5708,6 +5856,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "verso" version = "0.0.1" dependencies = [ + "arboard", "block", "cfg_aliases 0.2.1", "cocoa 0.25.0", @@ -6030,7 +6179,7 @@ dependencies = [ "crossbeam-channel", "euclid", "http", - "image", + "image 0.24.9", "ipc-channel", "keyboard-types", "log", @@ -6553,7 +6702,7 @@ dependencies = [ "memmap2", "ndk", "ndk-sys", - "objc2", + "objc2 0.4.1", "once_cell", "orbclient", "percent-encoding", diff --git a/Cargo.toml b/Cargo.toml index 9d5d6919..4cd3947c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ crossbeam-channel = "0.5" getopts = "0.2.17" surfman = { version = "0.9", features = ["chains", "sm-angle-default", "sm-raw-window-handle"] } winit = { version = "0.29", features = ["rwh_05"] } +arboard = "3.4.0" [target."cfg(any(target_os = \"ios\", target_os = \"macos\"))".dependencies] block = "0.1" diff --git a/src/window.rs b/src/window.rs index c3161006..211757c3 100644 --- a/src/window.rs +++ b/src/window.rs @@ -33,6 +33,8 @@ use crate::{ Status, }; +use arboard::Clipboard; + /// A Verso window is a Winit window containing several web views. pub struct Window { /// Access to Winit window with webrender context. @@ -45,7 +47,10 @@ pub struct Window { webrender_gl: Rc, /// The mouse physical position in the web view. mouse_position: Cell>, + /// The current state of the keyboard modifiers. modifiers_state: Cell, + /// The clipboard. `None` if the platform or desktop environment is not support. + clipboard: Option, } impl Window { @@ -81,6 +86,11 @@ impl Window { webrender_gl, mouse_position: Cell::new(PhysicalPosition::default()), modifiers_state: Cell::new(ModifiersState::default()), + clipboard: Clipboard::new() + .map_err(|e| { + log::warn!("Failed to create clipboard: {}", e); + }) + .ok(), } } @@ -220,6 +230,34 @@ impl Window { ) -> bool { let mut need_present = false; servo.get_events().into_iter().for_each(|(w, m)| { + + // Window-wise events + match &m { + EmbedderMsg::GetClipboardContents(sender) => { + if let Some(clipboard) = self.clipboard.as_mut() { + let contents = clipboard.get_text().unwrap_or_else(|e| { + log::warn!("Failed to get clipboard content: {}", e); + String::new() + }); + if let Err(e) = sender.send(contents) { + log::warn!("Failed to send clipboard content: {}", e); + } + } else { + log::trace!("Clipboard is not supported on this platform."); + } + }, + EmbedderMsg::SetClipboardContents(text) => { + if let Some(clipboard) = self.clipboard.as_mut() { + if let Err(e) = clipboard.set_text(text) { + log::warn!("Failed to set clipboard contents: {}", e); + } + } else { + log::trace!("Clipboard is not supported on this platform."); + } + }, + _ => () + } + match w { // Handle message in Verso Panel Some(p) if p == self.panel.id() => {