Skip to content

Commit

Permalink
Implement wp_viewporter protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
maxhbooth committed Mar 5, 2025
1 parent 583ff24 commit 6e20ffd
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 4 deletions.
54 changes: 54 additions & 0 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::sync::OnceLock;

use bimap::BiMap;
use enum_as_inner::EnumAsInner;
use smithay::reexports::wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport;
use smithay::reexports::wayland_protocols::wp::viewporter::client::wp_viewporter::WpViewporter;
use smithay_client_toolkit::compositor::CompositorState;
use smithay_client_toolkit::compositor::Surface;
use smithay_client_toolkit::data_device_manager::data_offer::DragOffer;
Expand All @@ -41,6 +43,7 @@ use smithay_client_toolkit::reexports::client::Proxy;
use smithay_client_toolkit::reexports::client::QueueHandle;
use smithay_client_toolkit::reexports::protocols::xdg::shell::client::xdg_surface;
use smithay_client_toolkit::registry::RegistryState;
use smithay_client_toolkit::registry::SimpleGlobal;
use smithay_client_toolkit::seat::pointer::ThemedPointer;
use smithay_client_toolkit::seat::SeatState;
use smithay_client_toolkit::shell::xdg::XdgShell;
Expand All @@ -61,6 +64,7 @@ use crate::serialization::wayland::BufferAssignment;
use crate::serialization::wayland::BufferMetadata;
use crate::serialization::wayland::Region;
use crate::serialization::wayland::SubsurfacePosition;
use crate::serialization::wayland::ViewportState;
use crate::serialization::wayland::WlSurfaceId;
use crate::serialization::Capabilities;
use crate::serialization::ClientId;
Expand Down Expand Up @@ -112,6 +116,7 @@ pub struct WprsClientState {
subcompositor: WlSubcompositor,
shm_state: Shm,
xdg_shell_state: XdgShell,
wp_viewporter: Option<SimpleGlobal<WpViewporter, 1>>,

data_device_manager_state: DataDeviceManagerState,
primary_selection_manager_state: Option<PrimarySelectionManagerState>,
Expand Down Expand Up @@ -175,6 +180,10 @@ impl WprsClientState {
shm_state,
xdg_shell_state: XdgShell::bind(&globals, &qh)
.context(loc!(), "xdg shell is not available")?,
wp_viewporter: SimpleGlobal::<WpViewporter, 1>::bind(&globals, &qh)
.context(loc!(), "wp_viewporter is not available")
.warn(loc!())
.ok(),
data_device_manager_state: DataDeviceManagerState::bind(&globals, &qh)
.context(loc!(), "data device manager is not available")?,
primary_selection_manager_state: PrimarySelectionManagerState::bind(&globals, &qh)
Expand Down Expand Up @@ -338,6 +347,8 @@ pub struct RemoteSurface {
pub z_ordered_children: Vec<SubsurfacePosition>,
pub frame_callback_completed: bool,
pub frame_damage: Option<Vec<Rectangle<i32>>>,
pub viewport: Option<WpViewport>,
pub current_viewport_state: Option<ViewportState>,
}

impl RemoteSurface {
Expand Down Expand Up @@ -369,6 +380,8 @@ impl RemoteSurface {
}],
frame_callback_completed: true,
frame_damage: None,
viewport: None,
current_viewport_state: None,
})
}

Expand Down Expand Up @@ -559,6 +572,39 @@ impl RemoteSurface {
}
}

pub fn set_viewport_state(
&mut self,
viewport_state: Option<ViewportState>,
wp_viewporter: &Option<SimpleGlobal<WpViewporter, 1>>,
qh: &QueueHandle<WprsClientState>,
) {
let Some(wp_viewporter) = wp_viewporter else {
return;
};
let Ok(wp_viewporter) = wp_viewporter.get() else {
return;
};
let Some(viewport_state) = viewport_state else {
return;
};

let wl_surface = self.wl_surface().clone();
let viewport = self
.viewport
.get_or_insert_with(|| wp_viewporter.get_viewport(&wl_surface, qh, ()));

// skip if the viewport state hasn't changed
if self.current_viewport_state != Some(viewport_state) {
if let Some(src) = viewport_state.src {
viewport.set_source(src.loc.x, src.loc.y, src.size.w, src.size.h);
}
if let Some(dst) = viewport_state.dst {
viewport.set_destination(dst.w, dst.h);
}
self.current_viewport_state = Some(viewport_state);
}
}

pub fn set_input_region(
&mut self,
region: Option<Region>,
Expand Down Expand Up @@ -653,6 +699,14 @@ impl RemoteSurface {
}
}

impl Drop for RemoteSurface {
fn drop(&mut self) {
if let Some(viewport) = &self.viewport {
viewport.destroy();
}
}
}

