Update example to use shell global

This commit is contained in:
Victor Berger 2017-09-05 21:09:50 +02:00
parent a86b3d6d67
commit aab56047f0
4 changed files with 96 additions and 130 deletions

View File

@ -1,5 +1,3 @@
mod shell;
mod glium;
pub use self::glium::GliumDrawer;
pub use self::shell::{ShellSurfaceRole, WlShellStubHandler};

View File

@ -1,93 +0,0 @@
use smithay::compositor::{CompositorToken, Handler as CompositorHandler};
use smithay::compositor::roles::{Role, RoleType};
use wayland_server::{Client, EventLoopHandle, GlobalHandler, Init, Resource};
use wayland_server::protocol::{wl_shell, wl_shell_surface, wl_surface};
/// A very basic handler for wl_shell
///
/// All it does is track which wl_shell_surface exist and which do not,
/// as well as the roles associated to them.
///
/// That's it.
pub struct WlShellStubHandler<U, R, H> {
my_id: Option<usize>,
token: CompositorToken<U, R, H>,
surfaces: Vec<(wl_shell_surface::WlShellSurface, wl_surface::WlSurface)>,
}
#[derive(Default)]
pub struct ShellSurfaceRole;
impl<U, R, H> WlShellStubHandler<U, R, H> {
pub fn new(compositor_token: CompositorToken<U, R, H>) -> WlShellStubHandler<U, R, H> {
WlShellStubHandler {
my_id: None,
token: compositor_token,
surfaces: Vec::new(),
}
}
pub fn surfaces(&self) -> &[(wl_shell_surface::WlShellSurface, wl_surface::WlSurface)] {
&self.surfaces
}
}
impl<U, R, H> Init for WlShellStubHandler<U, R, H> {
fn init(&mut self, evqh: &mut EventLoopHandle, index: usize) {
self.my_id = Some(index)
}
}
impl<U, R, H> GlobalHandler<wl_shell::WlShell> for WlShellStubHandler<U, R, H>
where
U: Send + 'static,
R: RoleType + Role<ShellSurfaceRole> + Send + 'static,
H: CompositorHandler<U, R> + Send + 'static,
{
fn bind(&mut self, evqh: &mut EventLoopHandle, client: &Client, global: wl_shell::WlShell) {
evqh.register::<_, Self>(
&global,
self.my_id
.expect("WlShellStubHandler was not properly initialized."),
);
}
}
impl<U, R, H> wl_shell::Handler for WlShellStubHandler<U, R, H>
where
U: Send + 'static,
R: RoleType + Role<ShellSurfaceRole> + Send + 'static,
H: CompositorHandler<U, R> + Send + 'static,
{
fn get_shell_surface(&mut self, evqh: &mut EventLoopHandle, client: &Client,
resource: &wl_shell::WlShell, id: wl_shell_surface::WlShellSurface,
surface: &wl_surface::WlSurface) {
let surface = surface.clone().expect(
"WlShellStubHandler can only manage surfaces managed by Smithay's CompositorHandler.",
);
if self.token.give_role::<ShellSurfaceRole>(&surface).is_err() {
// This surface already has a role, and thus cannot be given one!
resource.post_error(
wl_shell::Error::Role as u32,
"Surface already has a role.".into(),
);
return;
}
evqh.register::<_, Self>(&id, self.my_id.unwrap());
self.surfaces.push((id, surface))
}
}
server_declare_handler!(WlShellStubHandler<U: [Send], R: [RoleType, Role<ShellSurfaceRole>, Send], H: [CompositorHandler<U, R>, Send]>, wl_shell::Handler, wl_shell::WlShell);
impl<U, R, H> wl_shell_surface::Handler for WlShellStubHandler<U, R, H>
where
U: Send + 'static,
H: CompositorHandler<U, R> + Send + 'static,
{
}
server_declare_handler!(WlShellStubHandler<U: [Send], R: [Send], H: [CompositorHandler<U, R>, Send]>, wl_shell_surface::Handler, wl_shell_surface::WlShellSurface);

View File

