Update to SCTK 0.18.0
The main highlight is the move to calloop to handle all the requests which makes it possible to remove all the active polling and clean the data reading/writing, as well as accepting arbitrary long payloads. This update also fixes the CI for the repository by moving it to github actions, sets the minimum rust version, and edition to 2021. Fixes #46. Fixes #44. Fixes #34.
This commit is contained in:
parent
e2ffc4f183
commit
31392200dc
15 changed files with 1124 additions and 937 deletions
104
src/worker.rs
Normal file
104
src/worker.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
use std::io::{Error, ErrorKind, Result};
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use sctk::reexports::calloop::channel::Channel;
|
||||
use sctk::reexports::calloop::{channel, EventLoop};
|
||||
use sctk::reexports::calloop_wayland_source::WaylandSource;
|
||||
use sctk::reexports::client::globals::registry_queue_init;
|
||||
use sctk::reexports::client::Connection;
|
||||
|
||||
use crate::state::{SelectionTarget, State};
|
||||
|
||||
/// Spawn a clipboard worker, which dispatches its own `EventQueue` and handles
|
||||
/// clipboard requests.
|
||||
pub fn spawn(
|
||||
name: String,
|
||||
display: Connection,
|
||||
rx_chan: Channel<Command>,
|
||||
worker_replier: Sender<Result<String>>,
|
||||
) -> Option<std::thread::JoinHandle<()>> {
|
||||
std::thread::Builder::new()
|
||||
.name(name)
|
||||
.spawn(move || {
|
||||
worker_impl(display, rx_chan, worker_replier);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Clipboard worker thread command.
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum Command {
|
||||
/// Store data to a clipboard.
|
||||
Store(String),
|
||||
/// Store data to a primary selection.
|
||||
StorePrimary(String),
|
||||
/// Load data from a clipboard.
|
||||
Load,
|
||||
/// Load primary selection.
|
||||
LoadPrimary,
|
||||
/// Shutdown the worker.
|
||||
Exit,
|
||||
}
|
||||
|
||||
/// Handle clipboard requests.
|
||||
fn worker_impl(
|
||||
connection: Connection,
|
||||
rx_chan: Channel<Command>,
|
||||
reply_tx: Sender<Result<String>>,
|
||||
) {
|
||||
let (globals, event_queue) = match registry_queue_init(&connection) {
|
||||
Ok(data) => data,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let mut event_loop = EventLoop::<State>::try_new().unwrap();
|
||||
let loop_handle = event_loop.handle();
|
||||
|
||||
let mut state = match State::new(&globals, &event_queue.handle(), loop_handle.clone(), reply_tx)
|
||||
{
|
||||
Some(state) => state,
|
||||
None => return,
|
||||
};
|
||||
|
||||
loop_handle
|
||||
.insert_source(rx_chan, |event, _, state| {
|
||||
if let channel::Event::Msg(event) = event {
|
||||
match event {
|
||||
Command::StorePrimary(contents) => {
|
||||
state.store_selection(SelectionTarget::Primary, contents);
|
||||
},
|
||||
Command::Store(contents) => {
|
||||
state.store_selection(SelectionTarget::Clipboard, contents);
|
||||
},
|
||||
Command::Load if state.data_device_manager_state.is_some() => {
|
||||
if let Err(err) = state.load_selection(SelectionTarget::Clipboard) {
|
||||
let _ = state.reply_tx.send(Err(err));
|
||||
}
|
||||
},
|
||||
Command::LoadPrimary if state.data_device_manager_state.is_some() => {
|
||||
if let Err(err) = state.load_selection(SelectionTarget::Primary) {
|
||||
let _ = state.reply_tx.send(Err(err));
|
||||
}
|
||||
},
|
||||
Command::Load | Command::LoadPrimary => {
|
||||
let _ = state.reply_tx.send(Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"requested selection is not supported",
|
||||
)));
|
||||
},
|
||||
Command::Exit => state.exit = true,
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
WaylandSource::new(connection, event_queue).insert(loop_handle).unwrap();
|
||||
|
||||
loop {
|
||||
event_loop.dispatch(None, &mut state).unwrap();
|
||||
|
||||
if state.exit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue