linux: clipboard (#8822)
Linux clipboard implementation with `copypasta`. Release Notes: - Added linux clipboard support
This commit is contained in:
parent
33ef5b7731
commit
996f1036fc
6 changed files with 216 additions and 9 deletions
|
@ -1,5 +1,8 @@
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use copypasta::ClipboardProvider;
|
||||
|
||||
use crate::platform::PlatformWindow;
|
||||
use crate::{AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, WindowOptions};
|
||||
|
||||
|
@ -12,4 +15,6 @@ pub trait Client {
|
|||
options: WindowOptions,
|
||||
) -> Box<dyn PlatformWindow>;
|
||||
fn set_cursor_style(&self, style: CursorStyle);
|
||||
fn get_clipboard(&self) -> Rc<RefCell<dyn ClipboardProvider>>;
|
||||
fn get_primary(&self) -> Rc<RefCell<dyn ClipboardProvider>>;
|
||||
}
|
||||
|
|
|
@ -354,12 +354,21 @@ impl Platform for LinuxPlatform {
|
|||
false
|
||||
}
|
||||
|
||||
// todo(linux)
|
||||
fn write_to_clipboard(&self, item: ClipboardItem) {}
|
||||
fn write_to_clipboard(&self, item: ClipboardItem) {
|
||||
let clipboard = self.client.get_clipboard();
|
||||
clipboard.borrow_mut().set_contents(item.text);
|
||||
}
|
||||
|
||||
// todo(linux)
|
||||
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
||||
None
|
||||
let clipboard = self.client.get_clipboard();
|
||||
let contents = clipboard.borrow_mut().get_contents();
|
||||
match contents {
|
||||
Ok(text) => Some(ClipboardItem {
|
||||
metadata: None,
|
||||
text,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
//todo!(linux)
|
||||
|
@ -382,6 +391,8 @@ impl Platform for LinuxPlatform {
|
|||
})
|
||||
}
|
||||
|
||||
//todo!(linux): add trait methods for accessing the primary selection
|
||||
|
||||
//todo!(linux)
|
||||
fn read_credentials(&self, url: &str) -> Task<Result<Option<(String, Vec<u8>)>>> {
|
||||
let url = url.to_string();
|
||||
|
|
|
@ -6,6 +6,8 @@ use std::time::Duration;
|
|||
use calloop::timer::{TimeoutAction, Timer};
|
||||
use calloop::LoopHandle;
|
||||
use calloop_wayland_source::WaylandSource;
|
||||
use copypasta::wayland_clipboard::{create_clipboards_from_external, Clipboard, Primary};
|
||||
use copypasta::ClipboardProvider;
|
||||
use wayland_backend::client::ObjectId;
|
||||
use wayland_backend::protocol::WEnum;
|
||||
use wayland_client::globals::{registry_queue_init, GlobalListContents};
|
||||
|
@ -74,6 +76,8 @@ pub(crate) struct CursorState {
|
|||
pub(crate) struct WaylandClientState {
|
||||
client_state_inner: Rc<RefCell<WaylandClientStateInner>>,
|
||||
cursor_state: Rc<RefCell<CursorState>>,
|
||||
clipboard: Rc<RefCell<Clipboard>>,
|
||||
primary: Rc<RefCell<Primary>>,
|
||||
}
|
||||
|
||||
pub(crate) struct KeyRepeat {
|
||||
|
@ -111,6 +115,9 @@ impl WaylandClient {
|
|||
}
|
||||
});
|
||||
|
||||
let display = conn.backend().display_ptr() as *mut std::ffi::c_void;
|
||||
let (primary, clipboard) = unsafe { create_clipboards_from_external(display) };
|
||||
|
||||
let mut state_inner = Rc::new(RefCell::new(WaylandClientStateInner {
|
||||
compositor: globals.bind(&qh, 1..=1, ()).unwrap(),
|
||||
wm_base: globals.bind(&qh, 1..=1, ()).unwrap(),
|
||||
|
@ -152,20 +159,20 @@ impl WaylandClient {
|
|||
let mut state = WaylandClientState {
|
||||
client_state_inner: Rc::clone(&state_inner),
|
||||
cursor_state: Rc::clone(&cursor_state),
|
||||
clipboard: Rc::new(RefCell::new(clipboard)),
|
||||
primary: Rc::new(RefCell::new(primary)),
|
||||
};
|
||||
let mut state_loop = state.clone();
|
||||
linux_platform_inner
|
||||
.loop_handle
|
||||
.insert_source(source, move |_, queue, _| {
|
||||
queue.dispatch_pending(&mut state)
|
||||
queue.dispatch_pending(&mut state_loop)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
platform_inner: linux_platform_inner,
|
||||
state: WaylandClientState {
|
||||
client_state_inner: state_inner,
|
||||
cursor_state,
|
||||
},
|
||||
state,
|
||||
qh: Arc::new(qh),
|
||||
}
|
||||
}
|
||||
|
@ -265,6 +272,14 @@ impl Client for WaylandClient {
|
|||
let mut cursor_state = self.state.cursor_state.borrow_mut();
|
||||
cursor_state.cursor_icon_name = cursor_icon_name;
|
||||
}
|
||||
|
||||
fn get_clipboard(&self) -> Rc<RefCell<dyn ClipboardProvider>> {
|
||||
self.state.clipboard.clone()
|
||||
}
|
||||
|
||||
fn get_primary(&self) -> Rc<RefCell<dyn ClipboardProvider>> {
|
||||
self.state.primary.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for WaylandClientState {
|
||||
|
|
|
@ -6,6 +6,8 @@ use xcb::{x, Xid as _};
|
|||
use xkbcommon::xkb;
|
||||
|
||||
use collections::HashMap;
|
||||
use copypasta::x11_clipboard::{Clipboard, Primary, X11ClipboardContext};
|
||||
use copypasta::ClipboardProvider;
|
||||
|
||||
use crate::platform::linux::client::Client;
|
||||
use crate::platform::{LinuxPlatformInner, PlatformWindow};
|
||||
|
@ -28,6 +30,8 @@ struct WindowRef {
|
|||
struct X11ClientState {
|
||||
windows: HashMap<x::Window, WindowRef>,
|
||||
xkb: xkbcommon::xkb::State,
|
||||
clipboard: Rc<RefCell<X11ClipboardContext<Clipboard>>>,
|
||||
primary: Rc<RefCell<X11ClipboardContext<Primary>>>,
|
||||
}
|
||||
|
||||
pub(crate) struct X11Client {
|
||||
|
@ -70,6 +74,9 @@ impl X11Client {
|
|||
xkb::x11::state_new_from_device(&xkb_keymap, &xcb_connection, xkb_device_id)
|
||||
};
|
||||
|
||||
let clipboard = X11ClipboardContext::<Clipboard>::new().unwrap();
|
||||
let primary = X11ClipboardContext::<Primary>::new().unwrap();
|
||||
|
||||
let client: Rc<X11Client> = Rc::new(Self {
|
||||
platform_inner: inner.clone(),
|
||||
xcb_connection: Rc::clone(&xcb_connection),
|
||||
|
@ -78,6 +85,8 @@ impl X11Client {
|
|||
state: RefCell::new(X11ClientState {
|
||||
windows: HashMap::default(),
|
||||
xkb: xkb_state,
|
||||
clipboard: Rc::new(RefCell::new(clipboard)),
|
||||
primary: Rc::new(RefCell::new(primary)),
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -354,6 +363,14 @@ impl Client for X11Client {
|
|||
|
||||
//todo!(linux)
|
||||
fn set_cursor_style(&self, _style: CursorStyle) {}
|
||||
|
||||
fn get_clipboard(&self) -> Rc<RefCell<dyn ClipboardProvider>> {
|
||||
self.state.borrow().clipboard.clone()
|
||||
}
|
||||
|
||||
fn get_primary(&self) -> Rc<RefCell<dyn ClipboardProvider>> {
|
||||
self.state.borrow().primary.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// Adatpted from:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue