diff --git a/src/client/objects.rs b/src/client/objects.rs index 5fade5f4..1ebd3ada 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -6,7 +6,8 @@ use { ext_image_capture_source_v1::ExtImageCaptureSourceV1, ext_image_copy::ext_image_copy_capture_session_v1::ExtImageCopyCaptureSessionV1, ipc::{ - wl_data_source::WlDataSource, zwlr_data_control_source_v1::ZwlrDataControlSourceV1, + data_control::zwlr_data_control_source_v1::ZwlrDataControlSourceV1, + wl_data_source::WlDataSource, zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, }, jay_output::JayOutput, diff --git a/src/compositor.rs b/src/compositor.rs index a466757b..a77d6170 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -274,6 +274,7 @@ fn start_compositor2( toplevels: Default::default(), const_40hz_latch: Default::default(), tray_item_ids: Default::default(), + data_control_device_ids: Default::default(), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/globals.rs b/src/globals.rs index 17357566..b541cb1e 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -10,8 +10,8 @@ use { ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1Global, ext_session_lock_manager_v1::ExtSessionLockManagerV1Global, ipc::{ + data_control::zwlr_data_control_manager_v1::ZwlrDataControlManagerV1Global, wl_data_device_manager::WlDataDeviceManagerGlobal, - zwlr_data_control_manager_v1::ZwlrDataControlManagerV1Global, zwp_primary_selection_device_manager_v1::ZwpPrimarySelectionDeviceManagerV1Global, }, jay_compositor::JayCompositorGlobal, diff --git a/src/ifs/ipc.rs b/src/ifs/ipc.rs index 3bb77ed8..ecd7686a 100644 --- a/src/ifs/ipc.rs +++ b/src/ifs/ipc.rs @@ -2,12 +2,7 @@ use { crate::{ client::{Client, ClientError, ClientId}, fixed::Fixed, - ifs::{ - ipc::{ - x_data_device::XIpcDevice, zwlr_data_control_device_v1::ZwlrDataControlDeviceV1, - }, - wl_seat::WlSeatGlobal, - }, + ifs::{ipc::x_data_device::XIpcDevice, wl_seat::WlSeatGlobal}, utils::{ bitflags::BitflagsExt, cell_ext::CellExt, clonecell::CloneCell, numcell::NumCell, smallmap::SmallMap, @@ -26,6 +21,7 @@ use { uapi::OwnedFd, }; +pub mod data_control; pub mod wl_data_device; pub mod wl_data_device_manager; pub mod wl_data_offer; @@ -33,10 +29,6 @@ pub mod wl_data_source; pub mod x_data_device; pub mod x_data_offer; pub mod x_data_source; -pub mod zwlr_data_control_device_v1; -pub mod zwlr_data_control_manager_v1; -pub mod zwlr_data_control_offer_v1; -pub mod zwlr_data_control_source_v1; pub mod zwp_primary_selection_device_manager_v1; pub mod zwp_primary_selection_device_v1; pub mod zwp_primary_selection_offer_v1; @@ -137,12 +129,6 @@ pub trait IterableIpcVtable: IpcVtable { C: FnMut(&Rc); } -pub trait WlrIpcVtable: IpcVtable { - fn for_each_device(seat: &WlSeatGlobal, f: C) - where - C: FnMut(&Rc); -} - pub trait IpcVtable: Sized { type Device; type Source: DataSource; @@ -360,9 +346,9 @@ where offer_source_to_device::(&src, dd, data, shared); } -pub fn offer_source_to_wlr_device(src: Rc, dd: &Rc) +pub fn offer_source_to_data_control_device(src: Rc, dd: &Rc) where - T: IpcVtable, + T: IpcVtable, { let data = src.source_data(); let shared = data.shared.get(); diff --git a/src/ifs/ipc/data_control.rs b/src/ifs/ipc/data_control.rs new file mode 100644 index 00000000..976f8a1d --- /dev/null +++ b/src/ifs/ipc/data_control.rs @@ -0,0 +1,21 @@ +use { + crate::ifs::ipc::{DynDataSource, IpcLocation}, + std::rc::Rc, +}; + +pub mod zwlr_data_control_device_v1; +pub mod zwlr_data_control_manager_v1; +pub mod zwlr_data_control_offer_v1; +pub mod zwlr_data_control_source_v1; + +linear_ids!(DataControlDeviceIds, DataControlDeviceId, u64); + +pub trait DynDataControlDevice { + fn id(&self) -> DataControlDeviceId; + + fn handle_new_source( + self: Rc, + location: IpcLocation, + source: Option>, + ); +} diff --git a/src/ifs/ipc/zwlr_data_control_device_v1.rs b/src/ifs/ipc/data_control/zwlr_data_control_device_v1.rs similarity index 80% rename from src/ifs/ipc/zwlr_data_control_device_v1.rs rename to src/ifs/ipc/data_control/zwlr_data_control_device_v1.rs index ecd5cf2f..4ab57159 100644 --- a/src/ifs/ipc/zwlr_data_control_device_v1.rs +++ b/src/ifs/ipc/data_control/zwlr_data_control_device_v1.rs @@ -3,13 +3,17 @@ use { client::{Client, ClientError}, ifs::{ ipc::{ - break_device_loops, destroy_data_device, - zwlr_data_control_device_v1::private::{ - WlrClipboardIpcCore, WlrIpcImpl, WlrPrimarySelectionIpcCore, + break_device_loops, + data_control::{ + zwlr_data_control_device_v1::private::{ + WlrClipboardIpcCore, WlrIpcImpl, WlrPrimarySelectionIpcCore, + }, + zwlr_data_control_offer_v1::ZwlrDataControlOfferV1, + zwlr_data_control_source_v1::ZwlrDataControlSourceV1, + DataControlDeviceId, DynDataControlDevice, }, - zwlr_data_control_offer_v1::ZwlrDataControlOfferV1, - zwlr_data_control_source_v1::ZwlrDataControlSourceV1, - DeviceData, IpcLocation, IpcVtable, OfferData, Role, WlrIpcVtable, + destroy_data_device, offer_source_to_data_control_device, DeviceData, + DynDataSource, IpcLocation, IpcVtable, OfferData, Role, }, wl_seat::{WlSeatError, WlSeatGlobal}, }, @@ -28,6 +32,7 @@ pub const PRIMARY_SELECTION_SINCE: Version = Version(2); pub struct ZwlrDataControlDeviceV1 { pub id: ZwlrDataControlDeviceV1Id, + pub data_control_device_id: DataControlDeviceId, pub client: Rc, pub version: Version, pub seat: Rc, @@ -45,6 +50,7 @@ impl ZwlrDataControlDeviceV1 { ) -> Self { Self { id, + data_control_device_id: client.state.data_control_device_ids.next(), client: client.clone(), version, seat: seat.clone(), @@ -111,7 +117,7 @@ impl ZwlrDataControlDeviceV1RequestHandler for ZwlrDataControlDeviceV1 { fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { destroy_data_device::(self); destroy_data_device::(self); - self.seat.remove_wlr_device(self); + self.seat.remove_data_control_device(self); self.client.remove_obj(self)?; Ok(()) } @@ -138,7 +144,6 @@ pub type WlrClipboardIpc = WlrIpcImpl; pub type WlrPrimarySelectionIpc = WlrIpcImpl; trait WlrIpc { - const MIN_VERSION: Version; const LOCATION: IpcLocation; fn wlr_get_device_data(dd: &ZwlrDataControlDeviceV1) -> &DeviceData; @@ -149,7 +154,6 @@ trait WlrIpc { } impl WlrIpc for WlrClipboardIpcCore { - const MIN_VERSION: Version = Version::ALL; const LOCATION: IpcLocation = IpcLocation::Clipboard; fn wlr_get_device_data(dd: &ZwlrDataControlDeviceV1) -> &DeviceData { @@ -169,7 +173,6 @@ impl WlrIpc for WlrClipboardIpcCore { } impl WlrIpc for WlrPrimarySelectionIpcCore { - const MIN_VERSION: Version = PRIMARY_SELECTION_SINCE; const LOCATION: IpcLocation = IpcLocation::PrimarySelection; fn wlr_get_device_data(dd: &ZwlrDataControlDeviceV1) -> &DeviceData { @@ -188,15 +191,6 @@ impl WlrIpc for WlrPrimarySelectionIpcCore { } } -impl WlrIpcVtable for WlrIpcImpl { - fn for_each_device(seat: &WlSeatGlobal, f: C) - where - C: FnMut(&Rc), - { - seat.for_each_wlr_data_device(T::MIN_VERSION, f) - } -} - impl IpcVtable for WlrIpcImpl { type Device = ZwlrDataControlDeviceV1; type Source = ZwlrDataControlSourceV1; @@ -245,6 +239,35 @@ impl IpcVtable for WlrIpcImpl { } } +impl DynDataControlDevice for ZwlrDataControlDeviceV1 { + fn id(&self) -> DataControlDeviceId { + self.data_control_device_id + } + + fn handle_new_source( + self: Rc, + location: IpcLocation, + source: Option>, + ) { + match location { + IpcLocation::Clipboard => match source { + Some(src) => offer_source_to_data_control_device::(src, &self), + _ => self.send_selection(None), + }, + IpcLocation::PrimarySelection => { + if self.version >= PRIMARY_SELECTION_SINCE { + match source { + Some(src) => offer_source_to_data_control_device::( + src, &self, + ), + _ => self.send_primary_selection(None), + } + } + } + } + } +} + object_base! { self = ZwlrDataControlDeviceV1; version = self.version; @@ -254,7 +277,7 @@ impl Object for ZwlrDataControlDeviceV1 { fn break_loops(&self) { break_device_loops::(self); break_device_loops::(self); - self.seat.remove_wlr_device(self); + self.seat.remove_data_control_device(self); } } diff --git a/src/ifs/ipc/zwlr_data_control_manager_v1.rs b/src/ifs/ipc/data_control/zwlr_data_control_manager_v1.rs similarity index 79% rename from src/ifs/ipc/zwlr_data_control_manager_v1.rs rename to src/ifs/ipc/data_control/zwlr_data_control_manager_v1.rs index 4959548e..8a43469a 100644 --- a/src/ifs/ipc/zwlr_data_control_manager_v1.rs +++ b/src/ifs/ipc/data_control/zwlr_data_control_manager_v1.rs @@ -3,12 +3,11 @@ use { client::{Client, ClientCaps, ClientError, CAP_DATA_CONTROL_MANAGER}, globals::{Global, GlobalName}, ifs::ipc::{ - offer_source_to_wlr_device, - zwlr_data_control_device_v1::{ - WlrClipboardIpc, WlrPrimarySelectionIpc, ZwlrDataControlDeviceV1, - PRIMARY_SELECTION_SINCE, + data_control::{ + zwlr_data_control_device_v1::ZwlrDataControlDeviceV1, + zwlr_data_control_source_v1::ZwlrDataControlSourceV1, DynDataControlDevice, }, - zwlr_data_control_source_v1::ZwlrDataControlSourceV1, + IpcLocation, }, leaks::Tracker, object::{Object, Version}, @@ -79,18 +78,14 @@ impl ZwlrDataControlManagerV1RequestHandler for ZwlrDataControlManagerV1 { &seat.global, )); track!(self.client, dev); - seat.global.add_wlr_device(&dev); + seat.global.add_data_control_device(dev.clone()); self.client.add_client_obj(&dev)?; - match seat.global.get_selection() { - Some(s) => offer_source_to_wlr_device::(s, &dev), - _ => dev.send_selection(None), - } - if self.version >= PRIMARY_SELECTION_SINCE { - match seat.global.get_primary_selection() { - Some(s) => offer_source_to_wlr_device::(s, &dev), - _ => dev.send_primary_selection(None), - } - } + dev.clone() + .handle_new_source(IpcLocation::Clipboard, seat.global.get_selection()); + dev.clone().handle_new_source( + IpcLocation::PrimarySelection, + seat.global.get_primary_selection(), + ); Ok(()) } diff --git a/src/ifs/ipc/zwlr_data_control_offer_v1.rs b/src/ifs/ipc/data_control/zwlr_data_control_offer_v1.rs similarity index 93% rename from src/ifs/ipc/zwlr_data_control_offer_v1.rs rename to src/ifs/ipc/data_control/zwlr_data_control_offer_v1.rs index 6307edc1..7c0f9197 100644 --- a/src/ifs/ipc/zwlr_data_control_offer_v1.rs +++ b/src/ifs/ipc/data_control/zwlr_data_control_offer_v1.rs @@ -3,11 +3,12 @@ use { client::{Client, ClientError, ClientId}, ifs::{ ipc::{ - break_offer_loops, cancel_offer, destroy_data_offer, receive_data_offer, - zwlr_data_control_device_v1::{ + break_offer_loops, cancel_offer, + data_control::zwlr_data_control_device_v1::{ WlrClipboardIpc, WlrPrimarySelectionIpc, ZwlrDataControlDeviceV1, }, - DataOffer, DataOfferId, DynDataOffer, IpcLocation, OfferData, + destroy_data_offer, receive_data_offer, DataOffer, DataOfferId, DynDataOffer, + IpcLocation, OfferData, }, wl_seat::WlSeatGlobal, }, diff --git a/src/ifs/ipc/zwlr_data_control_source_v1.rs b/src/ifs/ipc/data_control/zwlr_data_control_source_v1.rs similarity index 94% rename from src/ifs/ipc/zwlr_data_control_source_v1.rs rename to src/ifs/ipc/data_control/zwlr_data_control_source_v1.rs index 0cfef704..08488bd9 100644 --- a/src/ifs/ipc/zwlr_data_control_source_v1.rs +++ b/src/ifs/ipc/data_control/zwlr_data_control_source_v1.rs @@ -3,10 +3,12 @@ use { client::{Client, ClientError}, ifs::{ ipc::{ - add_data_source_mime_type, break_source_loops, cancel_offers, destroy_data_source, - detach_seat, offer_source_to_x, + add_data_source_mime_type, break_source_loops, cancel_offers, + data_control::zwlr_data_control_device_v1::{ + WlrClipboardIpc, WlrPrimarySelectionIpc, + }, + destroy_data_source, detach_seat, offer_source_to_x, x_data_device::{XClipboardIpc, XIpcDevice, XPrimarySelectionIpc}, - zwlr_data_control_device_v1::{WlrClipboardIpc, WlrPrimarySelectionIpc}, DataSource, DynDataSource, IpcLocation, SourceData, }, wl_seat::WlSeatGlobal, diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 0b88f732..96dd6b06 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -32,18 +32,17 @@ use { ifs::{ ext_idle_notification_v1::ExtIdleNotificationV1, ipc::{ - self, offer_source_to_regular_client, offer_source_to_wlr_device, + self, + data_control::{DataControlDeviceId, DynDataControlDevice}, + offer_source_to_regular_client, wl_data_device::{ClipboardIpc, WlDataDevice}, wl_data_source::WlDataSource, x_data_device::{XClipboardIpc, XIpcDevice, XIpcDeviceId, XPrimarySelectionIpc}, - zwlr_data_control_device_v1::{ - WlrClipboardIpc, WlrPrimarySelectionIpc, ZwlrDataControlDeviceV1, - }, zwp_primary_selection_device_v1::{ PrimarySelectionIpc, ZwpPrimarySelectionDeviceV1, }, zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, - DynDataSource, IpcError, + DynDataSource, IpcError, IpcLocation, }, wl_output::WlOutputGlobal, wl_seat::{ @@ -88,8 +87,8 @@ use { }, wire::{ wl_seat::*, ExtIdleNotificationV1Id, WlDataDeviceId, WlKeyboardId, WlPointerId, - WlSeatId, WlTouchId, XdgPopupId, ZwlrDataControlDeviceV1Id, - ZwpPrimarySelectionDeviceV1Id, ZwpRelativePointerV1Id, ZwpTextInputV3Id, + WlSeatId, WlTouchId, XdgPopupId, ZwpPrimarySelectionDeviceV1Id, ZwpRelativePointerV1Id, + ZwpTextInputV3Id, }, wire_ei::EiSeatId, xkbcommon::{DynKeyboardState, KeyboardState, KeymapId, XkbKeymap, XkbState}, @@ -167,8 +166,7 @@ pub struct WlSeatGlobal { AHashMap>, >, >, - wlr_data_devices: - CopyHashMap<(ClientId, ZwlrDataControlDeviceV1Id), Rc>, + data_control_devices: CopyHashMap>, repeat_rate: Cell<(i32, i32)>, seat_kb_map: CloneCell>, seat_xkb_state: CloneCell>>, @@ -267,7 +265,7 @@ impl WlSeatGlobal { constraint: Default::default(), idle_notifications: Default::default(), last_input_usec: Cell::new(state.now_usec()), - wlr_data_devices: Default::default(), + data_control_devices: Default::default(), text_inputs: Default::default(), text_input: Default::default(), input_method: Default::default(), @@ -383,13 +381,12 @@ impl WlSeatGlobal { } } - pub fn add_wlr_device(&self, device: &Rc) { - self.wlr_data_devices - .set((device.client.id, device.id), device.clone()); + pub fn add_data_control_device(&self, device: Rc) { + self.data_control_devices.set(device.id(), device.clone()); } - pub fn remove_wlr_device(&self, device: &ZwlrDataControlDeviceV1) { - self.wlr_data_devices.remove(&(device.client.id, device.id)); + pub fn remove_data_control_device(&self, device: &dyn DynDataControlDevice) { + self.data_control_devices.remove(&device.id()); } pub fn get_output(&self) -> Rc { @@ -711,15 +708,15 @@ impl WlSeatGlobal { } } - fn set_selection_( + fn set_selection_( self: &Rc, field: &CloneCell>>, src: Option>, + location: IpcLocation, ) -> Result<(), WlSeatError> where T: ipc::IterableIpcVtable, X: ipc::IpcVtable, - W: ipc::WlrIpcVtable, S: DynDataSource, { if let (Some(new), Some(old)) = (&src, &field.get()) { @@ -738,10 +735,10 @@ impl WlSeatGlobal { self.offer_selection_to_client::(src.clone().map(|v| v as Rc<_>), &client); // client.flush(); } - W::for_each_device(self, |device| match &src { - Some(src) => offer_source_to_wlr_device::(src.clone(), device), - _ => W::send_selection(device, None), - }); + let dyn_source = src.map(|s| s as Rc); + for dd in self.data_control_devices.lock().values() { + dd.clone().handle_new_source(location, dyn_source.clone()); + } Ok(()) } @@ -825,9 +822,10 @@ impl WlSeatGlobal { self: &Rc, selection: Option>, ) -> Result<(), WlSeatError> { - self.set_selection_::( + self.set_selection_::( &self.selection, selection, + IpcLocation::Clipboard, ) } @@ -871,9 +869,10 @@ impl WlSeatGlobal { self: &Rc, selection: Option>, ) -> Result<(), WlSeatError> { - self.set_selection_::( + self.set_selection_::( &self.primary_selection, selection, + IpcLocation::PrimarySelection, ) } @@ -910,7 +909,7 @@ impl WlSeatGlobal { self.bindings.borrow_mut().clear(); self.data_devices.borrow_mut().clear(); self.primary_selection_devices.borrow_mut().clear(); - self.wlr_data_devices.clear(); + self.data_control_devices.clear(); self.cursor_user_group.detach(); self.selection.set(None); self.primary_selection.set(None); diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 54a7407e..159dd676 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -12,7 +12,6 @@ use { offer_source_to_regular_client, wl_data_device::{ClipboardIpc, WlDataDevice}, x_data_device::{XClipboardIpc, XPrimarySelectionIpc}, - zwlr_data_control_device_v1::ZwlrDataControlDeviceV1, zwp_primary_selection_device_v1::{ PrimarySelectionIpc, ZwpPrimarySelectionDeviceV1, }, @@ -1037,17 +1036,6 @@ impl WlSeatGlobal { } } - pub fn for_each_wlr_data_device(&self, ver: Version, mut f: C) - where - C: FnMut(&Rc), - { - for dd in self.wlr_data_devices.lock().values() { - if dd.version >= ver { - f(dd); - } - } - } - fn surface_pointer_frame(&self, surface: &WlSurface) { self.surface_pointer_event(POINTER_FRAME_SINCE_VERSION, surface, |p| p.send_frame()); } diff --git a/src/state.rs b/src/state.rs index 142a9531..6a958b72 100644 --- a/src/state.rs +++ b/src/state.rs @@ -35,7 +35,10 @@ use { ifs::{ ext_foreign_toplevel_list_v1::ExtForeignToplevelListV1, ext_session_lock_v1::ExtSessionLockV1, - ipc::{x_data_device::XIpcDeviceIds, DataOfferIds, DataSourceIds}, + ipc::{ + data_control::DataControlDeviceIds, x_data_device::XIpcDeviceIds, DataOfferIds, + DataSourceIds, + }, jay_render_ctx::JayRenderCtx, jay_screencast::JayScreencast, jay_seat_events::JaySeatEvents, @@ -224,6 +227,7 @@ pub struct State { pub toplevels: CopyHashMap>, pub const_40hz_latch: EventSource, pub tray_item_ids: TrayItemIds, + pub data_control_device_ids: DataControlDeviceIds, } // impl Drop for State {