2023-01-13 21:53:07 +01:00
|
|
|
use std::{
|
2023-02-08 22:53:41 +01:00
|
|
|
cmp::max,
|
|
|
|
|
default::Default,
|
2023-01-13 21:53:07 +01:00
|
|
|
env,
|
2023-01-16 00:25:34 +01:00
|
|
|
rc::Rc,
|
|
|
|
|
sync::{Arc, Mutex},
|
2023-01-13 21:53:07 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use wayland_client::{
|
|
|
|
|
protocol::{
|
2023-02-08 22:53:41 +01:00
|
|
|
wl_buffer, wl_compositor, wl_keyboard, wl_pointer, wl_registry, wl_seat, wl_shm,
|
|
|
|
|
wl_shm_pool, wl_subcompositor, wl_subsurface, wl_surface,
|
2023-01-13 21:53:07 +01:00
|
|
|
},
|
|
|
|
|
Connection, Dispatch, QueueHandle, WEnum,
|
|
|
|
|
};
|
|
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
use wayland_protocols::{
|
2023-02-08 22:53:41 +01:00
|
|
|
wp::{
|
|
|
|
|
single_pixel_buffer::v1::client::wp_single_pixel_buffer_manager_v1,
|
|
|
|
|
viewporter::client::{wp_viewport, wp_viewporter},
|
|
|
|
|
},
|
2023-02-06 18:34:07 +01:00
|
|
|
xdg::{
|
|
|
|
|
activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1},
|
|
|
|
|
shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base},
|
|
|
|
|
},
|
2023-01-13 21:53:07 +01:00
|
|
|
};
|
|
|
|
|
|
2023-02-08 22:53:41 +01:00
|
|
|
use wayland_protocols_wlr::layer_shell::v1::client::{zwlr_layer_shell_v1, zwlr_layer_surface_v1};
|
2023-02-04 14:42:29 +01:00
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
use crate::{
|
|
|
|
|
buffer::BufferManager,
|
2023-02-13 18:49:44 +01:00
|
|
|
config::OperationMode,
|
2023-02-08 22:53:41 +01:00
|
|
|
event::{Event, Events, PointerButton, PointerEvent},
|
2023-01-16 00:25:34 +01:00
|
|
|
fonts::{FontMap, MaybeFontMap},
|
2023-02-13 17:39:54 +01:00
|
|
|
keyboard::{Keyboard, RepeatMessage},
|
2023-01-16 00:25:34 +01:00
|
|
|
widgets::{Geometry, Layout, Widget, WidgetUpdater},
|
2023-01-13 21:53:07 +01:00
|
|
|
};
|
|
|
|
|
|
2023-02-13 17:39:54 +01:00
|
|
|
use calloop::channel::Sender;
|
|
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct MainSurface {
|
|
|
|
|
pub wl_surface: Option<wl_surface::WlSurface>,
|
|
|
|
|
xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>,
|
|
|
|
|
layer_surface: Option<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct BackgroundSurface {
|
|
|
|
|
wl_surface: Option<wl_surface::WlSurface>,
|
|
|
|
|
subsurface: Option<wl_subsurface::WlSubsurface>,
|
|
|
|
|
viewport: Option<wp_viewport::WpViewport>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct Protocols {
|
|
|
|
|
wl_shm: Option<wl_shm::WlShm>,
|
|
|
|
|
xdg_activation: Option<xdg_activation_v1::XdgActivationV1>,
|
|
|
|
|
viewporter: Option<wp_viewporter::WpViewporter>,
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
pub struct State {
|
2023-02-04 14:42:29 +01:00
|
|
|
mode: OperationMode,
|
2023-11-10 13:58:56 +01:00
|
|
|
background: Option<u32>,
|
2023-02-06 18:34:07 +01:00
|
|
|
pub main_surface: MainSurface,
|
|
|
|
|
pub bg_surface: BackgroundSurface,
|
|
|
|
|
pub protocols: Protocols,
|
2023-01-13 21:53:07 +01:00
|
|
|
pub running: bool,
|
|
|
|
|
pub dirty: bool,
|
2023-01-16 00:25:34 +01:00
|
|
|
activated: bool,
|
2023-01-13 21:53:07 +01:00
|
|
|
pub configured: bool,
|
|
|
|
|
pub dimensions: (i32, i32),
|
|
|
|
|
pub bufmgr: BufferManager,
|
|
|
|
|
pub widgets: Vec<Box<dyn Widget>>,
|
2023-02-06 18:34:07 +01:00
|
|
|
pub keyboard: Keyboard,
|
2023-02-13 17:39:54 +01:00
|
|
|
pub keyrepeat_sender: Sender<RepeatMessage>,
|
2023-02-02 23:52:59 +01:00
|
|
|
pointer: Option<(f64, f64)>,
|
2023-01-13 21:53:07 +01:00
|
|
|
pub fonts: MaybeFontMap,
|
2023-01-16 00:25:34 +01:00
|
|
|
pub events: Arc<Mutex<Events>>,
|
|
|
|
|
layout: Rc<Box<dyn Layout>>,
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl State {
|
2023-01-16 00:25:34 +01:00
|
|
|
pub fn new(
|
2023-02-04 14:42:29 +01:00
|
|
|
mode: OperationMode,
|
2023-11-10 13:58:56 +01:00
|
|
|
background: Option<u32>,
|
2023-01-16 00:25:34 +01:00
|
|
|
widgets: Vec<Box<dyn Widget>>,
|
|
|
|
|
layout: Rc<Box<dyn Layout>>,
|
|
|
|
|
fonts: MaybeFontMap,
|
|
|
|
|
events: Arc<Mutex<Events>>,
|
2023-02-13 17:39:54 +01:00
|
|
|
keyrepeat_sender: Sender<RepeatMessage>,
|
2023-01-16 00:25:34 +01:00
|
|
|
) -> State {
|
|
|
|
|
State {
|
2023-02-06 18:34:07 +01:00
|
|
|
protocols: Default::default(),
|
|
|
|
|
bg_surface: Default::default(),
|
|
|
|
|
main_surface: Default::default(),
|
2023-01-16 00:25:34 +01:00
|
|
|
running: true,
|
|
|
|
|
dirty: true,
|
|
|
|
|
activated: false,
|
|
|
|
|
configured: false,
|
|
|
|
|
dimensions: (320, 240),
|
|
|
|
|
bufmgr: BufferManager::new(),
|
|
|
|
|
keyboard: Keyboard::new(),
|
2023-02-02 23:52:59 +01:00
|
|
|
pointer: None,
|
2023-02-13 17:39:54 +01:00
|
|
|
keyrepeat_sender,
|
2023-02-04 14:42:29 +01:00
|
|
|
mode,
|
2023-11-10 13:58:56 +01:00
|
|
|
background,
|
2023-01-16 00:25:34 +01:00
|
|
|
widgets,
|
|
|
|
|
fonts,
|
|
|
|
|
events,
|
|
|
|
|
layout,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
pub fn add_buffer(&mut self, qh: &QueueHandle<Self>) {
|
|
|
|
|
self.bufmgr.add_buffer(
|
2023-02-06 18:34:07 +01:00
|
|
|
self.protocols.wl_shm.as_ref().expect("missing wl_shm"),
|
2023-01-13 21:53:07 +01:00
|
|
|
self.dimensions,
|
|
|
|
|
qh,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn activate(&mut self, qh: &QueueHandle<Self>) {
|
|
|
|
|
let key = match env::var("XDG_ACTIVATION_TOKEN") {
|
|
|
|
|
Ok(token) => token,
|
|
|
|
|
Err(_) => return,
|
|
|
|
|
};
|
2023-02-08 22:53:41 +01:00
|
|
|
match (
|
|
|
|
|
&self.main_surface.wl_surface,
|
|
|
|
|
&self.protocols.xdg_activation,
|
|
|
|
|
) {
|
2023-01-13 21:53:07 +01:00
|
|
|
(Some(surface), Some(activation)) => {
|
|
|
|
|
activation.activate(key, surface);
|
|
|
|
|
let activation_token = activation.get_activation_token(qh, ());
|
|
|
|
|
activation_token.commit();
|
|
|
|
|
env::remove_var("XDG_ACTIVATION_TOKEN");
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 00:25:34 +01:00
|
|
|
impl WidgetUpdater for State {
|
|
|
|
|
fn geometry_update(
|
|
|
|
|
&mut self,
|
|
|
|
|
idx: usize,
|
|
|
|
|
fonts: &mut FontMap,
|
|
|
|
|
geometry: &Geometry,
|
|
|
|
|
) -> Geometry {
|
|
|
|
|
self.widgets[idx].geometry_update(fonts, geometry)
|
|
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
|
|
|
|
|
fn minimum_size(&mut self, idx: usize, fonts: &mut FontMap) -> Geometry {
|
|
|
|
|
self.widgets[idx].minimum_size(fonts)
|
|
|
|
|
}
|
2023-01-16 00:25:34 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
impl Dispatch<wl_registry::WlRegistry, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
registry: &wl_registry::WlRegistry,
|
|
|
|
|
event: wl_registry::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
qh: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
if let wl_registry::Event::Global {
|
|
|
|
|
name, interface, ..
|
|
|
|
|
} = event
|
|
|
|
|
{
|
|
|
|
|
match &interface[..] {
|
|
|
|
|
"wl_compositor" => {
|
|
|
|
|
let compositor =
|
2023-02-04 14:42:29 +01:00
|
|
|
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 5, qh, ());
|
2023-02-06 18:34:07 +01:00
|
|
|
let main_surface = compositor.create_surface(qh, ());
|
|
|
|
|
let bg_surface = compositor.create_surface(qh, ());
|
|
|
|
|
state.main_surface.wl_surface = Some(main_surface);
|
|
|
|
|
state.bg_surface.wl_surface = Some(bg_surface);
|
2023-01-13 21:53:07 +01:00
|
|
|
state.activate(qh);
|
2023-02-06 18:34:07 +01:00
|
|
|
}
|
|
|
|
|
"wl_subcompositor" => {
|
|
|
|
|
let subcompositor =
|
|
|
|
|
registry.bind::<wl_subcompositor::WlSubcompositor, _, _>(name, 1, qh, ());
|
2023-01-13 21:53:07 +01:00
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
match (&state.main_surface.wl_surface, &state.bg_surface.wl_surface) {
|
|
|
|
|
(Some(parent), Some(child)) => {
|
|
|
|
|
let subsurface = subcompositor.get_subsurface(child, parent, qh, ());
|
|
|
|
|
subsurface.place_below(parent);
|
|
|
|
|
state.bg_surface.subsurface = Some(subsurface);
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-02-06 18:34:07 +01:00
|
|
|
_ => todo!("handle early subcompositor creation"),
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"wl_shm" => {
|
2023-02-08 22:53:41 +01:00
|
|
|
state.protocols.wl_shm =
|
|
|
|
|
Some(registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ()));
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
"wl_seat" => {
|
2023-02-04 14:42:29 +01:00
|
|
|
registry.bind::<wl_seat::WlSeat, _, _>(name, 8, qh, ());
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
"xdg_wm_base" => {
|
|
|
|
|
if let OperationMode::XdgToplevel = state.mode {
|
|
|
|
|
let wm_base =
|
|
|
|
|
registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 2, qh, ());
|
|
|
|
|
match &state.main_surface.wl_surface {
|
|
|
|
|
Some(surface) => {
|
|
|
|
|
let xdg_surface = wm_base.get_xdg_surface(surface, qh, ());
|
|
|
|
|
let toplevel = xdg_surface.get_toplevel(qh, ());
|
|
|
|
|
toplevel.set_title("wldash".into());
|
2023-02-06 18:34:07 +01:00
|
|
|
|
2023-02-08 22:53:41 +01:00
|
|
|
surface.commit();
|
2023-02-06 18:34:07 +01:00
|
|
|
|
2023-02-08 22:53:41 +01:00
|
|
|
state.main_surface.xdg_surface = Some((xdg_surface, toplevel));
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("handle early xdg_shell creation"),
|
2023-02-06 18:34:07 +01:00
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"xdg_activation_v1" => {
|
2023-02-06 18:34:07 +01:00
|
|
|
state.protocols.xdg_activation = Some(
|
2023-01-13 21:53:07 +01:00
|
|
|
registry.bind::<xdg_activation_v1::XdgActivationV1, _, _>(name, 1, qh, ()),
|
|
|
|
|
);
|
|
|
|
|
state.activate(qh);
|
|
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
"zwlr_layer_shell_v1" => {
|
|
|
|
|
if let OperationMode::LayerSurface(size) = state.mode {
|
|
|
|
|
let layer_shell = registry
|
|
|
|
|
.bind::<zwlr_layer_shell_v1::ZwlrLayerShellV1, _, _>(name, 4, qh, ());
|
|
|
|
|
state.fonts.resolve();
|
|
|
|
|
let fonts = state.fonts.unwrap();
|
|
|
|
|
let layout = state.layout.clone();
|
|
|
|
|
let min_size = layout.minimum_size(&mut fonts.borrow_mut(), state);
|
|
|
|
|
match &state.main_surface.wl_surface {
|
|
|
|
|
Some(surface) => {
|
|
|
|
|
let layer_surface = layer_shell.get_layer_surface(
|
|
|
|
|
surface,
|
|
|
|
|
None,
|
|
|
|
|
zwlr_layer_shell_v1::Layer::Top,
|
|
|
|
|
"launcher".to_string(),
|
|
|
|
|
qh,
|
|
|
|
|
(),
|
|
|
|
|
);
|
|
|
|
|
layer_surface.set_keyboard_interactivity(
|
|
|
|
|
zwlr_layer_surface_v1::KeyboardInteractivity::Exclusive,
|
|
|
|
|
);
|
|
|
|
|
layer_surface.set_size(
|
|
|
|
|
max(size.0, min_size.width),
|
|
|
|
|
max(size.1, min_size.height),
|
|
|
|
|
);
|
2023-02-06 18:34:07 +01:00
|
|
|
|
2023-02-08 22:53:41 +01:00
|
|
|
surface.commit();
|
|
|
|
|
state.main_surface.layer_surface = Some(layer_surface);
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("handle early layer_shell creation"),
|
2023-02-06 18:34:07 +01:00
|
|
|
}
|
2023-02-04 14:42:29 +01:00
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-02-06 18:34:07 +01:00
|
|
|
"wp_viewporter" => {
|
2023-02-08 22:53:41 +01:00
|
|
|
let viewporter =
|
|
|
|
|
registry.bind::<wp_viewporter::WpViewporter, _, _>(name, 1, qh, ());
|
2023-02-06 18:34:07 +01:00
|
|
|
match &state.bg_surface.wl_surface {
|
|
|
|
|
Some(surface) => {
|
2023-02-08 22:53:41 +01:00
|
|
|
state.bg_surface.viewport =
|
|
|
|
|
Some(viewporter.get_viewport(surface, qh, ()));
|
|
|
|
|
}
|
2023-02-06 18:34:07 +01:00
|
|
|
_ => todo!("handle early viewporter creation"),
|
2023-02-04 16:52:32 +01:00
|
|
|
}
|
2023-02-06 18:34:07 +01:00
|
|
|
state.protocols.viewporter = Some(viewporter);
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-11-10 13:58:56 +01:00
|
|
|
"wp_single_pixel_buffer_manager_v1" if state.background.is_some() => {
|
2023-02-06 18:34:07 +01:00
|
|
|
let singlepixel = registry.bind::<wp_single_pixel_buffer_manager_v1::WpSinglePixelBufferManagerV1, _, _>(name, 1, qh, ());
|
|
|
|
|
match &state.bg_surface.wl_surface {
|
|
|
|
|
Some(surface) => {
|
2023-02-08 22:53:41 +01:00
|
|
|
let buffer =
|
2023-11-10 13:58:56 +01:00
|
|
|
singlepixel.create_u32_rgba_buffer(0, 0, 0, state.background.unwrap(), qh, ());
|
2023-02-06 18:34:07 +01:00
|
|
|
surface.attach(Some(&buffer), 0, 0);
|
|
|
|
|
surface.damage_buffer(0, 0, 1, 1);
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-02-06 18:34:07 +01:00
|
|
|
_ => todo!("handle early single_pixel_buffer creation"),
|
|
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wl_compositor::WlCompositor, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wl_compositor::WlCompositor,
|
|
|
|
|
_: wl_compositor::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
impl Dispatch<wl_subcompositor::WlSubcompositor, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wl_subcompositor::WlSubcompositor,
|
|
|
|
|
_: wl_subcompositor::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
impl Dispatch<wl_surface::WlSurface, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wl_surface::WlSurface,
|
|
|
|
|
_: wl_surface::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
impl Dispatch<wl_subsurface::WlSubsurface, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wl_subsurface::WlSubsurface,
|
|
|
|
|
_: wl_subsurface::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
impl Dispatch<wl_shm::WlShm, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wl_shm::WlShm,
|
|
|
|
|
_: wl_shm::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wl_shm_pool::WlShmPool, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wl_shm_pool::WlShmPool,
|
|
|
|
|
_: wl_shm_pool::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wl_buffer::WlBuffer, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
buffer: &wl_buffer::WlBuffer,
|
|
|
|
|
_: wl_buffer::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
for buf in state.bufmgr.buffers.iter_mut() {
|
|
|
|
|
if &buf.buffer == buffer {
|
|
|
|
|
buf.release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-04 14:42:29 +01:00
|
|
|
impl Dispatch<zwlr_layer_shell_v1::ZwlrLayerShellV1, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &zwlr_layer_shell_v1::ZwlrLayerShellV1,
|
|
|
|
|
_: zwlr_layer_shell_v1::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
2023-02-08 22:53:41 +01:00
|
|
|
) {
|
|
|
|
|
}
|
2023-02-04 14:42:29 +01:00
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
|
2023-02-04 14:42:29 +01:00
|
|
|
impl Dispatch<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
layer_surface: &zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
|
|
|
|
event: zwlr_layer_surface_v1::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
2023-02-08 22:53:41 +01:00
|
|
|
if let zwlr_layer_surface_v1::Event::Configure {
|
|
|
|
|
serial,
|
2023-08-22 13:17:08 +02:00
|
|
|
mut width,
|
|
|
|
|
mut height,
|
2023-02-08 22:53:41 +01:00
|
|
|
} = event
|
|
|
|
|
{
|
2023-02-04 14:42:29 +01:00
|
|
|
if (width, height) == (0, 0) {
|
2023-08-22 13:17:08 +02:00
|
|
|
if state.configured {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
(width, height) = (640, 480);
|
2023-02-04 14:42:29 +01:00
|
|
|
}
|
|
|
|
|
layer_surface.ack_configure(serial);
|
|
|
|
|
state.configured = true;
|
|
|
|
|
state.dirty = true;
|
2023-01-13 21:53:07 +01:00
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
let dim = (width as i32, height as i32);
|
|
|
|
|
|
2023-08-22 13:17:08 +02:00
|
|
|
if state.configured && state.dimensions == dim {
|
2023-02-06 18:34:07 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
state.bufmgr.clear_buffers();
|
|
|
|
|
state.dimensions = dim;
|
|
|
|
|
let fonts = state.fonts.unwrap();
|
|
|
|
|
let layout = state.layout.clone();
|
|
|
|
|
layout.geometry_update(
|
|
|
|
|
&mut fonts.borrow_mut(),
|
|
|
|
|
&Geometry {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
width: width as u32,
|
|
|
|
|
height: height as u32,
|
|
|
|
|
},
|
|
|
|
|
state,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
match (&state.bg_surface.wl_surface, &state.bg_surface.viewport) {
|
|
|
|
|
(Some(surface), Some(viewport)) => {
|
|
|
|
|
viewport.set_destination(dim.0, dim.1);
|
|
|
|
|
surface.commit();
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-02-06 18:34:07 +01:00
|
|
|
_ => todo!("handle early layer shell creation"),
|
2023-02-04 14:42:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
wm_base: &xdg_wm_base::XdgWmBase,
|
|
|
|
|
event: xdg_wm_base::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
if let xdg_wm_base::Event::Ping { serial } = event {
|
|
|
|
|
wm_base.pong(serial);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<xdg_surface::XdgSurface, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
xdg_surface: &xdg_surface::XdgSurface,
|
|
|
|
|
event: xdg_surface::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
if let xdg_surface::Event::Configure { serial, .. } = event {
|
|
|
|
|
xdg_surface.ack_configure(serial);
|
|
|
|
|
state.configured = true;
|
|
|
|
|
state.dirty = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<xdg_toplevel::XdgToplevel, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
_: &xdg_toplevel::XdgToplevel,
|
|
|
|
|
event: xdg_toplevel::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
match event {
|
|
|
|
|
xdg_toplevel::Event::Configure {
|
2023-08-22 13:17:08 +02:00
|
|
|
mut width,
|
|
|
|
|
mut height,
|
2023-01-13 21:53:07 +01:00
|
|
|
states,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
if (width, height) == (0, 0) {
|
2023-08-22 13:17:08 +02:00
|
|
|
if state.configured {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
(width, height) = (640, 480);
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
let activated = states
|
|
|
|
|
.iter()
|
|
|
|
|
.find(|&st| *st as u32 == xdg_toplevel::State::Activated as u32)
|
|
|
|
|
.is_some();
|
|
|
|
|
|
|
|
|
|
if activated {
|
|
|
|
|
state.activated = true;
|
|
|
|
|
} else if state.activated && !activated {
|
2023-02-14 00:04:58 +01:00
|
|
|
let ev = Event::FocusLost;
|
|
|
|
|
for widget in state.widgets.iter_mut() {
|
|
|
|
|
widget.event(&ev);
|
|
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-22 13:17:08 +02:00
|
|
|
if !state.configured || state.dimensions != (width, height) {
|
2023-05-20 17:34:52 +02:00
|
|
|
match (&state.bg_surface.wl_surface, &state.bg_surface.viewport) {
|
|
|
|
|
(Some(surface), Some(viewport)) => {
|
|
|
|
|
viewport.set_destination(width, height);
|
|
|
|
|
surface.commit();
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("handle early xdg creation"),
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
state.bufmgr.clear_buffers();
|
|
|
|
|
state.dimensions = (width, height);
|
|
|
|
|
state.fonts.resolve();
|
|
|
|
|
let fonts = state.fonts.unwrap();
|
2023-01-16 00:25:34 +01:00
|
|
|
let layout = state.layout.clone();
|
2023-01-13 21:53:07 +01:00
|
|
|
layout.geometry_update(
|
|
|
|
|
&mut fonts.borrow_mut(),
|
|
|
|
|
&Geometry {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
width: width as u32,
|
|
|
|
|
height: height as u32,
|
|
|
|
|
},
|
|
|
|
|
state,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
xdg_toplevel::Event::Close => {
|
|
|
|
|
state.running = false;
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wl_seat::WlSeat, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
seat: &wl_seat::WlSeat,
|
|
|
|
|
event: wl_seat::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
qh: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
if let wl_seat::Event::Capabilities {
|
|
|
|
|
capabilities: WEnum::Value(capabilities),
|
|
|
|
|
} = event
|
|
|
|
|
{
|
|
|
|
|
if capabilities.contains(wl_seat::Capability::Keyboard) {
|
|
|
|
|
seat.get_keyboard(qh, ());
|
|
|
|
|
}
|
2023-02-02 23:52:59 +01:00
|
|
|
if capabilities.contains(wl_seat::Capability::Pointer) {
|
|
|
|
|
seat.get_pointer(qh, ());
|
|
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
_: &wl_keyboard::WlKeyboard,
|
|
|
|
|
event: wl_keyboard::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
match event {
|
2023-02-13 18:49:44 +01:00
|
|
|
wl_keyboard::Event::Leave { .. } => {
|
|
|
|
|
state
|
|
|
|
|
.keyrepeat_sender
|
|
|
|
|
.send(RepeatMessage::StopRepeat)
|
|
|
|
|
.unwrap();
|
2023-02-13 17:39:54 +01:00
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
wl_keyboard::Event::Key {
|
|
|
|
|
key,
|
|
|
|
|
state: kbstate,
|
2023-02-13 17:39:54 +01:00
|
|
|
..
|
2023-01-13 21:53:07 +01:00
|
|
|
} => {
|
|
|
|
|
if key == 1 {
|
|
|
|
|
state.running = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-08-22 13:17:08 +02:00
|
|
|
state.keyboard.resolve();
|
2023-02-13 17:39:54 +01:00
|
|
|
let k = state.keyboard.key(key, kbstate);
|
|
|
|
|
let repeats = k.repeats;
|
2023-01-16 00:25:34 +01:00
|
|
|
let ev = Event::KeyEvent(k);
|
2023-01-13 21:53:07 +01:00
|
|
|
for widget in state.widgets.iter_mut() {
|
2023-01-16 00:25:34 +01:00
|
|
|
widget.event(&ev);
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
2023-02-13 17:39:54 +01:00
|
|
|
if repeats {
|
|
|
|
|
if let Event::KeyEvent(k) = ev {
|
2023-02-13 18:49:44 +01:00
|
|
|
state
|
|
|
|
|
.keyrepeat_sender
|
|
|
|
|
.send(RepeatMessage::KeyEvent(k))
|
|
|
|
|
.unwrap();
|
2023-02-13 17:39:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
state.dirty = true;
|
|
|
|
|
}
|
|
|
|
|
wl_keyboard::Event::Modifiers {
|
|
|
|
|
mods_depressed,
|
|
|
|
|
mods_latched,
|
|
|
|
|
mods_locked,
|
|
|
|
|
group,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
state
|
|
|
|
|
.keyboard
|
|
|
|
|
.modifiers(mods_depressed, mods_latched, mods_locked, group);
|
|
|
|
|
}
|
|
|
|
|
wl_keyboard::Event::Keymap { format, fd, size } => {
|
2023-01-16 00:25:34 +01:00
|
|
|
// TODO: Keymap loading blocks xdg configure, consider delaying
|
2023-01-13 21:53:07 +01:00
|
|
|
state.keyboard.keymap(format, fd, size);
|
|
|
|
|
}
|
2023-02-13 17:39:54 +01:00
|
|
|
wl_keyboard::Event::RepeatInfo { rate, delay } => {
|
2023-02-13 18:49:44 +01:00
|
|
|
state
|
|
|
|
|
.keyrepeat_sender
|
|
|
|
|
.send(RepeatMessage::RepeatInfo((rate as u32, delay as u32)))
|
|
|
|
|
.unwrap();
|
2023-02-13 17:39:54 +01:00
|
|
|
}
|
2023-01-13 21:53:07 +01:00
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
// TODO: Move to dedicated pointer module
|
2023-02-02 23:52:59 +01:00
|
|
|
const BTN_LEFT: u32 = 0x110;
|
|
|
|
|
const BTN_RIGHT: u32 = 0x111;
|
|
|
|
|
const BTN_MIDDLE: u32 = 0x112;
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wl_pointer::WlPointer, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
_: &wl_pointer::WlPointer,
|
|
|
|
|
event: wl_pointer::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
match event {
|
2023-02-08 22:53:41 +01:00
|
|
|
wl_pointer::Event::Enter {
|
|
|
|
|
surface_x,
|
|
|
|
|
surface_y,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
2023-02-02 23:52:59 +01:00
|
|
|
state.pointer = Some((surface_x, surface_y));
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
|
|
|
|
wl_pointer::Event::Motion {
|
|
|
|
|
surface_x,
|
|
|
|
|
surface_y,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
2023-02-02 23:52:59 +01:00
|
|
|
state.pointer = Some((surface_x, surface_y));
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
|
|
|
|
wl_pointer::Event::Leave { .. } => state.pointer = None,
|
|
|
|
|
wl_pointer::Event::Axis { axis, value, .. } => match state.pointer {
|
2023-02-02 23:52:59 +01:00
|
|
|
Some((x, y)) => {
|
|
|
|
|
let axis = match axis {
|
2023-02-08 22:53:41 +01:00
|
|
|
WEnum::Value(wl_pointer::Axis::VerticalScroll) => {
|
|
|
|
|
PointerButton::ScrollVertical(value)
|
|
|
|
|
}
|
|
|
|
|
WEnum::Value(wl_pointer::Axis::HorizontalScroll) => {
|
|
|
|
|
PointerButton::ScrollHorizontal(value)
|
|
|
|
|
}
|
2023-02-02 23:52:59 +01:00
|
|
|
_ => return,
|
|
|
|
|
};
|
|
|
|
|
let pos = (x as u32, y as u32);
|
|
|
|
|
for widget in state.widgets.iter_mut() {
|
|
|
|
|
let geo = widget.geometry();
|
|
|
|
|
if geo.contains(pos) {
|
|
|
|
|
let pos = (pos.0 - geo.x, pos.1 - geo.y);
|
2023-02-08 22:53:41 +01:00
|
|
|
let ev = Event::PointerEvent(PointerEvent {
|
2023-02-02 23:52:59 +01:00
|
|
|
button: axis,
|
|
|
|
|
pos: pos,
|
|
|
|
|
});
|
|
|
|
|
widget.event(&ev);
|
|
|
|
|
state.dirty = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-02-02 23:52:59 +01:00
|
|
|
_ => (),
|
|
|
|
|
},
|
2023-02-08 22:53:41 +01:00
|
|
|
wl_pointer::Event::Button {
|
|
|
|
|
button,
|
|
|
|
|
state: button_state,
|
|
|
|
|
..
|
|
|
|
|
} => match (button, button_state, state.pointer) {
|
2023-02-02 23:52:59 +01:00
|
|
|
(button, WEnum::Value(wl_pointer::ButtonState::Pressed), Some((x, y))) => {
|
|
|
|
|
let button = match button {
|
|
|
|
|
BTN_LEFT => PointerButton::Left,
|
|
|
|
|
BTN_RIGHT => PointerButton::Right,
|
|
|
|
|
BTN_MIDDLE => PointerButton::Middle,
|
|
|
|
|
_ => return,
|
|
|
|
|
};
|
|
|
|
|
let pos = (x as u32, y as u32);
|
|
|
|
|
for widget in state.widgets.iter_mut() {
|
|
|
|
|
let geo = widget.geometry();
|
|
|
|
|
if geo.contains(pos) {
|
|
|
|
|
let pos = (pos.0 - geo.x, pos.1 - geo.y);
|
2023-02-08 22:53:41 +01:00
|
|
|
let ev = Event::PointerEvent(PointerEvent {
|
2023-02-02 23:52:59 +01:00
|
|
|
button: button,
|
|
|
|
|
pos: pos,
|
|
|
|
|
});
|
|
|
|
|
widget.event(&ev);
|
|
|
|
|
state.dirty = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-08 22:53:41 +01:00
|
|
|
}
|
2023-02-02 23:52:59 +01:00
|
|
|
_ => (),
|
|
|
|
|
},
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-06 18:34:07 +01:00
|
|
|
impl Dispatch<wp_single_pixel_buffer_manager_v1::WpSinglePixelBufferManagerV1, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wp_single_pixel_buffer_manager_v1::WpSinglePixelBufferManagerV1,
|
|
|
|
|
_: wp_single_pixel_buffer_manager_v1::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wp_viewporter::WpViewporter, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wp_viewporter::WpViewporter,
|
|
|
|
|
_: wp_viewporter::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<wp_viewport::WpViewport, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &wp_viewport::WpViewport,
|
|
|
|
|
_: wp_viewport::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 21:53:07 +01:00
|
|
|
impl Dispatch<xdg_activation_v1::XdgActivationV1, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
_: &mut Self,
|
|
|
|
|
_: &xdg_activation_v1::XdgActivationV1,
|
|
|
|
|
_: xdg_activation_v1::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dispatch<xdg_activation_token_v1::XdgActivationTokenV1, ()> for State {
|
|
|
|
|
fn event(
|
|
|
|
|
state: &mut Self,
|
|
|
|
|
_: &xdg_activation_token_v1::XdgActivationTokenV1,
|
|
|
|
|
event: xdg_activation_token_v1::Event,
|
|
|
|
|
_: &(),
|
|
|
|
|
_: &Connection,
|
|
|
|
|
_: &QueueHandle<Self>,
|
|
|
|
|
) {
|
|
|
|
|
match event {
|
|
|
|
|
xdg_activation_token_v1::Event::Done { token } => {
|
2023-01-16 00:25:34 +01:00
|
|
|
let ev = Event::TokenUpdate(token);
|
2023-01-13 21:53:07 +01:00
|
|
|
for widget in state.widgets.iter_mut() {
|
2023-01-16 00:25:34 +01:00
|
|
|
widget.event(&ev);
|
2023-01-13 21:53:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|