Skip to content

Commit

Permalink
wlr_data_control: use primary-selection filter
Browse files Browse the repository at this point in the history
  • Loading branch information
notpeelz authored and Drakulix committed Jan 23, 2025
1 parent db50f52 commit 7a4c803
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 17 deletions.
21 changes: 17 additions & 4 deletions src/wayland/selection/primary_selection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
use std::{
cell::{Ref, RefCell},
os::unix::io::OwnedFd,
sync::Arc,
};

use tracing::instrument;
Expand Down Expand Up @@ -94,9 +95,17 @@ pub trait PrimarySelectionHandler: Sized + SeatHandler + SelectionHandler {
}

/// State of the primary selection.
#[derive(Debug)]
pub struct PrimarySelectionState {
manager_global: GlobalId,
pub(super) filter: Arc<Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>>,
}

impl std::fmt::Debug for PrimarySelectionState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PrimarySelectionState")
.field("manager_global", &self.manager_global)
.finish()
}
}

impl PrimarySelectionState {
Expand All @@ -119,11 +128,15 @@ impl PrimarySelectionState {
F: for<'c> Fn(&'c Client) -> bool + Send + Sync + 'static,
{
let data = PrimaryDeviceManagerGlobalData {
filter: Box::new(filter),
filter: Arc::new(Box::new(filter)),
};
let filter = Arc::clone(&data.filter);
let manager_global = display.create_global::<D, PrimaryDeviceManager, _>(1, data);

Self { manager_global }
Self {
manager_global,
filter,
}
}

/// [`PrimaryDeviceManager`] GlobalId getter
Expand All @@ -135,7 +148,7 @@ impl PrimarySelectionState {
#[allow(missing_debug_implementations)]
#[doc(hidden)]
pub struct PrimaryDeviceManagerGlobalData {
filter: Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>,
filter: Arc<Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>>,
}

/// Set the primary selection focus to a certain client for a given seat
Expand Down
9 changes: 5 additions & 4 deletions src/wayland/selection/wlr_data_control/device.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::sync::Arc;

use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_device_v1::{
self, ZwlrDataControlDeviceV1,
Expand All @@ -15,10 +16,10 @@ use crate::wayland::selection::{SelectionSource, SelectionTarget};

use super::{DataControlHandler, DataControlState};

#[allow(missing_debug_implementations)]
#[doc(hidden)]
#[derive(Debug)]
pub struct DataControlDeviceUserData {
pub(crate) primary: bool,
pub(crate) primary_selection_filter: Arc<Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>>,
pub(crate) wl_seat: WlSeat,
}

Expand All @@ -30,7 +31,7 @@ where
{
fn request(
handler: &mut D,
_client: &Client,
client: &Client,
resource: &ZwlrDataControlDeviceV1,
request: <ZwlrDataControlDeviceV1 as wayland_server::Resource>::Request,
data: &DataControlDeviceUserData,
Expand Down Expand Up @@ -63,7 +64,7 @@ where
}
zwlr_data_control_device_v1::Request::SetPrimarySelection { source, .. } => {
// When the primary selection is disabled, we should simply ignore the requests.
if !data.primary {
if !(*data.primary_selection_filter)(client) {
return;
}

Expand Down
24 changes: 15 additions & 9 deletions src/wayland/selection/wlr_data_control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
//! Be aware that data control clients rely on other selection providers to be implemneted, like
//! wl_data_device or zwp_primary_selection.
use std::sync::Arc;

use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_manager_v1::ZwlrDataControlManagerV1;
use wayland_server::backend::GlobalId;
use wayland_server::{Client, DisplayHandle, GlobalDispatch};
Expand Down Expand Up @@ -86,7 +88,9 @@ impl DataControlState {
F: for<'c> Fn(&'c Client) -> bool + Send + Sync + 'static,
{
let data = DataControlManagerGlobalData {
primary: primary_selection.is_some(),
primary_selection_filter: primary_selection
.map(|x| Arc::clone(&x.filter))
.unwrap_or_else(|| Arc::new(Box::new(|_| false))),
filter: Box::new(filter),
};
let manager_global = display.create_global::<D, ZwlrDataControlManagerV1, _>(2, data);
Expand All @@ -102,22 +106,24 @@ impl DataControlState {
#[allow(missing_debug_implementations)]
#[doc(hidden)]
pub struct DataControlManagerGlobalData {
/// Whether to allow primary selection.
primary: bool,
/// Filter whether the clients can read/modify the primary selection.
primary_selection_filter: Arc<Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>>,

/// Filter whether the clients can view global.
filter: Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>,
}

#[allow(missing_debug_implementations)]
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
#[derive(Clone)]
pub struct DataControlManagerUserData {
/// Whether to allow primary selection.
primary: bool,
/// Filter whether the clients can read/modify the primary selection.
primary_selection_filter: Arc<Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>>,
}

mod handlers {
use std::cell::RefCell;
use std::sync::Arc;

use tracing::error;
use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_device_v1::ZwlrDataControlDeviceV1;
Expand Down Expand Up @@ -158,7 +164,7 @@ mod handlers {
data_init.init(
resource,
DataControlManagerUserData {
primary: global_data.primary,
primary_selection_filter: Arc::clone(&global_data.primary_selection_filter),
},
);
}
Expand Down Expand Up @@ -199,7 +205,7 @@ mod handlers {
id,
DataControlDeviceUserData {
wl_seat,
primary: data.primary,
primary_selection_filter: Arc::clone(&data.primary_selection_filter),
},
));

Expand All @@ -214,7 +220,7 @@ mod handlers {
// NOTE: broadcast selection only to the newly created device.
let device = Some(&device);
seat_data.send_selection::<D>(dh, SelectionTarget::Clipboard, device, true);
if data.primary {
if (*data.primary_selection_filter)(client) {
seat_data.send_selection::<D>(dh, SelectionTarget::Primary, device, true);
}
}
Expand Down

0 comments on commit 7a4c803

Please sign in to comment.