Basic xdg_shell_v6 handling

This commit is contained in:
buffet 2019-01-31 16:37:27 +01:00
parent eb5efc4557
commit a45075205c
9 changed files with 262 additions and 75 deletions

View file

@ -1,35 +1,45 @@
use crate::CompositorState;
use log::debug; use log::debug;
use wlroots::{ use wlroots::{
compositor, compositor,
input::{self, keyboard}, input::{self, keyboard},
wlroots_dehandle,
xkbcommon::xkb::{keysym_get_name, keysyms}, xkbcommon::xkb::{keysym_get_name, keysyms},
WLR_KEY_PRESSED, WLR_KEY_PRESSED,
}; };
use std::{process::Command, thread};
pub struct Keyboard; pub struct Keyboard;
impl input::keyboard::Handler for Keyboard { impl input::keyboard::Handler for Keyboard {
#[wlroots_dehandle(compositor, seat)]
fn on_key( fn on_key(
&mut self, &mut self,
compositor_handle: compositor::Handle, compositor_handle: compositor::Handle,
_keyboard_handle: keyboard::Handle, _keyboard_handle: keyboard::Handle,
key_event: &keyboard::event::Key, key_event: &keyboard::event::Key,
) { ) {
use compositor_handle as compositor;
if key_event.key_state() == WLR_KEY_PRESSED { if key_event.key_state() == WLR_KEY_PRESSED {
for key in key_event.pressed_keys() { for key in key_event.pressed_keys() {
debug!("Key down: {}", keysym_get_name(key)); debug!("Key down: {}", keysym_get_name(key));
match key { match key {
keysyms::KEY_Escape => compositor::terminate(), keysyms::KEY_Escape => compositor::terminate(),
keysyms::KEY_F1 => {
thread::spawn(move || {
Command::new("weston-terminal").output().unwrap();
});
}
keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 => { keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 => {
compositor_handle
.run(|compositor| {
let backend = compositor.backend_mut(); let backend = compositor.backend_mut();
if let Some(mut session) = backend.get_session() { if let Some(mut session) = backend.get_session() {
session.change_vt(key - keysyms::KEY_XF86Switch_VT_1 + 1); session.change_vt(key - keysyms::KEY_XF86Switch_VT_1 + 1);
} }
})
.unwrap();
} }
_ => {} _ => {}
} }
@ -39,5 +49,14 @@ impl input::keyboard::Handler for Keyboard {
debug!("Key up: {}", keysym_get_name(key)); debug!("Key up: {}", keysym_get_name(key));
} }
} }
let state: &mut CompositorState = compositor.downcast();
let seat_handle = state.seat_handle.clone().unwrap();
use seat_handle as seat;
seat.keyboard_notify_key(
key_event.time_msec(),
key_event.keycode(),
key_event.key_state() as u32,
);
} }
} }

View file

@ -8,7 +8,7 @@ use log::debug;
use wlroots::{ use wlroots::{
compositor, compositor,
input::{self, keyboard, pointer}, input::{self, keyboard, pointer},
with_handles, wlroots_dehandle,
}; };
pub fn build() -> input::manager::Builder { pub fn build() -> input::manager::Builder {
@ -17,32 +17,46 @@ pub fn build() -> input::manager::Builder {
.pointer_added(pointer_added) .pointer_added(pointer_added)
} }
#[wlroots_dehandle(compositor, keyboard, seat)]
fn keyboard_added( fn keyboard_added(
compositor_handle: compositor::Handle, compositor_handle: compositor::Handle,
keyboard_handle: keyboard::Handle, keyboard_handle: keyboard::Handle,
) -> Option<Box<keyboard::Handler>> { ) -> Option<Box<keyboard::Handler>> {
{
debug!("Keyboard added"); debug!("Keyboard added");
with_handles!([(compositor: {compositor_handle})] => { use compositor_handle as compositor;
let compositor_state: &mut CompositorState = compositor.data.downcast_mut().unwrap(); let state: &mut CompositorState = compositor.data.downcast_mut().unwrap();
compositor_state.keyboards.push(keyboard_handle);
}) {
.unwrap(); let seat_handle = state.seat_handle.as_ref().unwrap();
use keyboard_handle as keyboard;
use seat_handle as seat;
seat.set_keyboard(keyboard.input_device());
}
state.keyboards.push(keyboard_handle);
}
Some(Box::new(Keyboard)) Some(Box::new(Keyboard))
} }
#[wlroots_dehandle(compositor, pointer, cursor)]
fn pointer_added( fn pointer_added(
compositor_handle: compositor::Handle, compositor_handle: compositor::Handle,
pointer_handle: pointer::Handle, pointer_handle: pointer::Handle,
) -> Option<Box<pointer::Handler>> { ) -> Option<Box<pointer::Handler>> {
{
debug!("Pointer added"); debug!("Pointer added");
with_handles!([(compositor: {compositor_handle}), (pointer: {pointer_handle})] => { use compositor_handle as compositor;
let compositor_state: &mut CompositorState = compositor.downcast(); let state: &mut CompositorState = compositor.downcast();
compositor_state.cursor_handle
.run(|cursor| cursor.attach_input_device(pointer.input_device())) let cursor_handle = &state.cursor_handle;
.unwrap(); use cursor_handle as cursor;
}) use pointer_handle as pointer;
.unwrap(); cursor.attach_input_device(pointer.input_device());
}
Some(Box::new(Pointer)) Some(Box::new(Pointer))
} }

View file

@ -1,41 +1,41 @@
use crate::CompositorState; use crate::CompositorState;
use wlroots::{compositor, input::pointer, with_handles}; use wlroots::{compositor, input::pointer, wlroots_dehandle};
pub struct Pointer; pub struct Pointer;
impl pointer::Handler for Pointer { impl pointer::Handler for Pointer {
#[wlroots_dehandle(compositor, cursor)]
fn on_motion_absolute( fn on_motion_absolute(
&mut self, &mut self,
compositor_handle: compositor::Handle, compositor_handle: compositor::Handle,
_pointer_handle: pointer::Handle, _pointer_handle: pointer::Handle,
absolute_motion_event: &pointer::event::AbsoluteMotion, absolute_motion_event: &pointer::event::AbsoluteMotion,
) { ) {
with_handles!([(compositor: {compositor_handle})] => { use compositor_handle as compositor;
let compositor_state: &mut CompositorState = compositor.downcast(); let state: &mut CompositorState = compositor.downcast();
let (x, y) = absolute_motion_event.pos(); let (x, y) = absolute_motion_event.pos();
compositor_state.cursor_handle let cursor_handle = &state.cursor_handle;
.run(|cursor| cursor.warp_absolute(absolute_motion_event.device(), x, y)) use cursor_handle as cursor;
.unwrap(); cursor.warp_absolute(absolute_motion_event.device(), x, y);
})
.unwrap();
} }
#[wlroots_dehandle(compositor, cursor)]
fn on_motion( fn on_motion(
&mut self, &mut self,
compositor_handle: compositor::Handle, compositor_handle: compositor::Handle,
_pointer_handle: pointer::Handle, _pointer_handle: pointer::Handle,
motion_event: &pointer::event::Motion, motion_event: &pointer::event::Motion,
) { ) {
with_handles!([(compositor: {compositor_handle})] => { use compositor_handle as compositor;
let compositor_state: &mut CompositorState = compositor.downcast(); let state: &mut CompositorState = compositor.downcast();
let (dx, dy) = motion_event.delta(); let (dx, dy) = motion_event.delta();
compositor_state.cursor_handle let cursor_handle = &state.cursor_handle;
.run(|cursor| cursor.move_to(None, dx, dy)) use cursor_handle as cursor;
.unwrap(); cursor.move_to(None, dx, dy);
})
.unwrap();
} }
// TODO: implement on_button
} }

View file

@ -1,5 +1,6 @@
mod input; mod input;
mod output; mod output;
mod shells;
use log::{info, warn, LevelFilter}; use log::{info, warn, LevelFilter};
@ -8,6 +9,8 @@ use wlroots::{
cursor::{self, xcursor, Cursor}, cursor::{self, xcursor, Cursor},
input::keyboard, input::keyboard,
output::layout, output::layout,
seat::{self, Seat},
shell::xdg_shell_v6,
utils::log::Logger, utils::log::Logger,
}; };
@ -18,10 +21,12 @@ struct ExOutputLayout;
impl layout::Handler for ExOutputLayout {} impl layout::Handler for ExOutputLayout {}
struct CompositorState { struct CompositorState {
pub xcursor_manager: xcursor::Manager, xcursor_manager: xcursor::Manager,
pub cursor_handle: cursor::Handle, cursor_handle: cursor::Handle,
pub layout_handle: layout::Handle, layout_handle: layout::Handle,
pub keyboards: Vec<keyboard::Handle>, keyboards: Vec<keyboard::Handle>,
shells: Vec<xdg_shell_v6::Handle>,
seat_handle: Option<seat::Handle>,
} }
impl CompositorState { impl CompositorState {
@ -44,7 +49,9 @@ impl CompositorState {
xcursor_manager: xcursor_manager, xcursor_manager: xcursor_manager,
cursor_handle: cursor_handle, cursor_handle: cursor_handle,
layout_handle: layout_handle, layout_handle: layout_handle,
keyboards: Vec::new(), keyboards: vec![],
shells: vec![],
seat_handle: None,
} }
} }
} }
@ -56,11 +63,31 @@ fn main() {
build_compositor().run(); build_compositor().run();
} }
struct SeatHandler;
impl seat::Handler for SeatHandler {}
fn build_compositor() -> compositor::Compositor { fn build_compositor() -> compositor::Compositor {
compositor::Builder::new() let mut compositor = compositor::Builder::new()
.gles2(true) .gles2(true)
.wl_shm(true)
.data_device(true) .data_device(true)
.input_manager(input::build()) .input_manager(input::build())
.output_manager(output::build()) .output_manager(output::build())
.build_auto(CompositorState::new()) .xdg_shell_v6_manager(shells::xdg_v6::build())
.build_auto(CompositorState::new());
let seat_handle = Seat::create(
&mut compositor,
String::from("seat0"),
Box::new(SeatHandler),
);
seat_handle
.run(|seat| seat.set_capabilities(seat::Capability::all()))
.unwrap();
let state: &mut CompositorState = compositor.downcast();
state.seat_handle = Some(seat_handle);
compositor
} }

