Basic xdg_shell_v6 handling
This commit is contained in:
parent
eb5efc4557
commit
a45075205c
9 changed files with 262 additions and 75 deletions
|
@ -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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
62
src/output/output.rs
Normal 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
1
src/shells/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod xdg_v6;
|
62
src/shells/xdg_v6.rs
Normal file
62
src/shells/xdg_v6.rs
Normal 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)))
|
||||||
|
}
|
Loading…
Reference in a new issue