ltk/platform/wayland/state.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>
use smithay_client_toolkit::
{
activation::ActivationState,
compositor::CompositorState,
data_device_manager::{ DataDeviceManagerState, data_device::DataDevice, data_source::CopyPasteSource },
foreign_toplevel_list::ForeignToplevelList,
output::OutputState,
registry::RegistryState,
seat::{ SeatState, pointer::cursor_shape::CursorShapeManager },
shell::{ wlr_layer::LayerShell, xdg::XdgShell },
shm::Shm,
session_lock::SessionLock,
subcompositor::SubcompositorState,
};
use smithay_client_toolkit::reexports::client::
{
protocol::{ wl_keyboard::WlKeyboard, wl_output::WlOutput, wl_pointer::WlPointer, wl_touch::WlTouch },
QueueHandle,
};
use smithay_client_toolkit::reexports::protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::WpCursorShapeDeviceV1;
use wayland_protocols::wp::text_input::zv3::client::
{
zwp_text_input_manager_v3::ZwpTextInputManagerV3,
zwp_text_input_v3::ZwpTextInputV3,
};
use std::collections::HashMap;
use std::sync::Arc;
use crate::app::App;
use crate::egl_context::EglContext;
use crate::app::SubsurfaceId;
use crate::event_loop::AppData;
use crate::render::Canvas;
use super::data_device::DropPayload;
use super::primary_selection::PrimarySelection;
use super::session::SessionRuntime;
use super::subsurface::SubsurfaceSlot;
/// The Wayland protocol state the runtime's requests go through: globals, seat devices, the serials later requests quote and the queue new objects are created on.
pub( crate ) struct WaylandPlatform<A: App>
{
pub registry_state: RegistryState,
pub seat_state: SeatState,
pub output_state: OutputState,
pub compositor_state: CompositorState,
/// `None` when the compositor does not advertise `wl_subcompositor`.
pub subcompositor: Option<SubcompositorState>,
pub shm: Shm,
/// Process-wide EGL context. `None` when EGL failed to initialise or `LTK_FORCE_SOFTWARE=1`; every surface then draws through the SHM pool.
pub egl_context: Option<Arc<EglContext>>,
pub session_lock: Option<SessionLock>,
#[ allow( dead_code ) ]
pub xdg_shell: Option<XdgShell>,
/// Shared by the main surface and every overlay; `None` when the compositor does not advertise the protocol.
pub layer_shell: Option<LayerShell>,
pub keyboard: Option<WlKeyboard>,
pub pointer: Option<WlPointer>,
pub touch: Option<WlTouch>,
/// `None` when the compositor does not advertise `wp_cursor_shape_v1`; the compositor's default cursor then stays.
pub cursor_shape_manager: Option<CursorShapeManager>,
/// Present once the compositor supports cursor shapes and the seat has a pointer.
pub cursor_shape_device: Option<WpCursorShapeDeviceV1>,
/// Last `wl_pointer.enter` serial, which every `set_shape` must quote.
pub last_pointer_enter_serial: u32,
/// Last left or middle press, which an interactive move or resize quotes.
pub last_pointer_serial: u32,
/// Last serial of any input event, which `xdg_popup.grab` and setting a selection quote.
pub last_input_serial: u32,
pub text_input_manager: Option<ZwpTextInputManagerV3>,
pub text_input: Option<ZwpTextInputV3>,
/// `xdg-activation-v1`, used on the first configure to honour `XDG_ACTIVATION_TOKEN` and for [`App::request_activation_token`].
pub activation_state: Option<ActivationState>,
/// Honoured once, after the first configure of the main surface.
pub activation_token_pending: Option<String>,
/// `xdg-session-management-v1` proxies and the on-disk store; the store is `None` when persistence is off (layer or lock surfaces, unusable app id, concurrent instance, or after `replaced`).
pub session: SessionRuntime,
/// `None` when the compositor does not advertise `wl_data_device_manager`; copy and paste then stay within the process.
pub data_device_manager: Option<DataDeviceManagerState>,
/// Created with the first seat that has a keyboard or a pointer.
pub data_device: Option<DataDevice>,
/// The selection we publish, held so each paste from another client can be served the clipboard text.
pub clipboard_source: Option<CopyPasteSource>,
pub primary: PrimarySelection,
/// Selections other clients set, read by a worker thread and drained into `AppData::clipboard` once per iteration.
pub clipboard_inbox_tx: std::sync::mpsc::Sender<String>,
pub clipboard_inbox_rx: std::sync::mpsc::Receiver<String>,
/// A drag from another client: where it is over our surface, in logical coordinates, and the type negotiated on `enter`. Cleared on `leave` and after the drop.
pub drop_position: Option<( f64, f64 )>,
pub drop_mime: Option<String>,
/// What other clients drop on our surfaces, read by a worker thread.
pub drop_inbox_tx: std::sync::mpsc::Sender<DropPayload>,
pub drop_inbox_rx: std::sync::mpsc::Receiver<DropPayload>,
/// First-configure latch for `App::start_fullscreen`: Mutter ignores a fullscreen request sent before the window is mapped.
pub pending_fullscreen: bool,
/// First-configure latch: clears `max_size` once the compositor has honoured the pinned initial size.
pub pending_size_hint_unpin: bool,
/// First-configure latch: check the size hint against the screen.
pub pending_size_hint_fit: bool,
/// The size hint once shrunk to fit the screen; replaces the app's.
pub fitted_size_hint: Option<( u32, u32 )>,
/// GLES canvases of destroyed overlays, reused by the next overlay.
pub canvas_pool: Vec<Canvas>,
/// `ext-foreign-toplevel-list-v1`; yields no toplevels when the compositor does not advertise it.
pub foreign_toplevel_list: ForeignToplevelList,
/// Output the main surface was created on, so a later `new_output` for the same output does not add a duplicate secondary surface.
pub main_output: Option<WlOutput>,
/// Input-transparent child surfaces keyed by their stable [`SubsurfaceId`], reconciled each frame from [`App::subsurfaces`].
pub subsurfaces: HashMap<SubsurfaceId, SubsurfaceSlot>,
/// One GLES canvas for every subsurface raster, so a subsurface dropped and re-created (a lazily emitted sliding panel) does not recompile the shader programs, hundreds of ms on a mobile GPU, each time it reappears.
pub subsurface_gles_canvas: Option<Canvas>,
pub qh: QueueHandle<AppData<A>>,
}