Skip to content
This repository has been archived by the owner on Aug 3, 2024. It is now read-only.

[WIP] Wrapped Layer shell #174

Closed
wants to merge 15 commits into from
Closed
34 changes: 31 additions & 3 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use errors::{HandleErr, HandleResult};
use types::surface::{InternalSurface, InternalSurfaceState};
use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
XdgShellManager,
XdgShellManagerHandler, XdgV6ShellManager, XdgV6ShellManagerHandler};
XdgShellManager, XdgShellManagerHandler, XdgV6ShellManager,
XdgV6ShellManagerHandler, LayerShellManagerHandler, LayerShellManager};
use render::GenericRenderer;

use wayland_sys::server::{wl_display, wl_event_loop, signal::wl_signal_add, WAYLAND_SERVER_HANDLE};
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
wlr_compositor, wlr_compositor_create, wlr_compositor_destroy,
wlr_xdg_shell_v6, wlr_xdg_shell_v6_create,
wlr_xdg_shell, wlr_xdg_shell_create};
wlr_xdg_shell, wlr_xdg_shell_create, wlr_layer_shell_create, wlr_layer_shell};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
Expand Down Expand Up @@ -80,12 +80,17 @@ pub struct Compositor {
xdg_shell_manager: Option<Box<XdgShellManager>>,
/// Manager for XDG shells v6.
xdg_v6_shell_manager: Option<Box<XdgV6ShellManager>>,
/// Manager for layer shells.
layer_shell_manager: Option<Box<LayerShellManager>>,
/// Pointer to the xdg_shell global.
/// If xdg_shell_manager is `None`, this value will be `NULL`.
xdg_shell_global: *mut wlr_xdg_shell,
/// Pointer to the xdg_shell_v6 global.
/// If xdg_v6_shell_manager is `None`, this value will be `NULL`.
xdg_v6_shell_global: *mut wlr_xdg_shell_v6,
/// Pointer to the layer_shell global.
/// If layer_shell_manager is `None`, this value will be `NULL`.
layer_shell_global: *mut wlr_layer_shell,
/// Pointer to the wlr_compositor.
compositor: *mut wlr_compositor,
/// Pointer to the wlroots backend in use.
Expand Down Expand Up @@ -122,6 +127,7 @@ pub struct CompositorBuilder {
output_manager_handler: Option<Box<OutputManagerHandler>>,
xdg_shell_manager_handler: Option<Box<XdgShellManagerHandler>>,
xdg_v6_shell_manager_handler: Option<Box<XdgV6ShellManagerHandler>>,
layer_shell_manager_handler: Option<Box<LayerShellManagerHandler>>,
gles2: bool,
server_decoration_manager: bool,
data_device_manager: bool,
Expand All @@ -142,6 +148,7 @@ impl CompositorBuilder {
output_manager_handler: None,
xdg_shell_manager_handler: None,
xdg_v6_shell_manager_handler: None,
layer_shell_manager_handler: None,
xwayland: None,
user_terminate: None }
}
Expand Down Expand Up @@ -179,6 +186,14 @@ impl CompositorBuilder {
self
}

/// Set the handler for the layer shells.
pub fn layer_shell_manager(mut self,
layer_shell_manager_handler: Box<LayerShellManagerHandler>)
-> Self {
self.layer_shell_manager_handler = Some(layer_shell_manager_handler);
self
}

/// Decide whether or not to enable the data device manager.
///
/// This is used to do DnD, or "drag 'n drop" copy paste.
Expand Down Expand Up @@ -311,6 +326,17 @@ impl CompositorBuilder {
xdg_v6_shell_manager
});

// Set up the layer shell handler and associated Wayland global,
// if user provided a manager for it.
let mut layer_shell_global = ptr::null_mut();
let layer_shell_manager = self.layer_shell_manager_handler.map(|handler| {
layer_shell_global = wlr_layer_shell_create(display as *mut _);
let mut layer_shell_manager = LayerShellManager::new(handler);
wl_signal_add(&mut (*layer_shell_global).events.new_surface as *mut _ as _,
layer_shell_manager.add_listener() as *mut _ as _);
layer_shell_manager
});

