Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a wp_viewporter implementation #397

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 8 additions & 45 deletions examples/image_viewporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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();
Expand All @@ -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::<wp_viewporter::WpViewporter, 1>::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();

Expand Down Expand Up @@ -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(),
Expand All @@ -117,7 +108,6 @@ fn main() {
registry_state: RegistryState::new(&globals),
output_state: OutputState::new(&globals, &qh),
shm,
wp_viewporter,
pool,
windows,
};
Expand All @@ -138,7 +128,6 @@ struct State {
registry_state: RegistryState,
output_state: OutputState,
shm: Shm,
wp_viewporter: SimpleGlobal<WpViewporter, 1>,

pool: SlotPool,
windows: Vec<ImageViewer>,
Expand Down Expand Up @@ -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 {
Expand All @@ -306,28 +294,3 @@ impl ProvidesRegistryState for State {

registry_handlers!(OutputState);
}

impl AsMut<SimpleGlobal<WpViewporter, 1>> for State {
fn as_mut(&mut self) -> &mut SimpleGlobal<WpViewporter, 1> {
&mut self.wp_viewporter
}
}

impl Dispatch<WpViewport, ()> for State {
fn event(
_: &mut State,
_: &WpViewport,
_: wp_viewport::Event,
_: &(),
_: &Connection,
_: &QueueHandle<State>,
) {
unreachable!("wp_viewport::Event is empty in version 1")
}
}

impl Drop for ImageViewer {
fn drop(&mut self) {
self.viewport.destroy()
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ pub mod seat;
pub mod shell;
pub mod shm;
pub mod subcompositor;
pub mod viewporter;
131 changes: 131 additions & 0 deletions src/viewporter.rs
Original file line number Diff line number Diff line change
@@ -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<State>(
globals: &GlobalList,
queue_handle: &QueueHandle<State>,
) -> Result<Self, BindError>
where
State: Dispatch<WpViewporter, GlobalData, State> + 'static,
{
let viewporter = globals.bind(queue_handle, 1..=1, GlobalData)?;
Ok(Viewporter { viewporter })
}

pub fn get_viewport<State>(
&self,
surface: &WlSurface,
queue_handle: &QueueHandle<State>,
) -> WpViewport
where
State: Dispatch<WpViewport, Viewport> + 'static,
{
let viewport_data = Viewport::new(surface.clone());
let viewport = self.viewporter.get_viewport(&surface, queue_handle, viewport_data);
viewport
}
}

impl<D> Dispatch<WpViewport, Viewport, D> for Viewporter
where
D: Dispatch<WpViewport, Viewport>,
{
fn event(
_: &mut D,
_: &WpViewport,
_: <WpViewport as Proxy>::Event,
_: &Viewport,
_: &Connection,
_: &QueueHandle<D>,
) {
unreachable!("wp_viewport has no events")
}
}

impl<D> Dispatch<WpViewporter, GlobalData, D> for Viewporter
where
D: Dispatch<WpViewporter, GlobalData>,
{
fn event(
_: &mut D,
_: &WpViewporter,
_: <WpViewporter as Proxy>::Event,
_: &GlobalData,
_: &Connection,
_: &QueueHandle<D>,
) {
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);
}
*/
Comment on lines +90 to +100
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we uncomment those?
It would be good to use this wrapper instead of WlVieporter directly, as that would allow for addition of version guards when a new version of viewporter releases some day.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any point to Viewport to begin with? Just getting the viewport from the state and using that is all you need really. My personal implementations never used more than that (https://github.com/catacombing/kumo/blob/master/src/wayland/protocols/viewporter.rs).

}

#[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
);
)*
};
}