View file

@ -1,42 +1,41 @@
use crate::CompositorState; use crate::{output::Output, CompositorState};
use log::debug; use log::debug;
use wlroots::{compositor, output, with_handles}; use wlroots::{compositor, output, wlroots_dehandle};
pub fn build() -> output::manager::Builder { pub fn build() -> output::manager::Builder {
output::manager::Builder::default().output_added(output_added) output::manager::Builder::default().output_added(output_added)
} }
struct Output; #[wlroots_dehandle(compositor, layout, cursor, output)]
impl output::Handler for Output {}
fn output_added<'output>( fn output_added<'output>(
compositor_handle: compositor::Handle, compositor_handle: compositor::Handle,
output_builder: output::Builder<'output>, output_builder: output::Builder<'output>,
) -> Option<output::BuilderResult<'output>> { ) -> Option<output::BuilderResult<'output>> {
debug!("Output added"); debug!("Output added");
let mut result = output_builder.build_best_mode(Output); let result = output_builder.build_best_mode(Output);
with_handles!([(compositor: {compositor_handle})] => {
let compositor_state: &mut CompositorState = compositor.data.downcast_mut().unwrap(); {
let layout_handle = &mut compositor_state.layout_handle; use compositor_handle as compositor;
let cursor_handle = &mut compositor_state.cursor_handle; let state: &mut CompositorState = compositor.data.downcast_mut().unwrap();
let xcursor_manager = &mut compositor_state.xcursor_manager;
// TODO use output config if present instead of auto let xcursor_manager = &mut state.xcursor_manager;
with_handles!([ let layout_handle = &state.layout_handle;
(layout: {layout_handle}), let cursor_handle = &state.cursor_handle;
(cursor: {cursor_handle}), let output_handle = &result.output;
(output: {&mut result.output})
] => { use cursor_handle as cursor;
use layout_handle as layout;
use output_handle as output;
layout.add_auto(output); layout.add_auto(output);
cursor.attach_output_layout(layout); cursor.attach_output_layout(layout);
xcursor_manager.load(output.scale()); xcursor_manager.load(output.scale());
xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor); xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
let (x, y) = cursor.coords(); let (x, y) = cursor.coords();
cursor.warp(None, x, y); cursor.warp(None, x, y);
}).unwrap(); }
Some(result)
}) Some(result)
.unwrap()
} }