// Set up the XWayland server, if the user wants it.
let xwayland = self.xwayland.and_then(|manager| {
Some(XWaylandServer::new(display as _,
Expand Down Expand Up @@ -344,6 +370,8 @@ impl CompositorBuilder {
xdg_shell_global,
xdg_v6_shell_manager,
xdg_v6_shell_global,
layer_shell_manager,
layer_shell_global,
data_device_manager,
compositor,
backend,
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ pub use self::events::{key_events, seat_events, tablet_pad_events, tablet_tool_e
xdg_shell_v6_events, xdg_shell_events};
pub use self::manager::{InputManagerHandler, KeyboardHandler, OutputBuilder, OutputBuilderResult,
OutputHandler, OutputManagerHandler, PointerHandler, TabletPadHandler,
TabletToolHandler, TouchHandler, XdgV6ShellHandler, XdgV6ShellManagerHandler,
XdgShellHandler, XdgShellManagerHandler};
TabletToolHandler, TouchHandler,
XdgV6ShellHandler, XdgV6ShellManagerHandler,
XdgShellHandler, XdgShellManagerHandler,
LayerShellManagerHandler, LayerShellHandler};
pub use self::types::area::*;
pub use self::types::cursor::*;
pub use self::types::data_device::*;
Expand Down
111 changes: 111 additions & 0 deletions src/manager/layer_shell_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//! Handler for layer shell client.

use libc;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wlr_layer_surface, wlr_xdg_popup};

use compositor::{compositor_handle, CompositorHandle};
use manager::construct_xdg_shell;
use {SurfaceHandle, LayerSurface, LayerSurfaceHandle, XdgShellSurface, XdgShellSurfaceHandle,
XdgPopup, XdgShellState, XdgShellHandler, SurfaceHandler};


/// Handles events from the client layer shells.
pub trait LayerShellHandler {
/// Called when the surface is ready to be mapped. It should be added to the list of views
/// at this time.
fn on_map(&mut self, CompositorHandle, SurfaceHandle, LayerSurfaceHandle) {}

/// Called when the surface should be unmapped.
///
/// It should be removed from the list of views at this time,
/// but may be remapped at a later time.
fn on_unmap(&mut self, CompositorHandle, SurfaceHandle, LayerSurfaceHandle) {}

/// Called when there is a new popup.
fn new_popup(&mut self, CompositorHandle, SurfaceHandle, LayerSurfaceHandle, XdgShellSurfaceHandle)
-> (Option<Box<XdgShellHandler>>, Option<Box<SurfaceHandler>>)
{ (None, None) }

/// Called when the Layer Shell is destroyed.
fn destroyed(&mut self, CompositorHandle, SurfaceHandle, LayerSurfaceHandle) {}
}

wayland_listener!(LayerShell, (LayerSurface, Box<LayerShellHandler>), [
destroy_listener => destroy_notify: |this: &mut LayerShell, data: *mut libc::c_void,| unsafe {
let layer_surface_ptr = data as *mut wlr_layer_surface;
{
let (ref shell_surface, ref mut manager) = this.data;
let surface = shell_surface.surface();
let compositor = match compositor_handle() {
Some(handle) => handle,
None => return
};
manager.destroyed(compositor,
surface,
shell_surface.weak_reference());
}
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_remove,
&mut (*this.destroy_listener()).link as *mut _ as _);
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_remove,
&mut (*this.on_map_listener()).link as *mut _ as _);
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_remove,
&mut (*this.on_unmap_listener()).link as *mut _ as _);
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_remove,
&mut (*this.new_popup_listener()).link as *mut _ as _);
Box::from_raw((*layer_surface_ptr).data as *mut LayerShell);
};
on_map_listener => on_map_notify: |this: &mut LayerShell, _data: *mut libc::c_void,| unsafe {
let (ref shell_surface, ref mut manager) = this.data;
let surface = shell_surface.surface();
let compositor = match compositor_handle() {
Some(handle) => handle,
None => return
};
manager.on_map(compositor,
surface,
shell_surface.weak_reference());
};
on_unmap_listener => on_unmap_notify: |this: &mut LayerShell, _data: *mut libc::c_void,|
unsafe {
let (ref shell_surface, ref mut manager) = this.data;
let surface = shell_surface.surface();
let compositor = match compositor_handle() {
Some(handle) => handle,
None => return
};

manager.on_unmap(compositor,
surface,
shell_surface.weak_reference());
};
new_popup_listener => new_popup_notify: |this: &mut LayerShell, data: *mut libc::c_void,|
unsafe {
let (ref shell_surface, ref mut manager) = this.data;
let surface = shell_surface.surface();
let compositor = match compositor_handle() {
Some(handle) => handle,
None => return
};
let popup_ptr = data as *mut wlr_xdg_popup;
let xdg_surface_ptr = (*popup_ptr).base;
let popup = XdgPopup::from_shell(xdg_surface_ptr, popup_ptr);
let xdg_surface = XdgShellSurface::new(xdg_surface_ptr, XdgShellState::Popup(popup));

let res = manager.new_popup(compositor,
surface,
shell_surface.weak_reference(),
xdg_surface.weak_reference());
if let (Some(shell_surface_handler), surface_handler) = res {
construct_xdg_shell(xdg_surface,
shell_surface_handler,
surface_handler,
xdg_surface_ptr);
}
};
]);
59 changes: 59 additions & 0 deletions src/manager/layer_shell_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Manager for layer shell clients.

