diff --git a/examples/image_viewporter.rs b/examples/image_viewporter.rs index e7b34ceaf..7c73c4976 100644 --- a/examples/image_viewporter.rs +++ b/examples/image_viewporter.rs @@ -2,10 +2,10 @@ use std::{env, path::Path}; use smithay_client_toolkit::{ compositor::{CompositorHandler, CompositorState}, - delegate_compositor, delegate_output, delegate_registry, delegate_shm, delegate_simple, + delegate_compositor, delegate_output, delegate_registry, delegate_shm, delegate_viewporter, delegate_xdg_shell, delegate_xdg_window, output::{OutputHandler, OutputState}, - registry::{ProvidesRegistryState, RegistryState, SimpleGlobal}, + registry::{ProvidesRegistryState, RegistryState}, registry_handlers, shell::{ xdg::{ @@ -15,16 +15,14 @@ use smithay_client_toolkit::{ WaylandSurface, }, shm::{slot::SlotPool, Shm, ShmHandler}, + viewporter::Viewporter, }; use wayland_client::{ globals::registry_queue_init, protocol::{wl_output, wl_shm, wl_surface}, - Connection, Dispatch, QueueHandle, -}; -use wayland_protocols::wp::viewporter::client::{ - wp_viewport::{self, WpViewport}, - wp_viewporter::{self, WpViewporter}, + Connection, QueueHandle, }; +use wayland_protocols::wp::viewporter::client::wp_viewport::WpViewport; fn main() { env_logger::init(); @@ -45,10 +43,7 @@ fn main() { // we share with the compositor process. let shm = Shm::bind(&globals, &qh).expect("wl shm is not available."); // In this example, we use the viewporter to allow the compositor to scale and crop presented images. - // - // Since the wp_viewporter protocol has no events, we can use SimpleGlobal. - let wp_viewporter = SimpleGlobal::::bind(&globals, &qh) - .expect("wp_viewporter not available"); + let viewporter = Viewporter::bind(&globals, &qh).expect("wp viewporter is not available"); let mut windows = Vec::new(); @@ -89,11 +84,7 @@ fn main() { window.commit(); // For scaling, create a viewport for the window. - let viewport = wp_viewporter.get().expect("Requires wp_viewporter").get_viewport( - window.wl_surface(), - &qh, - (), - ); + let viewport = viewporter.get_viewport(window.wl_surface(), &qh); windows.push(ImageViewer { width: image.width(), @@ -117,7 +108,6 @@ fn main() { registry_state: RegistryState::new(&globals), output_state: OutputState::new(&globals, &qh), shm, - wp_viewporter, pool, windows, }; @@ -138,7 +128,6 @@ struct State { registry_state: RegistryState, output_state: OutputState, shm: Shm, - wp_viewporter: SimpleGlobal, pool: SlotPool, windows: Vec, @@ -291,12 +280,11 @@ impl State { delegate_compositor!(State); delegate_output!(State); delegate_shm!(State); +delegate_viewporter!(State); delegate_xdg_shell!(State); delegate_xdg_window!(State); -delegate_simple!(State, WpViewporter, 1); - delegate_registry!(State); impl ProvidesRegistryState for State { @@ -306,28 +294,3 @@ impl ProvidesRegistryState for State { registry_handlers!(OutputState); } - -impl AsMut> for State { - fn as_mut(&mut self) -> &mut SimpleGlobal { - &mut self.wp_viewporter - } -} - -impl Dispatch for State { - fn event( - _: &mut State, - _: &WpViewport, - _: wp_viewport::Event, - _: &(), - _: &Connection, - _: &QueueHandle, - ) { - unreachable!("wp_viewport::Event is empty in version 1") - } -} - -impl Drop for ImageViewer { - fn drop(&mut self) { - self.viewport.destroy() - } -} diff --git a/src/lib.rs b/src/lib.rs index 3818c02d9..162d076f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,3 +27,4 @@ pub mod seat; pub mod shell; pub mod shm; pub mod subcompositor; +pub mod viewporter; diff --git a/src/viewporter.rs b/src/viewporter.rs new file mode 100644 index 000000000..1a851a7a2 --- /dev/null +++ b/src/viewporter.rs @@ -0,0 +1,131 @@ +use crate::reexports::client::globals::{BindError, GlobalList}; +use crate::reexports::client::protocol::wl_surface::WlSurface; +use crate::reexports::client::{Connection, Dispatch, Proxy, QueueHandle}; +use crate::reexports::protocols::wp::viewporter::client::{ + wp_viewport::WpViewport, wp_viewporter::WpViewporter, +}; + +use crate::globals::GlobalData; + +#[derive(Debug)] +pub struct Viewporter { + viewporter: WpViewporter, +} + +impl Viewporter { + pub fn bind( + globals: &GlobalList, + queue_handle: &QueueHandle, + ) -> Result + where + State: Dispatch + 'static, + { + let viewporter = globals.bind(queue_handle, 1..=1, GlobalData)?; + Ok(Viewporter { viewporter }) + } + + pub fn get_viewport( + &self, + surface: &WlSurface, + queue_handle: &QueueHandle, + ) -> WpViewport + where + State: Dispatch + 'static, + { + let viewport_data = Viewport::new(surface.clone()); + let viewport = self.viewporter.get_viewport(&surface, queue_handle, viewport_data); + viewport + } +} + +impl Dispatch for Viewporter +where + D: Dispatch, +{ + fn event( + _: &mut D, + _: &WpViewport, + _: ::Event, + _: &Viewport, + _: &Connection, + _: &QueueHandle, + ) { + unreachable!("wp_viewport has no events") + } +} + +impl Dispatch for Viewporter +where + D: Dispatch, +{ + fn event( + _: &mut D, + _: &WpViewporter, + _: ::Event, + _: &GlobalData, + _: &Connection, + _: &QueueHandle, + ) { + unreachable!("wp_viewporter has no events") + } +} + +/// The data assoctiated with the subsurface. +#[derive(Debug)] +pub struct Viewport { + /// The surface used when creating this subsurface. + surface: WlSurface, +} + +impl Viewport { + pub(crate) fn new(surface: WlSurface) -> Self { + Self { surface } + } + + /// Get the surface used when creating the given viewport. + pub fn surface(&self) -> &WlSurface { + &self.surface + } + + /* + /// Set the source rectangle. + pub fn set_source(&self, x: f64, y: f64, width: f64, height: f64) { + self.viewport.set_source(x, y, width, height); + } + + /// Set the destination size. + pub fn set_destination(&self, width: i32, height: i32) { + self.viewport.set_destination(width, height); + } + */ +} + +#[macro_export] +macro_rules! delegate_viewporter { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: + [ + $crate::reexports::protocols::wp::viewporter::client::wp_viewporter::WpViewporter: $crate::globals::GlobalData + ] => $crate::viewporter::Viewporter + ); + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: + [ + $crate::reexports::protocols::wp::viewporter::client::wp_viewport::WpViewport: $crate::viewporter::Viewport + ] => $crate::viewporter::Viewporter + ); + }; + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, subsurface: [$($subsurface: ty),*$(,)?]) => { + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: + [ + $crate::reexports::protocols::wp::viewporter::client::wp_viewporter::WpViewporter: $crate::globals::GlobalData + ] => $crate::viewporter::Viewporter + ); + $( + $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: + [ + $crate::reexports::protocols::wp::viewporter::client::wp_viewport::WpViewport: $subsurface + ] => $crate::viewporter::Viewporter + ); + )* + }; +}