Skip to content

Commit

Permalink
wayland: Add support for the wp_primary_selection protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakulix committed Jul 19, 2022
1 parent 38d41e4 commit 6be9a9c
Show file tree
Hide file tree
Showing 6 changed files with 712 additions and 6 deletions.
26 changes: 20 additions & 6 deletions anvil/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use std::{
};

use smithay::{
delegate_compositor, delegate_data_device, delegate_layer_shell, delegate_output, delegate_seat,
delegate_shm, delegate_tablet_manager, delegate_viewporter, delegate_xdg_activation,
delegate_xdg_decoration, delegate_xdg_shell,
delegate_compositor, delegate_data_device, delegate_layer_shell, delegate_output,
delegate_primary_selection, delegate_seat, delegate_shm, delegate_tablet_manager, delegate_viewporter,
delegate_xdg_activation, delegate_xdg_decoration, delegate_xdg_shell,
desktop::{PopupManager, Space, WindowSurfaceType},
reexports::{
calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
Expand All @@ -27,6 +27,7 @@ use smithay::{
ServerDndGrabHandler,
},
output::{Output, OutputManagerState},
primary_selection::{set_primary_focus, PrimarySelectionHandler, PrimarySelectionState},
seat::{CursorImageStatus, Seat, SeatHandler, SeatState, XkbConfig},
shell::{
wlr_layer::WlrLayerShellState,
Expand Down Expand Up @@ -80,6 +81,7 @@ pub struct AnvilState<BackendData: 'static> {
pub data_device_state: DataDeviceState,
pub layer_shell_state: WlrLayerShellState,
pub output_manager_state: OutputManagerState,
pub primary_selection_state: PrimarySelectionState,
pub seat_state: SeatState<AnvilState<BackendData>>,
pub shm_state: ShmState,
pub viewporter_state: ViewporterState,
Expand Down Expand Up @@ -128,8 +130,16 @@ impl<BackendData> ServerDndGrabHandler for AnvilState<BackendData> {
}
}
delegate_data_device!(@<BackendData: 'static> AnvilState<BackendData>);

delegate_output!(@<BackendData: 'static> AnvilState<BackendData>);

impl<BackendData> PrimarySelectionHandler for AnvilState<BackendData> {
fn primary_selection_state(&self) -> &PrimarySelectionState {
&self.primary_selection_state
}
}
delegate_primary_selection!(@<BackendData: 'static> AnvilState<BackendData>);

impl<BackendData> ShmHandler for AnvilState<BackendData> {
fn shm_state(&self) -> &ShmState {
&self.shm_state
Expand Down Expand Up @@ -247,6 +257,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
let data_device_state = DataDeviceState::new::<Self, _>(&dh, log.clone());
let layer_shell_state = WlrLayerShellState::new::<Self, _>(&dh, log.clone());
let output_manager_state = OutputManagerState::new();
let primary_selection_state = PrimarySelectionState::new::<Self, _>(&dh, log.clone());
let seat_state = SeatState::new();
let shm_state = ShmState::new::<Self, _>(&dh, vec![], log.clone());
let viewporter_state = ViewporterState::new::<Self, _>(&dh, log.clone());
Expand All @@ -262,9 +273,11 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
let cursor_status2 = cursor_status.clone();
seat.add_pointer(move |new_status| *cursor_status2.lock().unwrap() = new_status);

seat.add_keyboard(XkbConfig::default(), 200, 25, move |seat, focus| {
let focus = focus.and_then(|s| dh.get_client(s.id()).ok());
set_data_device_focus(&dh, seat, focus)
seat.add_keyboard(XkbConfig::default(), 200, 25, move |seat, surface| {
let focus = surface.and_then(|s| dh.get_client(s.id()).ok());
let focus2 = surface.and_then(|s| dh.get_client(s.id()).ok());
set_data_device_focus(&dh, seat, focus);
set_primary_focus(&dh, seat, focus2);
})
.expect("Failed to initialize the keyboard");

Expand Down Expand Up @@ -303,6 +316,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
data_device_state,
layer_shell_state,
output_manager_state,
primary_selection_state,
seat_state,
shm_state,
viewporter_state,
Expand Down
1 change: 1 addition & 0 deletions src/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub mod compositor;
pub mod data_device;
pub mod dmabuf;
pub mod output;
pub mod primary_selection;
pub mod seat;
pub mod shell;
pub mod shm;
Expand Down
72 changes: 72 additions & 0 deletions src/wayland/primary_selection/device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::cell::RefCell;

use slog::debug;
use wayland_protocols::wp::primary_selection::zv1::server::zwp_primary_selection_device_v1::{
self as primary_device, ZwpPrimarySelectionDeviceV1 as PrimaryDevice,
};
use wayland_server::{protocol::wl_seat::WlSeat, Client, DataInit, Dispatch, DisplayHandle, Resource};

use crate::wayland::{
primary_selection::seat_data::{SeatData, Selection},
seat::Seat,
};

use super::{PrimarySelectionHandler, PrimarySelectionState};

#[doc(hidden)]
#[derive(Debug)]
pub struct PrimaryDeviceUserData {
pub(crate) wl_seat: WlSeat,
}

impl<D> Dispatch<PrimaryDevice, PrimaryDeviceUserData, D> for PrimarySelectionState
where
D: Dispatch<PrimaryDevice, PrimaryDeviceUserData>,
D: PrimarySelectionHandler,
D: 'static,
{
fn request(
handler: &mut D,
_client: &Client,
resource: &PrimaryDevice,
request: primary_device::Request,
data: &PrimaryDeviceUserData,
dh: &DisplayHandle,
_data_init: &mut DataInit<'_, D>,
) {
let primary_selection_state = handler.primary_selection_state();

if let Some(seat) = Seat::<D>::from_resource(&data.wl_seat) {
match request {
primary_device::Request::SetSelection { source, .. } => {
if let Some(keyboard) = seat.get_keyboard() {
if keyboard.client_of_object_has_focus(&resource.id()) {
let seat_data = seat.user_data().get::<RefCell<SeatData>>().unwrap();

PrimarySelectionHandler::new_selection(handler, dh, source.clone());
// The client has kbd focus, it can set the selection
seat_data.borrow_mut().set_selection::<D>(
dh,
source.map(Selection::Client).unwrap_or(Selection::Empty),
);
return;
}
}
debug!(
&primary_selection_state.log,
"denying setting selection by a non-focused client"
);
}
primary_device::Request::Destroy => {
// Clean up the known devices
seat.user_data()
.get::<RefCell<SeatData>>()
.unwrap()
.borrow_mut()
.retain_devices(|ndd| ndd != resource)
}
_ => unreachable!(),
}
}
}
}
Loading

0 comments on commit 6be9a9c

Please sign in to comment.