diff --git a/Cargo.lock b/Cargo.lock index b4a296c1..79256024 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -736,6 +736,12 @@ dependencies = [ "serde", ] +[[package]] +name = "cursor-icon" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740bb192a8e2d1350119916954f4409ee7f62f149b536911eeb78ba5a20526bf" + [[package]] name = "d3d12" version = "0.6.0" @@ -1030,69 +1036,14 @@ dependencies = [ ] [[package]] -name = "encoding" -version = "0.2.33" +name = "encoding_rs" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", + "cfg-if", ] -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - [[package]] name = "enum-map" version = "2.6.3" @@ -3945,7 +3896,7 @@ checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=74ef59a3f#74ef59a3f8b6a1f86a74388590f2f852040354e4" +source = "git+https://github.com/smithay//smithay?rev=d60b1b83e#d60b1b83e71ae73aecad799025e3ea30e844c229" dependencies = [ "appendlist", "ash", @@ -3953,11 +3904,12 @@ dependencies = [ "calloop 0.12.2", "cc", "cgmath", + "cursor-icon", "downcast-rs", "drm", "drm-ffi", "drm-fourcc", - "encoding", + "encoding_rs", "gbm", "gl_generator", "glow", diff --git a/Cargo.toml b/Cargo.toml index 2a394951..bcaf1e9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,7 +87,7 @@ debug = true lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = { git = "https://github.com/smithay//smithay", rev = "74ef59a3f" } +smithay = { git = "https://github.com/smithay//smithay", rev = "d60b1b83e" } [patch.crates-io] -calloop = { git = "https://github.com/Smithay/calloop", rev = "71b6e633b1" } \ No newline at end of file +calloop = { git = "https://github.com/Smithay/calloop", rev = "71b6e633b1" } diff --git a/src/backend/render/cursor.rs b/src/backend/render/cursor.rs index 6dff81d6..b80c51d2 100644 --- a/src/backend/render/cursor.rs +++ b/src/backend/render/cursor.rs @@ -283,16 +283,17 @@ where let mut cursor_status = cell.borrow_mut(); if let CursorImageStatus::Surface(ref surface) = *cursor_status { if !surface.alive() { - *cursor_status = CursorImageStatus::Default; + *cursor_status = CursorImageStatus::default_named(); } } cursor_status.clone() }) - .unwrap_or(CursorImageStatus::Default); + .unwrap_or(CursorImageStatus::default_named()); if let CursorImageStatus::Surface(ref wl_surface) = cursor_status { return draw_surface_cursor(renderer, wl_surface, location.to_i32_round(), scale); - } else if draw_default && CursorImageStatus::Default == cursor_status { + // TODO: Handle other named cursors + } else if draw_default && CursorImageStatus::default_named() == cursor_status { let integer_scale = scale.x.max(scale.y).ceil() as u32; let seat_userdata = seat.user_data(); diff --git a/src/input/mod.rs b/src/input/mod.rs index 80764218..41e1a864 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -180,7 +180,7 @@ pub fn add_seat( userdata.insert_if_missing(SeatMoveGrabState::default); userdata.insert_if_missing(CursorState::default); userdata.insert_if_missing(|| ActiveOutput(RefCell::new(output.clone()))); - userdata.insert_if_missing(|| RefCell::new(CursorImageStatus::Default)); + userdata.insert_if_missing(|| RefCell::new(CursorImageStatus::default_named())); // A lot of clients bind keyboard and pointer unconditionally once on launch.. // Initial clients might race the compositor on adding periheral and diff --git a/src/state.rs b/src/state.rs index e4052048..8d4feeba 100644 --- a/src/state.rs +++ b/src/state.rs @@ -60,7 +60,6 @@ use smithay::{ utils::{Clock, IsAlive, Monotonic}, wayland::{ compositor::{CompositorClientState, CompositorState}, - data_device::DataDeviceState, dmabuf::{DmabufFeedback, DmabufState}, fractional_scale::{with_fractional_scale, FractionalScaleManagerState}, keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, @@ -68,9 +67,9 @@ use smithay::{ pointer_constraints::PointerConstraintsState, pointer_gestures::PointerGesturesState, presentation::PresentationState, - primary_selection::PrimarySelectionState, seat::WaylandFocus, security_context::{SecurityContext, SecurityContextState}, + selection::{data_device::DataDeviceState, primary_selection::PrimarySelectionState}, shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState}, shm::ShmState, viewporter::ViewporterState, @@ -465,12 +464,12 @@ impl Common { let mut cursor_status = cell.borrow_mut(); if let CursorImageStatus::Surface(ref surface) = *cursor_status { if !surface.alive() { - *cursor_status = CursorImageStatus::Default; + *cursor_status = CursorImageStatus::default_named(); } } cursor_status.clone() }) - .unwrap_or(CursorImageStatus::Default); + .unwrap_or(CursorImageStatus::default_named()); if let CursorImageStatus::Surface(wl_surface) = cursor_status { send_frames_surface_tree( diff --git a/src/utils/prelude.rs b/src/utils/prelude.rs index e4cac742..d5e8f42b 100644 --- a/src/utils/prelude.rs +++ b/src/utils/prelude.rs @@ -7,7 +7,7 @@ use crate::{ use smithay::{ desktop::utils::bbox_from_surface_tree, input::{ - pointer::{CursorImageAttributes, CursorImageStatus}, + pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus}, Seat, }, output::Output, @@ -86,12 +86,12 @@ impl SeatExt for Seat { let mut cursor_status = cell.borrow_mut(); if let CursorImageStatus::Surface(ref surface) = *cursor_status { if !surface.alive() { - *cursor_status = CursorImageStatus::Default; + *cursor_status = CursorImageStatus::default_named(); } } cursor_status.clone() }) - .unwrap_or(CursorImageStatus::Default); + .unwrap_or(CursorImageStatus::default_named()); match cursor_status { CursorImageStatus::Surface(surface) => { @@ -111,7 +111,7 @@ impl SeatExt for Seat { ); Some((buffer_geo, (hotspot.x, hotspot.y).into())) } - CursorImageStatus::Default => { + CursorImageStatus::Named(CursorIcon::Default) => { let seat_userdata = self.user_data(); seat_userdata.insert_if_missing(CursorState::default); let state = seat_userdata.get::().unwrap(); @@ -129,6 +129,10 @@ impl SeatExt for Seat { (frame.xhot as i32, frame.yhot as i32).into(), )) } + CursorImageStatus::Named(_) => { + // TODO: Handle for `cursor_shape_v1` protocol + None + } CursorImageStatus::Hidden => None, } } diff --git a/src/wayland/handlers/data_device.rs b/src/wayland/handlers/data_device.rs index 24703327..3590a35b 100644 --- a/src/wayland/handlers/data_device.rs +++ b/src/wayland/handlers/data_device.rs @@ -6,14 +6,11 @@ use smithay::{ input::Seat, reexports::wayland_server::protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface}, utils::IsAlive, - wayland::data_device::{ - with_source_metadata, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, - ServerDndGrabHandler, + wayland::selection::data_device::{ + ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, }, - xwayland::xwm::{SelectionType, XwmId}, }; -use std::{cell::RefCell, os::unix::io::OwnedFd}; -use tracing::warn; +use std::cell::RefCell; pub struct DnDIcon { surface: RefCell>, @@ -51,54 +48,9 @@ impl ClientDndGrabHandler for State { } impl ServerDndGrabHandler for State {} impl DataDeviceHandler for State { - type SelectionUserData = XwmId; - fn data_device_state(&self) -> &DataDeviceState { &self.common.data_device_state } - - fn new_selection(&mut self, source: Option, _seat: Seat) { - if let Some(state) = self.common.xwayland_state.as_mut() { - if let Some(xwm) = state.xwm.as_mut() { - if let Some(source) = &source { - if let Ok(Err(err)) = with_source_metadata(source, |metadata| { - xwm.new_selection( - SelectionType::Clipboard, - Some(metadata.mime_types.clone()), - ) - }) { - warn!(?err, "Failed to set Xwayland clipboard selection."); - } - } else if let Err(err) = xwm.new_selection(SelectionType::Clipboard, None) { - warn!(?err, "Failed to clear Xwayland clipboard selection."); - } - } - } - } - - fn send_selection( - &mut self, - mime_type: String, - fd: OwnedFd, - _seat: Seat, - _user_data: &Self::SelectionUserData, - ) { - if let Some(xwm) = self - .common - .xwayland_state - .as_mut() - .and_then(|xstate| xstate.xwm.as_mut()) - { - if let Err(err) = xwm.send_selection( - SelectionType::Clipboard, - mime_type, - fd, - self.common.event_loop_handle.clone(), - ) { - warn!(?err, "Failed to send clipboard (X11 -> Wayland)."); - } - } - } } delegate_data_device!(State); diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index 8107ec71..d1a301a0 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -18,6 +18,7 @@ pub mod relative_pointer; pub mod screencopy; pub mod seat; pub mod security_context; +pub mod selection; pub mod shm; pub mod toplevel_info; pub mod toplevel_management; diff --git a/src/wayland/handlers/primary_selection.rs b/src/wayland/handlers/primary_selection.rs index 763ead0c..255cff1b 100644 --- a/src/wayland/handlers/primary_selection.rs +++ b/src/wayland/handlers/primary_selection.rs @@ -3,58 +3,13 @@ use crate::state::State; use smithay::{ delegate_primary_selection, - wayland::primary_selection::{PrimarySelectionHandler, PrimarySelectionState, with_source_metadata}, xwayland::xwm::{XwmId, SelectionType}, reexports::wayland_protocols::wp::primary_selection::zv1::server::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, input::Seat, + wayland::selection::primary_selection::{PrimarySelectionHandler, PrimarySelectionState}, }; -use tracing::warn; - -use std::os::unix::io::OwnedFd; impl PrimarySelectionHandler for State { - type SelectionUserData = XwmId; - fn primary_selection_state(&self) -> &PrimarySelectionState { &self.common.primary_selection_state } - - fn new_selection(&mut self, source: Option, _seat: Seat) { - if let Some(state) = self.common.xwayland_state.as_mut() { - if let Some(xwm) = state.xwm.as_mut() { - if let Some(source) = &source { - if let Ok(Err(err)) = with_source_metadata(source, |metadata| { - xwm.new_selection(SelectionType::Primary, Some(metadata.mime_types.clone())) - }) { - warn!(?err, "Failed to set Xwayland primary selection"); - } - } else if let Err(err) = xwm.new_selection(SelectionType::Primary, None) { - warn!(?err, "Failed to clear Xwayland primary selection"); - } - } - } - } - - fn send_selection( - &mut self, - mime_type: String, - fd: OwnedFd, - _seat: Seat, - _user_data: &Self::SelectionUserData, - ) { - if let Some(xwm) = self - .common - .xwayland_state - .as_mut() - .and_then(|xstate| xstate.xwm.as_mut()) - { - if let Err(err) = xwm.send_selection( - SelectionType::Primary, - mime_type, - fd, - self.common.event_loop_handle.clone(), - ) { - warn!(?err, "Failed to send primary selection (X11 -> Wayland)."); - } - } - } } delegate_primary_selection!(State); diff --git a/src/wayland/handlers/seat.rs b/src/wayland/handlers/seat.rs index 1af64bb7..929c92cb 100644 --- a/src/wayland/handlers/seat.rs +++ b/src/wayland/handlers/seat.rs @@ -9,8 +9,8 @@ use smithay::{ input::{pointer::CursorImageStatus, SeatHandler, SeatState}, reexports::wayland_server::Resource, wayland::{ - data_device::set_data_device_focus, primary_selection::set_primary_focus, - seat::WaylandFocus, + seat::WaylandFocus, selection::data_device::set_data_device_focus, + selection::primary_selection::set_primary_focus, }, }; use std::cell::RefCell; diff --git a/src/wayland/handlers/selection.rs b/src/wayland/handlers/selection.rs new file mode 100644 index 00000000..6d157a5f --- /dev/null +++ b/src/wayland/handlers/selection.rs @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use crate::state::State; +use smithay::{ + input::Seat, + wayland::selection::{SelectionHandler, SelectionSource, SelectionTarget}, + xwayland::xwm::XwmId, +}; +use std::os::unix::io::OwnedFd; +use tracing::warn; + +impl SelectionHandler for State { + type SelectionUserData = XwmId; + + fn new_selection( + &mut self, + target: SelectionTarget, + source: Option, + _seat: Seat, + ) { + if let Some(xwm) = self + .common + .xwayland_state + .as_mut() + .and_then(|xstate| xstate.xwm.as_mut()) + { + if let Some(source) = &source { + if let Err(err) = xwm.new_selection(target, Some(source.mime_types())) { + warn!(?err, "Failed to set Xwayland clipboard selection."); + } + } else if let Err(err) = xwm.new_selection(target, None) { + warn!(?err, "Failed to clear Xwayland selection."); + } + } + } + + fn send_selection( + &mut self, + target: SelectionTarget, + mime_type: String, + fd: OwnedFd, + _seat: Seat, + _user_data: &Self::SelectionUserData, + ) { + if let Some(xwm) = self + .common + .xwayland_state + .as_mut() + .and_then(|xstate| xstate.xwm.as_mut()) + { + if let Err(err) = + xwm.send_selection(target, mime_type, fd, self.common.event_loop_handle.clone()) + { + warn!(?err, "Failed to send selection (X11 -> Wayland)."); + } + } + } +} diff --git a/src/xwayland.rs b/src/xwayland.rs index cc3b6d52..541c2960 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -12,7 +12,7 @@ use smithay::{ desktop::space::SpaceElement, reexports::x11rb::protocol::xproto::Window as X11Window, utils::{Logical, Point, Rectangle, Size}, - wayland::{ + wayland::selection::{ data_device::{ clear_data_device_selection, current_data_device_selection_userdata, request_data_device_client_selection, set_data_device_selection, @@ -21,9 +21,10 @@ use smithay::{ clear_primary_selection, current_primary_selection_userdata, request_primary_client_selection, set_primary_selection, }, + SelectionTarget, }, xwayland::{ - xwm::{Reorder, SelectionType, XwmId}, + xwm::{Reorder, XwmId}, X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler, }, }; @@ -411,13 +412,13 @@ impl XwmHandler for State { fn send_selection( &mut self, _xwm: XwmId, - selection: SelectionType, + selection: SelectionTarget, mime_type: String, fd: OwnedFd, ) { let seat = self.common.last_active_seat(); match selection { - SelectionType::Clipboard => { + SelectionTarget::Clipboard => { if let Err(err) = request_data_device_client_selection(seat, mime_type, fd) { error!( ?err, @@ -425,7 +426,7 @@ impl XwmHandler for State { ); } } - SelectionType::Primary => { + SelectionTarget::Primary => { if let Err(err) = request_primary_client_selection(seat, mime_type, fd) { error!( ?err, @@ -436,35 +437,35 @@ impl XwmHandler for State { } } - fn allow_selection_access(&mut self, xwm: XwmId, _selection: SelectionType) -> bool { + fn allow_selection_access(&mut self, xwm: XwmId, _selection: SelectionTarget) -> bool { self.common.is_x_focused(xwm) } - fn new_selection(&mut self, xwm: XwmId, selection: SelectionType, mime_types: Vec) { + fn new_selection(&mut self, xwm: XwmId, selection: SelectionTarget, mime_types: Vec) { trace!(?selection, ?mime_types, "Got Selection from Xwayland",); if self.common.is_x_focused(xwm) { let seat = self.common.last_active_seat(); match selection { - SelectionType::Clipboard => { + SelectionTarget::Clipboard => { set_data_device_selection(&self.common.display_handle, &seat, mime_types, xwm) } - SelectionType::Primary => { + SelectionTarget::Primary => { set_primary_selection(&self.common.display_handle, &seat, mime_types, xwm) } } } } - fn cleared_selection(&mut self, xwm: XwmId, selection: SelectionType) { + fn cleared_selection(&mut self, xwm: XwmId, selection: SelectionTarget) { for seat in self.common.seats() { match selection { - SelectionType::Clipboard => { + SelectionTarget::Clipboard => { if current_data_device_selection_userdata(seat).as_deref() == Some(&xwm) { clear_data_device_selection(&self.common.display_handle, seat) } } - SelectionType::Primary => { + SelectionTarget::Primary => { if current_primary_selection_userdata(seat).as_deref() == Some(&xwm) { clear_primary_selection(&self.common.display_handle, seat) }