use libc;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_layer_surface;

use {LayerSurface, LayerSurfaceHandle, LayerShellHandler, OutputHandle};
use super::layer_shell_handler::LayerShell;
use compositor::{compositor_handle, CompositorHandle};

pub trait LayerShellManagerHandler {
/// Callback that is triggered when a new layer shell surface appears.
///
/// The output is the output that was specified by the client.
/// If it was `None` then none was specified and you *must* specify it.
/// Do so by setting the value in the `Option`.
fn new_surface(&mut self,
CompositorHandle,
LayerSurfaceHandle,
&mut Option<OutputHandle>)
-> Option<Box<LayerShellHandler>>;
}

wayland_listener!(LayerShellManager, Box<LayerShellManagerHandler>, [
add_listener => add_notify: |this: &mut LayerShellManager, data: *mut libc::c_void,| unsafe {
let ref mut manager = this.data;
let layer_surface_ptr = data as *mut wlr_layer_surface;
let compositor = match compositor_handle() {
Some(handle) => handle,
None => return
};
wlr_log!(L_DEBUG, "New layer shell surface request {:p}", layer_surface_ptr);
let mut layer_surface = LayerSurface::new(layer_surface_ptr);
let mut output = if (*layer_surface_ptr).output.is_null() {
None
} else {
Some(OutputHandle::from_ptr((*layer_surface_ptr).output))
};
let new_surface_res = manager.new_surface(compositor, layer_surface.weak_reference(), &mut output);
if let Some(output) = output {
(*layer_surface_ptr).output = output.as_ptr();
} else {
layer_surface.close();
return
}
if let Some(layer_surface_handler) = new_surface_res {
let mut layer_surface = LayerShell::new((layer_surface, layer_surface_handler));
wl_signal_add(&mut (*layer_surface_ptr).events.destroy as *mut _ as _,
layer_surface.destroy_listener() as _);
wl_signal_add(&mut (*layer_surface_ptr).events.map as *mut _ as _,
layer_surface.on_map_listener() as _);
wl_signal_add(&mut (*layer_surface_ptr).events.unmap as *mut _ as _,
layer_surface.on_unmap_listener() as _);
wl_signal_add(&mut (*layer_surface_ptr).events.new_popup as *mut _ as _,
layer_surface.new_popup_listener() as _);
(*layer_surface_ptr).data = Box::into_raw(layer_surface) as *mut _;
}
};
]);
4 changes: 4 additions & 0 deletions src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ mod xdg_shell_v6_manager;
mod xdg_shell_v6_handler;
mod xdg_shell_manager;
mod xdg_shell_handler;
mod layer_shell_manager;
mod layer_shell_handler;
mod tablet_pad_handler;
mod tablet_tool_handler;