@ -2,6 +2,7 @@
extern crate glium;
#[macro_use(define_roles)]
extern crate smithay;
extern crate wayland_protocols;
#[macro_use(server_declare_handler)]
extern crate wayland_server;
@ -14,7 +15,7 @@ mod helpers;
use glium::Surface;
use helpers::{GliumDrawer, ShellSurfaceRole, WlShellStubHandler};
use helpers::GliumDrawer;
use slog::{Drain, Logger};
use smithay::backend::graphics::glium::IntoGlium;
@ -22,10 +23,15 @@ use smithay::backend::input::InputBackend;
use smithay::backend::winit;
use smithay::compositor::{self, CompositorHandler, CompositorToken, SubsurfaceRole, TraversalAction};
use smithay::compositor::roles::Role;
use smithay::shell::{self, PopupConfigure, PopupSurface, ShellClient, ShellHandler, ShellSurfaceRole,
ToplevelConfigure, ToplevelSurface};
use smithay::shm::{BufferData, ShmGlobal, ShmToken};
use wayland_server::{Client, EventLoopHandle, Liveness, Resource};
use wayland_server::protocol::{wl_compositor, wl_shell, wl_shm, wl_subcompositor, wl_surface};
use wayland_protocols::unstable::xdg_shell::server::{zxdg_shell_v6, zxdg_toplevel_v6};
use wayland_server::{Client, EventLoopHandle, Liveness, Resource};
use wayland_server::protocol::{wl_compositor, wl_output, wl_seat, wl_shell, wl_shm, wl_subcompositor,
wl_surface};
define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );
@ -36,6 +42,7 @@ struct SurfaceHandler {
#[derive(Default)]
struct SurfaceData {
buffer: Option<(Vec<u8>, (u32, u32))>,
location: Option<(u32, u32)>,
}
impl compositor::Handler<SurfaceData, Roles> for SurfaceHandler {
@ -70,7 +77,61 @@ impl compositor::Handler<SurfaceData, Roles> for SurfaceHandler {
}
}
struct ShellSurfaceHandler;
impl shell::Handler<SurfaceData, Roles, SurfaceHandler, ()> for ShellSurfaceHandler {
fn new_client(&mut self, evlh: &mut EventLoopHandle, client: ShellClient<()>) {}
fn client_pong(&mut self, evlh: &mut EventLoopHandle, client: ShellClient<()>) {}
fn new_toplevel(&mut self, evlh: &mut EventLoopHandle,
surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>)
-> ToplevelConfigure {
ToplevelConfigure {
size: None,
states: vec![],
serial: 42,
}
}
fn new_popup(&mut self, evlh: &mut EventLoopHandle,
surface: PopupSurface<SurfaceData, Roles, SurfaceHandler, ()>)
-> PopupConfigure {
PopupConfigure {
size: (10, 10),
position: (10, 10),
serial: 42,
}
}
fn move_(&mut self, evlh: &mut EventLoopHandle,
surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>, seat: &wl_seat::WlSeat,
serial: u32) {
}
fn resize(&mut self, evlh: &mut EventLoopHandle,
surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>, seat: &wl_seat::WlSeat,
serial: u32, edges: zxdg_toplevel_v6::ResizeEdge) {
}
fn grab(&mut self, evlh: &mut EventLoopHandle,
surface: PopupSurface<SurfaceData, Roles, SurfaceHandler, ()>, seat: &wl_seat::WlSeat,
serial: u32) {
}
fn change_display_state(&mut self, evlh: &mut EventLoopHandle,
surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>,
maximized: Option<bool>, minimized: Option<bool>, fullscreen: Option<bool>,
output: Option<&wl_output::WlOutput>)
-> ToplevelConfigure {
ToplevelConfigure {
size: None,
states: vec![],
serial: 42,
}
}
fn show_window_menu(&mut self, evlh: &mut EventLoopHandle,
surface: ToplevelSurface<SurfaceData, Roles, SurfaceHandler, ()>,
seat: &wl_seat::WlSeat, serial: u32, x: i32, y: i32) {
}
}
type MyCompositorHandler = CompositorHandler<SurfaceData, Roles, SurfaceHandler>;
type MyShellHandler = ShellHandler<SurfaceData, Roles, SurfaceHandler, ShellSurfaceHandler, ()>;
fn main() {
// A logger facility, here we use the terminal for this example
@ -121,14 +182,15 @@ fn main() {
};
/*
* Initialize the shell stub global
* Initialize the shell global
*/
let shell_handler_id =
event_loop.add_handler_with_init(WlShellStubHandler::new(compositor_token.clone()));
event_loop.register_global::<wl_shell::WlShell, WlShellStubHandler<SurfaceData, Roles, SurfaceHandler>>(
shell_handler_id,
1,
);
let shell_handler_id = event_loop.add_handler_with_init(MyShellHandler::new(
ShellSurfaceHandler,
compositor_token.clone(),
log.clone(),
));
event_loop.register_global::<wl_shell::WlShell, MyShellHandler>(shell_handler_id, 1);
event_loop.register_global::<zxdg_shell_v6::ZxdgShellV6, MyShellHandler>(shell_handler_id, 1);
/*
* Initialize glium
@ -152,32 +214,31 @@ fn main() {
{
let screen_dimensions = context.get_framebuffer_dimensions();
let state = event_loop.state();
for &(_, ref surface) in state
.get_handler::<WlShellStubHandler<SurfaceData, Roles, SurfaceHandler>>(shell_handler_id)
.surfaces()
for toplevel_surface in state
.get_handler::<MyShellHandler>(shell_handler_id)
.toplevel_surfaces()
{
if surface.status() != Liveness::Alive {
continue;
}
// this surface is a root of a subsurface tree that needs to be drawn
compositor_token.with_surface_tree(
surface,
(100, 100),
|surface, attributes, role, &(mut x, mut y)| {
if let Some((ref contents, (w, h))) = attributes.user_data.buffer {
// there is actually something to draw !
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
x += subdata.x;
y += subdata.y;
if let Some(wl_surface) = toplevel_surface.get_surface() {
// this surface is a root of a subsurface tree that needs to be drawn
compositor_token.with_surface_tree(
wl_surface,
(100, 100),
|surface, attributes, role, &(mut x, mut y)| {
if let Some((ref contents, (w, h))) = attributes.user_data.buffer {
// there is actually something to draw !
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
x += subdata.x;
y += subdata.y;
}
drawer.draw(&mut frame, contents, (w, h), (x, y), screen_dimensions);
TraversalAction::DoChildren((x, y))
} else {
// we are not display, so our children are neither
TraversalAction::SkipChildren
}
drawer.draw(&mut frame, contents, (w, h), (x, y), screen_dimensions);
TraversalAction::DoChildren((x, y))
} else {
// we are not display, so our children are neither
TraversalAction::SkipChildren
}
},
);
},
);
}
}
}
frame.finish().unwrap();

View File

@ -115,7 +115,7 @@ where
H: CompositorHandler<U, R> + Send + 'static,
{
/// Create a new CompositorHandler
pub fn new<F, L>(handler: SH, token: CompositorToken<U, R, H>, logger: L) -> ShellHandler<U, R, H, SH, SD>
pub fn new<L>(handler: SH, token: CompositorToken<U, R, H>, logger: L) -> ShellHandler<U, R, H, SH, SD>
where
L: Into<Option<::slog::Logger>>,
{