diff --git a/anvil/src/state.rs b/anvil/src/state.rs index 61b8a99587cc..57fd67fd2ef7 100644 --- a/anvil/src/state.rs +++ b/anvil/src/state.rs @@ -46,6 +46,7 @@ use smithay::{ }, utils::{Clock, Logical, Monotonic, Point, Rectangle}, wayland::{ + commit_timing::CommitTimingState, compositor::{get_parent, with_states, CompositorClientState, CompositorState}, dmabuf::DmabufFeedback, fifo::FifoState, @@ -568,6 +569,8 @@ smithay::delegate_single_pixel_buffer!(@ AnvilSt smithay::delegate_fifo!(@ AnvilState); +smithay::delegate_commit_timing!(@ AnvilState); + impl AnvilState { pub fn init( display: Display>, @@ -648,6 +651,7 @@ impl AnvilState { .map_or(true, |client_state| client_state.security_context.is_none()) }); FifoState::new::(&dh, |_| true); + CommitTimingState::new::(&dh, |_| true); // init input let seat_name = backend_data.seat_name(); diff --git a/src/wayland/commit_timing.rs b/src/wayland/commit_timing.rs new file mode 100644 index 000000000000..dee5562b4ecc --- /dev/null +++ b/src/wayland/commit_timing.rs @@ -0,0 +1,143 @@ +use std::time::Duration; +use wayland_protocols::wp::commit_timing::v1::server::{wp_commit_timer_v1, wp_commit_timing_manager_v1}; +use wayland_server::{ + backend::GlobalId, protocol::wl_surface, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, + Resource, WEnum, Weak, +}; + +pub struct CommitTimingState {} + +impl CommitTimingState { + pub fn new(display: &DisplayHandle, filter: F) -> Self + where + D: GlobalDispatch< + wp_commit_timing_manager_v1::WpCommitTimingManagerV1, + CommitTimingManagerGlobalData, + >, + D: Dispatch, + D: Dispatch, + D: 'static, + F: for<'c> Fn(&'c Client) -> bool + Send + Sync + 'static, + { + let data = CommitTimingManagerGlobalData { + filter: Box::new(filter), + }; + display.create_global::(1, data); + + Self {} + } +} + +#[allow(missing_debug_implementations)] +#[doc(hidden)] +pub struct CommitTimingManagerGlobalData { + /// Filter whether the clients can view global. + filter: Box Fn(&'c Client) -> bool + Send + Sync>, +} + +impl GlobalDispatch + for CommitTimingState +where + D: GlobalDispatch, + D: Dispatch, + D: 'static, +{ + fn bind( + _state: &mut D, + _display: &DisplayHandle, + _client: &Client, + manager: New, + _global_data: &CommitTimingManagerGlobalData, + data_init: &mut DataInit<'_, D>, + ) { + data_init.init(manager, ()); + } + + fn can_view(client: Client, global_data: &CommitTimingManagerGlobalData) -> bool { + (global_data.filter)(&client) + } +} + +#[doc(hidden)] +pub struct CommitTimerData { + surface: Weak, +} + +impl Dispatch for CommitTimingState +where + D: Dispatch, + D: Dispatch, + D: 'static, +{ + fn request( + state: &mut D, + _client: &wayland_server::Client, + _proxy: &wp_commit_timing_manager_v1::WpCommitTimingManagerV1, + request: wp_commit_timing_manager_v1::Request, + _data: &(), + _dh: &DisplayHandle, + data_init: &mut wayland_server::DataInit<'_, D>, + ) { + match request { + wp_commit_timing_manager_v1::Request::GetTimer { id, surface } => { + // TODO CommitTimerExists + data_init.init( + id, + CommitTimerData { + surface: surface.downgrade(), + }, + ); + } + wp_commit_timing_manager_v1::Request::Destroy => {} + _ => unreachable!(), + } + } +} + +impl Dispatch for CommitTimingState +where + D: Dispatch, + D: 'static, +{ + fn request( + state: &mut D, + _client: &wayland_server::Client, + _proxy: &wp_commit_timer_v1::WpCommitTimerV1, + request: wp_commit_timer_v1::Request, + _data: &CommitTimerData, + _dh: &DisplayHandle, + data_init: &mut wayland_server::DataInit<'_, D>, + ) { + match request { + wp_commit_timer_v1::Request::SetTimestamp { + tv_sec_hi, + tv_sec_lo, + tv_nsec, + } => { + let secs = (u64::from(tv_sec_hi) << 32) + u64::from(tv_sec_lo); + let duration = Duration::new(secs, tv_nsec); + } + wp_commit_timer_v1::Request::Destroy => {} + _ => unreachable!(), + } + } +} + +#[allow(missing_docs)] +#[macro_export] +macro_rules! delegate_commit_timing { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + $crate::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::wayland_protocols::wp::commit_timing::v1::server::wp_commit_timing_manager_v1::WpCommitTimingManagerV1: $crate::wayland::commit_timing::CommitTimingManagerGlobalData + ] => $crate::wayland::commit_timing::CommitTimingState); + + $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::wayland_protocols::wp::commit_timing::v1::server::wp_commit_timing_manager_v1::WpCommitTimingManagerV1: () + ] => $crate::wayland::commit_timing::CommitTimingState); + + $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::reexports::wayland_protocols::wp::commit_timing::v1::server::wp_commit_timer_v1::WpCommitTimerV1: $crate::wayland::commit_timing::CommitTimerData + ] => $crate::wayland::commit_timing::CommitTimingState); + }; +} +//use wayland_protocols::wp::commit_timing::v1::server::{wp_commit_timer_v1, wp_commit_timing_manager_v1}; diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 4e896365b995..6e108fabbd60 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -47,6 +47,7 @@ pub mod alpha_modifier; pub mod buffer; +pub mod commit_timing; pub mod compositor; pub mod content_type; pub mod cursor_shape;