Expand All @@ -24,3 +26,5 @@ pub use self::xdg_shell_v6_handler::*;
pub use self::xdg_shell_v6_manager::*;
pub use self::xdg_shell_handler::*;
pub use self::xdg_shell_manager::*;
pub use self::layer_shell_handler::*;
pub use self::layer_shell_manager::*;
78 changes: 42 additions & 36 deletions src/manager/xdg_shell_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,43 +47,49 @@ wayland_listener!(XdgShellManager, Box<XdgShellManagerHandler>, [
shell_surface.weak_reference());

if let (Some(shell_surface_handler), surface_handler) = new_surface_res {
construct_xdg_shell(shell_surface, shell_surface_handler, surface_handler, data);

let mut shell_surface = XdgShell::new((shell_surface, shell_surface_handler));
let surface_state = (*(*data).surface).data as *mut InternalSurfaceState;
if let Some(surface_handler) = surface_handler {
(*(*surface_state).surface).data().1 = surface_handler;
}

wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
shell_surface.destroy_listener() as _);
wl_signal_add(&mut (*(*data).surface).events.commit as *mut _ as _,
shell_surface.commit_listener() as _);
wl_signal_add(&mut (*data).events.ping_timeout as *mut _ as _,
shell_surface.ping_timeout_listener() as _);
wl_signal_add(&mut (*data).events.new_popup as *mut _ as _,
shell_surface.new_popup_listener() as _);
let events = with_handles!([(shell_surface: {shell_surface.surface_mut()})] => {
match shell_surface.state() {
None | Some(&mut Popup(_)) => None,
Some(&mut TopLevel(ref mut toplevel)) => Some((*toplevel.as_ptr()).events)
}
}).expect("Cannot borrow xdg shell surface");
if let Some(mut events) = events {
wl_signal_add(&mut events.request_maximize as *mut _ as _,
shell_surface.maximize_listener() as _);
wl_signal_add(&mut events.request_fullscreen as *mut _ as _,
shell_surface.fullscreen_listener() as _);
wl_signal_add(&mut events.request_minimize as *mut _ as _,
shell_surface.minimize_listener() as _);
wl_signal_add(&mut events.request_move as *mut _ as _,
shell_surface.move_listener() as _);
wl_signal_add(&mut events.request_resize as *mut _ as _,
shell_surface.resize_listener() as _);
wl_signal_add(&mut events.request_show_window_menu as *mut _ as _,
shell_surface.show_window_menu_listener() as _);
}
let shell_data = (*data).data as *mut XdgShellSurfaceState;
(*shell_data).shell = Box::into_raw(shell_surface);
}
};
]);
pub(crate) unsafe fn construct_xdg_shell(shell_surface: XdgShellSurface,
shell_surface_handler: Box<XdgShellHandler>,
surface_handler: Option<Box<SurfaceHandler>>,
data: *mut wlr_xdg_surface) {
let mut shell_surface = XdgShell::new((shell_surface, shell_surface_handler));
let surface_state = (*(*data).surface).data as *mut InternalSurfaceState;
if let Some(surface_handler) = surface_handler {
(*(*surface_state).surface).data().1 = surface_handler;
}

wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
shell_surface.destroy_listener() as _);
wl_signal_add(&mut (*(*data).surface).events.commit as *mut _ as _,
shell_surface.commit_listener() as _);
wl_signal_add(&mut (*data).events.ping_timeout as *mut _ as _,
shell_surface.ping_timeout_listener() as _);
wl_signal_add(&mut (*data).events.new_popup as *mut _ as _,
shell_surface.new_popup_listener() as _);
let events = with_handles!([(shell_surface: {shell_surface.surface_mut()})] => {
match shell_surface.state() {
None | Some(&mut Popup(_)) => None,
Some(&mut TopLevel(ref mut toplevel)) => Some((*toplevel.as_ptr()).events)
}
}).expect("Cannot borrow xdg shell surface");
if let Some(mut events) = events {
wl_signal_add(&mut events.request_maximize as *mut _ as _,
shell_surface.maximize_listener() as _);
wl_signal_add(&mut events.request_fullscreen as *mut _ as _,
shell_surface.fullscreen_listener() as _);
wl_signal_add(&mut events.request_minimize as *mut _ as _,
shell_surface.minimize_listener() as _);
wl_signal_add(&mut events.request_move as *mut _ as _,
shell_surface.move_listener() as _);
wl_signal_add(&mut events.request_resize as *mut _ as _,
shell_surface.resize_listener() as _);
wl_signal_add(&mut events.request_show_window_menu as *mut _ as _,
shell_surface.show_window_menu_listener() as _);
}
let shell_data = (*data).data as *mut XdgShellSurfaceState;
(*shell_data).shell = Box::into_raw(shell_surface);
}
Loading