// SPDX-License-Identifier: GPL-3.0-only /* * Copyright (c) 2024, Richard Acayan. All rights reserved. */ use crate::core::Button; use crate::core::Display; use crate::core::Graphics; use crate::core::Layout; use crate::wayland::Seat; use crate::wayland::Surface; use crate::wayland::VirtualKeyboard; use crate::wayland::wlr_layer_shell_unstable_v1::zwlr_layer_shell_v1; use crate::wayland::wlr_layer_shell_unstable_v1::zwlr_layer_surface_v1; use crate::wayland::fractional_scale_v1::wp_fractional_scale_manager_v1; use crate::wayland::fractional_scale_v1::wp_fractional_scale_v1; use crate::wayland::input_method_unstable_v2::zwp_input_method_manager_v2; use crate::wayland::input_method_unstable_v2::zwp_input_method_v2; use crate::wayland::viewporter::wp_viewporter; use crate::wayland::viewporter::wp_viewport; use crate::wayland::virtual_keyboard_unstable_v1::zwp_virtual_keyboard_manager_v1; use crate::wayland::virtual_keyboard_unstable_v1::zwp_virtual_keyboard_v1; use std::io::Error; use std::sync::Arc; use std::sync::Mutex; use wayland_client::Connection; use wayland_client::Dispatch; use wayland_client::Proxy; use wayland_client::QueueHandle; use wayland_client::WEnum; use wayland_client::globals::GlobalList; use wayland_client::globals::GlobalListContents; use wayland_client::protocol::wl_buffer; use wayland_client::protocol::wl_compositor; use wayland_client::protocol::wl_pointer; use wayland_client::protocol::wl_registry; use wayland_client::protocol::wl_seat; use wayland_client::protocol::wl_shm; use wayland_client::protocol::wl_shm_pool; use wayland_client::protocol::wl_surface; use wayland_client::protocol::wl_touch; pub struct Dispatcher { seat: Seat, VirtualKeyboard, Self>, gfx: Arc>>>, } impl Dispatcher { pub fn new(layout: Layout, queue: QueueHandle, globals: &GlobalList) -> Result { let shm = globals.bind(&queue, 1..=1, ()) .expect("Compositor must implement wl_shm"); let compositor = globals.bind(&queue, 4..=6, ()) .expect("Compositor must implement wl_compositor"); let seat = globals.bind(&queue, 5..=9, ()) .expect("Compositor must implement wl_seat"); let layer_shell = globals.bind(&queue, 3..=4, ()) .expect("Compositor must implement zwlr_layer_shell_v1"); let vk_man = globals.bind(&queue, 1..=1, ()) .expect("Compositor must implement zwp_virtual_keyboard_manager_v1"); let im_man: zwp_input_method_manager_v2::ZwpInputMethodManagerV2 = globals.bind(&queue, 1..=1, ()) .expect("Compositor must implement zwp_input_method_manager_v2"); let frac_scale_man = match globals.bind(&queue, 1..=1, ()) { Ok(g) => Some(g), Err(_) => None, }; let vper = match globals.bind(&queue, 1..=1, ()) { Ok(g) => Some(g), Err(_) => None, }; im_man.get_input_method(&seat, &queue, ()); let disp = Surface::new(queue.clone(), &shm, compositor, layer_shell, frac_scale_man, vper, 185)?; let gfx = Graphics::new(disp); let gfx = Mutex::new(gfx); let gfx = Arc::new(gfx); let vk = VirtualKeyboard::new(&queue, &vk_man, &seat); let seat = Seat::new(layout, vk, gfx.clone(), queue.clone(), seat); Ok(Dispatcher { seat, gfx, }) } #[inline(always)] pub fn button(&self) -> &Button, VirtualKeyboard> { self.seat.button() } pub fn dispatch_timers(&mut self) { self.seat.button_mut().dispatch_timers(); } fn show(&self) { let mut gfx = self.gfx.lock().unwrap(); gfx.display_mut().show(); } fn hide(&self) { let mut gfx = self.gfx.lock().unwrap(); gfx.display_mut().hide(); } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _buf: &wl_buffer::WlBuffer, evt: ::Event, data: &u32, _conn: &Connection, _qh: &QueueHandle) { match evt { wl_buffer::Event::Release => { let mut gfx = ctx.gfx.lock().unwrap(); gfx.display_mut().release(*data); }, _ => eprintln!("warn: unknown wl_buffer event emitted"), } } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _comp: &wl_compositor::WlCompositor, _evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown wl_compositor event emitted"); } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _ptr: &wl_pointer::WlPointer, evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { wl_pointer::Event::Motion { surface_x, surface_y, .. } => { ctx.seat.ptr_motion(surface_x, surface_y); }, wl_pointer::Event::Button { state: WEnum::Value(state), .. } => { ctx.seat.ptr_button(state); }, wl_pointer::Event::Frame => { ctx.seat.commit(); }, wl_pointer::Event::Enter { .. } => (), wl_pointer::Event::Leave { .. } => (), _ => eprintln!("warn: unknown wl_pointer event emitted"), }; } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _reg: &wl_registry::WlRegistry, _evt: ::Event, _data: &GlobalListContents, _conn: &Connection, _qh: &QueueHandle) { } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _seat: &wl_seat::WlSeat, evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { wl_seat::Event::Name { .. } => (), wl_seat::Event::Capabilities { capabilities: WEnum::Value(caps) } => { ctx.seat.set_capabilities(caps); }, _ => eprintln!("warn: unknown wl_seat event emitted"), }; } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _shm: &wl_shm::WlShm, evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { wl_shm::Event::Format { .. } => (), _ => eprintln!("warn: unknown wl_shm event emitted"), }; } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _pool: &wl_shm_pool::WlShmPool, _evt: ::Event, _data: &u32, _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown wl_shm_pool event emitted"); } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _pool: &wl_surface::WlSurface, evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { wl_surface::Event::PreferredBufferTransform { .. } => (), wl_surface::Event::PreferredBufferScale { .. } => (), // TODO _ => eprintln!("warn: unknown wl_surface event emitted"), } } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _ptr: &wl_touch::WlTouch, evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { wl_touch::Event::Down { id, x, y, .. } => { ctx.seat.touch_press(id as u32, x, y); }, wl_touch::Event::Motion { id, x, y, .. } => { ctx.seat.touch_pos(id as u32, x, y); }, wl_touch::Event::Up { id, .. } => { ctx.seat.touch_release(id as u32); }, wl_touch::Event::Frame => { ctx.seat.commit(); }, _ => eprintln!("warn: unknown wl_touch event emitted"), }; } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _pool: &wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1, _evt: wp_fractional_scale_manager_v1::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown wp_fractional_scale_manager_v1 event emitted"); } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _pool: &wp_fractional_scale_v1::WpFractionalScaleV1, evt: wp_fractional_scale_v1::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { wp_fractional_scale_v1::Event::PreferredScale { scale } => { let mut gfx = ctx.gfx.lock().unwrap(); if scale == gfx.display().scale() { return; } let old_scale = gfx.display().scale(); let (width, height) = gfx.display().size(); let (width, height) = (width * scale / old_scale, height * scale / old_scale); gfx.display_mut().update_scale(scale); if gfx.display().configured() { let layout = ctx.seat.layout(); let mod_state = ctx.seat.mod_state(); gfx.resize(layout, mod_state, width, height); let (width, height) = gfx.display().size(); let width = width as f64 * 120.0 / scale as f64; let height = height as f64 * 120.0 / scale as f64; ctx.seat.set_scale(layout.width() / width, layout.height() / height); } }, _ => eprintln!("warn: unknown wp_fractional_scale_v1 event emitted"), }; } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _pool: &wp_viewporter::WpViewporter, _evt: wp_viewporter::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown wp_viewporter event emitted"); } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _pool: &wp_viewport::WpViewport, _evt: wp_viewport::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown wp_viewport event emitted"); } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _pool: &zwlr_layer_shell_v1::ZwlrLayerShellV1, _evt: ::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown zwlr_layer_shell_v1 event emitted"); } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _surface: &zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, evt: zwlr_layer_surface_v1::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { zwlr_layer_surface_v1::Event::Configure { width, height, serial } => { let mut gfx = ctx.gfx.lock().unwrap(); gfx.display_mut().ack_configure(serial); let layout = ctx.seat.layout(); let mod_state = ctx.seat.mod_state(); let scale = gfx.display().scale() / 120; let (width, height) = (width * scale, height * scale); gfx.resize(layout, mod_state, width, height); let disp = gfx.display(); let scale = disp.scale() as f64; let (width, height) = disp.size(); let width = width as f64 * 120.0 / scale; let height = height as f64 * 120.0 / scale; ctx.seat.set_scale(layout.width() / width, layout.height() / height); }, _ => eprintln!("warn: unknown zwlr_layer_surface_v1 event emitted"), } } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _im_man: &zwp_input_method_manager_v2::ZwpInputMethodManagerV2, _evt: zwp_input_method_manager_v2::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown zwp_input_method_manager_v2 event emitted"); } } impl Dispatch for Dispatcher { fn event(ctx: &mut Dispatcher, _im: &zwp_input_method_v2::ZwpInputMethodV2, evt: zwp_input_method_v2::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { match evt { zwp_input_method_v2::Event::Activate => { ctx.show(); }, zwp_input_method_v2::Event::Deactivate => { ctx.hide(); }, zwp_input_method_v2::Event::TextChangeCause { .. } => (), zwp_input_method_v2::Event::ContentType { .. } => (), zwp_input_method_v2::Event::SurroundingText { .. } => (), zwp_input_method_v2::Event::Done => (), _ => eprintln!("warn: unknown zwp_input_method_v2 event emitted"), } } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _vk_man: &zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1, _evt: zwp_virtual_keyboard_manager_v1::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown zwp_virtual_keyboard_manager_v1 event emitted"); } } impl Dispatch for Dispatcher { fn event(_ctx: &mut Dispatcher, _vk: &zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1, _evt: zwp_virtual_keyboard_v1::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle) { eprintln!("warn: unknown zwp_virtual_keyboard_v1 event emitted"); } }