View file

@ -1,3 +1,6 @@
mod manager; mod manager;
mod output;
pub use self::manager::*; pub use self::manager::*;
use self::output::*;

62
src/output/output.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::CompositorState;
use wlroots::{
area::{Area, Origin, Size},
compositor, output,
render::{matrix, Renderer},
utils::current_time,
wlroots_dehandle,
};
pub struct Output;
impl output::Handler for Output {
#[wlroots_dehandle(compositor, output)]
fn on_frame(&mut self, compositor_handle: compositor::Handle, output_handle: output::Handle) {
use compositor_handle as compositor;
use output_handle as output;
let state: &mut CompositorState = compositor.data.downcast_mut().unwrap();
let renderer = compositor
.renderer
.as_mut()
.expect("Compositor was not loaded with a renderer");
let mut render_context = renderer.render(output, None);
render_context.clear([0.45, 0.25, 0.25, 1.0]);
render_shells(state, &mut render_context)
}
}
#[wlroots_dehandle(shell, surface, layout)]
fn render_shells(state: &mut CompositorState, renderer: &mut Renderer) {
let shells = state.shells.clone();
let layout_handle = &state.layout_handle;
for shell_handle in shells {
use shell_handle as shell;
let surface_handle = shell.surface();
use layout_handle as layout;
use surface_handle as surface;
let (width, height) = surface.current_state().size();
let (render_width, render_height) = (
width * renderer.output.scale() as i32,
height * renderer.output.scale() as i32,
);
let (lx, ly) = (0.0, 0.0);
let render_box = Area::new(
Origin::new(lx as i32, ly as i32),
Size::new(render_width, render_height),
);
if layout.intersects(renderer.output, render_box) {
let transform = renderer.output.get_transform().invert();
let matrix = matrix::project_box(
render_box,
transform,
0.0,
renderer.output.transform_matrix(),
);
if let Some(texture) = surface.texture().as_ref() {
renderer.render_texture_with_matrix(texture, matrix);
}
surface.send_frame_done(current_time());
}
}
}

