Skip to content

Commit

Permalink
Add subcompositor and subsurface helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
kchibisov committed Mar 2, 2023
1 parent 69bffe5 commit 94c261b
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 5 deletions.
31 changes: 26 additions & 5 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use std::sync::{

use wayland_client::{
globals::{BindError, GlobalList},
protocol::{wl_callback, wl_compositor, wl_output, wl_region, wl_surface},
protocol::{
wl_callback, wl_compositor, wl_output, wl_region,
wl_surface::{self, WlSurface},
},
Connection, Dispatch, Proxy, QueueHandle,
};

Expand Down Expand Up @@ -95,6 +98,12 @@ pub struct SurfaceData {
/// The scale factor of the output with the highest scale factor.
pub(crate) scale_factor: AtomicI32,

/// Parent surface used when creating subsurfaces.
///
/// For top-level surfaces this is always `None`.
pub(crate) parent_surface: Option<WlSurface>,

/// The inner mutable storage.
inner: Mutex<SurfaceDataInner>,
}

Expand All @@ -108,16 +117,28 @@ struct SurfaceDataInner {
}

impl SurfaceData {
/// Create a new surface that initially reports the given scale factor.
pub fn with_initial_scale(scale_factor: i32) -> Self {
Self { scale_factor: AtomicI32::new(scale_factor), inner: Default::default() }
/// Create a new surface that initially reports the given scale factor and parent.
pub fn new(parent_surface: Option<WlSurface>, scale_factor: i32) -> Self {
Self {
scale_factor: AtomicI32::new(scale_factor),
parent_surface,
inner: Default::default(),
}
}

/// The scale factor of the output with the highest scale factor.
pub fn scale_factor(&self) -> i32 {
self.scale_factor.load(Ordering::Relaxed)
}

/// The parent surface used for this surface.
///
/// The surface is `Some` for primarily for subsurfaces,
/// since they must have a parent surface.
pub fn parent_surface(&self) -> Option<&WlSurface> {
self.parent_surface.as_ref()
}

/// The outputs the surface is currently inside.
pub fn outputs(&self) -> impl Iterator<Item = wl_output::WlOutput> {
self.inner.lock().unwrap().outputs.clone().into_iter()
Expand All @@ -126,7 +147,7 @@ impl SurfaceData {

impl Default for SurfaceData {
fn default() -> Self {
Self::with_initial_scale(1)
Self::new(None, 1)
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ pub mod registry;
pub mod seat;
pub mod shell;
pub mod shm;
pub mod subcompositor;
124 changes: 124 additions & 0 deletions src/subcompositor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use crate::reexports::client::globals::{BindError, GlobalList};
use crate::reexports::client::protocol::wl_compositor::WlCompositor;
use crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor;
use crate::reexports::client::protocol::wl_subsurface::WlSubsurface;
use crate::reexports::client::protocol::wl_surface::WlSurface;
use crate::reexports::client::{Connection, Dispatch, Proxy, QueueHandle};

use crate::compositor::SurfaceData;
use crate::globals::GlobalData;

#[derive(Debug)]
pub struct SubcompositorState {
compositor: WlCompositor,
subcompositor: WlSubcompositor,
}

impl SubcompositorState {
pub fn bind<State>(
compositor: WlCompositor,
globals: &GlobalList,
queue_handle: &QueueHandle<State>,
) -> Result<Self, BindError>
where
State: Dispatch<WlSubcompositor, GlobalData, State> + 'static,
{
let subcompositor = globals.bind(queue_handle, 1..=1, GlobalData)?;
Ok(SubcompositorState { compositor, subcompositor })
}

pub fn create_subsurface<State>(
&self,
parent: WlSurface,
queue_handle: &QueueHandle<State>,
) -> (WlSubsurface, WlSurface)
where
State: Dispatch<WlSurface, SurfaceData> + Dispatch<WlSubsurface, SubsurfaceData> + 'static,
{
let surface_data = SurfaceData::new(Some(parent.clone()), 1);
let surface = self.compositor.create_surface(queue_handle, surface_data);
let subsurface_data = SubsurfaceData::new(surface.clone());
let subsurface =
self.subcompositor.get_subsurface(&surface, &parent, queue_handle, subsurface_data);
(subsurface, surface)
}
}

impl<D> Dispatch<WlSubsurface, SubsurfaceData, D> for SubcompositorState
where
D: Dispatch<WlSubsurface, SubsurfaceData>,
{
fn event(
_: &mut D,
_: &WlSubsurface,
_: <WlSubsurface as Proxy>::Event,
_: &SubsurfaceData,
_: &Connection,
_: &QueueHandle<D>,
) {
}
}

impl<D> Dispatch<WlSubcompositor, GlobalData, D> for SubcompositorState
where
D: Dispatch<WlSubcompositor, GlobalData>,
{
fn event(
_: &mut D,
_: &WlSubcompositor,
_: <WlSubcompositor as Proxy>::Event,
_: &GlobalData,
_: &Connection,
_: &QueueHandle<D>,
) {
unreachable!("wl_subcompositor has no events")
}
}

/// The data assoctiated with the subsurface.
#[derive(Debug)]
pub struct SubsurfaceData {
/// The surface used when creating this subsurface.
surface: WlSurface,
}

impl SubsurfaceData {
pub(crate) fn new(surface: WlSurface) -> Self {
Self { surface }
}

/// Get the surface used when creating the given subsurface.
pub fn surface(&self) -> &WlSurface {
&self.surface
}
}

#[macro_export]
macro_rules! delegate_subcompositor {
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
[
$crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor: $crate::globals::GlobalData
] => $crate::subcompositor::SubcompositorState
);
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
[
$crate::reexports::client::protocol::wl_subsurface::WlSubsurface: $crate::subcompositor::SubsurfaceData
] => $crate::subcompositor::SubcompositorState
);
};
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, subsurface: [$($subsurface: ty),*$(,)?]) => {
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
[
$crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor: $crate::globals::GlobalData
] => $crate::subcompositor::SubcompositorState
);
$(
$crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
[
$crate::reexports::client::protocol::wl_subsurface::WlSubsurface: $subsurface
] => $crate::subcompositor::SubcompositorState
);
)*
};
}

0 comments on commit 94c261b

Please sign in to comment.