#[derive(Debug)]
pub struct RemoteCursor {
// TODO: can we remove client?
Expand Down
6 changes: 6 additions & 0 deletions src/client/server_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ impl WprsClientState {
surface_state.buffer_transform.map(Into::into),
);

remote_surface.set_viewport_state(
surface_state.viewport_state,
&self.wp_viewporter,
&self.qh,
);

remote_surface
.set_input_region(surface_state.input_region.take(), &self.compositor_state)
.location(loc!())?;
Expand Down
25 changes: 25 additions & 0 deletions src/client/smithay_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
/// Handlers for events from smithay client toolkit.
use smithay::reexports::wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
use smithay::reexports::wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1;
use smithay::reexports::wayland_protocols::wp::viewporter::client::wp_viewport;
use smithay::reexports::wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport;
use smithay::reexports::wayland_protocols::wp::viewporter::client::wp_viewporter::WpViewporter;
use smithay_client_toolkit::compositor::CompositorHandler;
use smithay_client_toolkit::compositor::SurfaceData;
use smithay_client_toolkit::data_device_manager::data_device::DataDeviceHandler;
Expand Down Expand Up @@ -46,6 +49,7 @@ use smithay_client_toolkit::reexports::client::Proxy;
use smithay_client_toolkit::reexports::client::QueueHandle;
use smithay_client_toolkit::registry::ProvidesRegistryState;
use smithay_client_toolkit::registry::RegistryState;
use smithay_client_toolkit::registry::SimpleGlobal;
use smithay_client_toolkit::registry_handlers;
use smithay_client_toolkit::seat::keyboard::KeyEvent;
use smithay_client_toolkit::seat::keyboard::KeyboardHandler;
Expand Down Expand Up @@ -954,6 +958,13 @@ impl PrimarySelectionSourceHandler for WprsClientState {
}
}

impl AsMut<SimpleGlobal<WpViewporter, 1>> for WprsClientState {
fn as_mut(&mut self) -> &mut SimpleGlobal<WpViewporter, 1> {
// This should never panic since self.wp_viewporter is none then we will never get any events for it.
&mut *self.wp_viewporter.as_mut().unwrap()
}
}

smithay_client_toolkit::delegate_compositor!(WprsClientState);
smithay_client_toolkit::delegate_data_device!(WprsClientState);
smithay_client_toolkit::delegate_keyboard!(WprsClientState);
Expand All @@ -967,6 +978,7 @@ smithay_client_toolkit::delegate_xdg_popup!(WprsClientState);
smithay_client_toolkit::delegate_xdg_shell!(WprsClientState);
smithay_client_toolkit::delegate_xdg_window!(WprsClientState);
smithay_client_toolkit::delegate_primary_selection!(WprsClientState);
smithay_client_toolkit::delegate_simple!(WprsClientState, WpViewporter, 1);