1
src/shells/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod xdg_v6;

62
src/shells/xdg_v6.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::CompositorState;
use log::debug;
use wlroots::{compositor, shell::xdg_shell_v6, surface, utils::Handleable, wlroots_dehandle};
pub fn build() -> xdg_shell_v6::manager::Builder {
xdg_shell_v6::manager::Builder::default().surface_added(surface_added)
}
struct XdgShellV6Handler;
impl xdg_shell_v6::Handler for XdgShellV6Handler {
#[wlroots_dehandle(compositor)]
fn destroyed(
&mut self,
compositor_handle: compositor::Handle,
shell_handle: xdg_shell_v6::Handle,
) {
use compositor_handle as compositor;
let state: &mut CompositorState = compositor.downcast();
let weak = shell_handle;
if let Some(index) = state.shells.iter().position(|s| *s == weak) {
state.shells.remove(index);
}
}
}
struct Surface;
impl surface::Handler for Surface {
fn on_commit(&mut self, _: compositor::Handle, surface_handle: surface::Handle) {
debug!("Commiting for surface {:?}", surface_handle);
}
}
#[wlroots_dehandle(compositor, shell, layout, output)]
fn surface_added(
compositor_handle: compositor::Handle,
shell_handle: xdg_shell_v6::Handle,
) -> (
Option<Box<xdg_shell_v6::Handler>>,
Option<Box<surface::Handler>>,
) {
{
use compositor_handle as compositor;
use shell_handle as shell;
shell.ping();
let state: &mut CompositorState = compositor.downcast();
state.shells.push(shell.weak_reference());
log::warn!("shells.len(): {}", state.shells.len());
let layout_handle = &state.layout_handle;
use layout_handle as layout;
for (output_handle, _) in layout.outputs() {
use output_handle as output;
output.schedule_frame()
}
}
(Some(Box::new(XdgShellV6Handler)), Some(Box::new(Surface)))
}