impl ProvidesRegistryState for WprsClientState {
fn registry(&mut self) -> &mut RegistryState {
Expand Down Expand Up @@ -1004,3 +1016,16 @@ impl Dispatch<WlSubsurface, SubSurfaceData> for WprsClientState {
dbg!("SUBSURFACE DISPATCH");
}
}

impl Dispatch<WpViewport, ()> for WprsClientState {
fn event(
_state: &mut Self,
_viewport: &WpViewport,
_event: wp_viewport::Event,
_data: &(),
_conn: &Connection,
_qh: &QueueHandle<Self>,
) {
unreachable!("There are no wp_viewport events")
}
}
2 changes: 1 addition & 1 deletion src/serialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub struct Capabilities {

// TODO: https://github.com/rust-lang/rfcs/pull/2593 - simplify all the enums.

#[derive(Debug, Clone, Eq, PartialEq, Archive, Deserialize, Serialize)]
#[derive(Debug, Clone, PartialEq, Archive, Deserialize, Serialize)]
pub enum Request {
Surface(wayland::SurfaceRequest),
CursorImage(wayland::CursorImage),
Expand Down
24 changes: 21 additions & 3 deletions src/serialization/wayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use smithay::wayland::compositor::RectangleKind as SmithayRectangleKind;
use smithay::wayland::compositor::RegionAttributes;
use smithay::wayland::selection::data_device::SourceMetadata as SmithaySourceMetadata;
use smithay::wayland::shm::BufferData;
use smithay::wayland::viewporter::ViewportCachedState;
use smithay_client_toolkit::compositor::CompositorState;
use smithay_client_toolkit::compositor::Region as SctkRegion;
use smithay_client_toolkit::output::Mode as SctkMode;
Expand Down Expand Up @@ -664,7 +665,7 @@ pub struct SubsurfacePosition {
pub position: Point<i32>,
}

#[derive(Debug, Clone, Eq, PartialEq, Archive, Deserialize, Serialize)]
#[derive(Debug, Clone, PartialEq, Archive, Deserialize, Serialize)]
pub struct SurfaceState {
pub client: ClientId,
pub id: WlSurfaceId,
Expand All @@ -679,6 +680,7 @@ pub struct SurfaceState {
pub damage: Option<Vec<Rectangle<i32>>>,
// server-side only
pub output_ids: Vec<u32>,
pub viewport_state: Option<ViewportState>,

// Interfaces
pub xdg_surface_state: Option<xdg_shell::XdgSurfaceState>,
Expand All @@ -700,6 +702,7 @@ impl SurfaceState {
z_ordered_children: Vec::new(),
damage: None,
output_ids: Vec::new(),
viewport_state: None,
xdg_surface_state: None,
})
}
Expand Down Expand Up @@ -845,13 +848,13 @@ impl From<SctkOutputInfo> for OutputInfo {
}
}

#[derive(Debug, Clone, Eq, PartialEq, Archive, Deserialize, Serialize)]
#[derive(Debug, Clone, PartialEq, Archive, Deserialize, Serialize)]
pub enum SurfaceRequestPayload {
Commit(SurfaceState),
Destroyed,
}

#[derive(Debug, Clone, Eq, PartialEq, Archive, Deserialize, Serialize)]
#[derive(Debug, Clone, PartialEq, Archive, Deserialize, Serialize)]
pub struct SurfaceRequest {
pub client: ClientId,
pub surface: WlSurfaceId,
Expand Down Expand Up @@ -1051,3 +1054,18 @@ pub struct SurfaceEvent {
pub surface_id: WlSurfaceId,
pub payload: SurfaceEventPayload,
}

#[derive(Debug, Copy, Clone, PartialEq, Archive, Deserialize, Serialize)]
pub struct ViewportState {
pub src: Option<Rectangle<f64>>,
pub dst: Option<Size<i32>>,
}

impl From<&ViewportCachedState> for ViewportState {
fn from(viewport_state: &ViewportCachedState) -> Self {
Self {
src: viewport_state.src.map(Into::into),
dst: viewport_state.dst.map(Into::into),
}
}
}
3 changes: 3 additions & 0 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use smithay::wayland::shell::xdg::XdgShellState;
use smithay::wayland::shell::xdg::decoration::XdgDecorationState;
use smithay::wayland::shm::ShmState;
use smithay::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode as KdeDecorationMode;
use smithay::wayland::viewporter::ViewporterState;

use crate::prelude::*;
use crate::serialization::wayland::SurfaceRequest;
Expand Down Expand Up @@ -96,6 +97,7 @@ pub struct WprsServerState {
pub seat_state: SeatState<Self>,
pub data_device_state: DataDeviceState,
pub primary_selection_state: PrimarySelectionState,
pub viewporter_state: ViewporterState,

pub seat: Seat<Self>,

Expand Down Expand Up @@ -151,6 +153,7 @@ impl WprsServerState {
seat_state,
data_device_state: DataDeviceState::new::<Self>(&dh),
primary_selection_state: PrimarySelectionState::new::<Self>(&dh),
viewporter_state: ViewporterState::new::<Self>(&dh),
seat,
serializer,
object_map: HashMap::new(),
Expand Down
10 changes: 10 additions & 0 deletions src/server/smithay_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ use smithay::wayland::shell::xdg::XdgToplevelSurfaceData;
use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler;
use smithay::wayland::shm::ShmHandler;
use smithay::wayland::shm::ShmState;
use smithay::wayland::viewporter::ViewportCachedState;

use crate::channel_utils::DiscardingSender;
use crate::compositor_utils;
Expand Down Expand Up @@ -654,6 +655,10 @@ pub fn set_transformation(
surface_state.buffer_transform = Some(surface_attributes.buffer_transform.into());
}

pub fn set_viewport_state(viewport_state: &ViewportCachedState, surface_state: &mut SurfaceState) {
surface_state.viewport_state = Some(viewport_state.into());
}

#[instrument(skip_all, level = "debug")]
pub fn set_xdg_surface_attributes(surface_data: &SurfaceData, surface_state: &mut SurfaceState) {
if surface_data.cached_state.has::<SurfaceCachedState>() {
Expand Down Expand Up @@ -747,6 +752,9 @@ pub fn commit_impl(
position: (0, 0).into(),
});

let mut guard = surface_data.cached_state.get::<ViewportCachedState>();
let viewport_state = guard.current();

let mut guard = surface_data.cached_state.get::<SurfaceAttributes>();
let surface_attributes = guard.current();
let mut frame_callbacks = mem::take(&mut surface_attributes.frame_callbacks);
Expand Down Expand Up @@ -792,6 +800,7 @@ pub fn commit_impl(

set_regions(surface_attributes, surface_state);
set_transformation(surface_attributes, surface_state);
set_viewport_state(viewport_state, surface_state);
set_xdg_surface_attributes(surface_data, surface_state);

match &mut surface_state.role {
Expand Down Expand Up @@ -1229,3 +1238,4 @@ smithay::delegate_seat!(WprsServerState);
smithay::delegate_data_device!(WprsServerState);
smithay::delegate_output!(WprsServerState);
smithay::delegate_primary_selection!(WprsServerState);
smithay::delegate_viewporter!(WprsServerState);

0 comments on commit 6e20ffd

Please sign in to comment.