1
0
Fork 0
forked from wry/wry
wry/src/config.rs

279 lines
8.2 KiB
Rust

mod handler;
#[cfg(feature = "it")]
use crate::it::test_config::TEST_CONFIG_ENTRY;
use {
crate::{
backend::{ConnectorId, DrmDeviceId, InputDeviceId},
config::handler::ConfigProxyHandler,
ifs::wl_seat::SeatId,
state::State,
tree::{TileState, ToplevelData, ToplevelIdentifier},
utils::{
clonecell::CloneCell,
numcell::NumCell,
ptr_ext::PtrExt,
},
},
jay_config::{
protocol::{
ClientMessage, ConfigEntry, InitMessage, ServerFeature, ServerHandler, ServerMessage,
Unref, V1InitMessage, VERSION, handle_client_message, init_client, unref_client,
},
input::{InputDevice, Seat, SwitchEvent},
keyboard::{mods::Modifiers, syms::KeySym},
video::{Connector, DrmDevice},
window::{self},
},
std::{cell::Cell, mem, ptr, rc::Rc},
};
pub struct ConfigProxy {
handler: CloneCell<Option<Rc<ConfigProxyHandler>>>,
}
impl ConfigProxy {
fn send(&self, msg: &ServerMessage) {
if let Some(handler) = self.handler.get() {
handler.send(msg);
}
}
pub fn destroy(&self) {
if let Some(handler) = self.handler.take() {
unsafe {
handler.do_drop();
(handler.unref)(handler.client_data.get());
}
}
}
pub fn invoke_shortcut(&self, seat: SeatId, shortcut: &InvokedShortcut) {
let msg = if shortcut.unmasked_mods == shortcut.effective_mods {
ServerMessage::InvokeShortcut {
seat: Seat(seat.raw() as _),
mods: shortcut.effective_mods,
sym: shortcut.sym,
}
} else {
ServerMessage::InvokeShortcut2 {
seat: Seat(seat.raw() as _),
unmasked_mods: shortcut.unmasked_mods,
effective_mods: shortcut.effective_mods,
sym: shortcut.sym,
}
};
self.send(&msg);
}
pub fn new_drm_dev(&self, dev: DrmDeviceId) {
self.send(&ServerMessage::NewDrmDev {
device: DrmDevice(dev.raw() as _),
});
}
pub fn del_drm_dev(&self, dev: DrmDeviceId) {
self.send(&ServerMessage::DelDrmDev {
device: DrmDevice(dev.raw() as _),
});
}
pub fn new_connector(&self, connector: ConnectorId) {
self.send(&ServerMessage::NewConnector {
device: Connector(connector.raw() as _),
});
}
pub fn del_connector(&self, connector: ConnectorId) {
self.send(&ServerMessage::DelConnector {
device: Connector(connector.raw() as _),
});
}
pub fn connector_connected(&self, connector: ConnectorId) {
self.send(&ServerMessage::ConnectorConnect {
device: Connector(connector.raw() as _),
});
}
pub fn connector_disconnected(&self, connector: ConnectorId) {
self.send(&ServerMessage::ConnectorDisconnect {
device: Connector(connector.raw() as _),
});
}
pub fn new_input_device(&self, dev: InputDeviceId) {
self.send(&ServerMessage::NewInputDevice {
device: InputDevice(dev.raw() as _),
});
}
pub fn del_input_device(&self, dev: InputDeviceId) {
self.send(&ServerMessage::DelInputDevice {
device: InputDevice(dev.raw() as _),
});
}
pub fn graphics_initialized(&self) {
self.send(&ServerMessage::GraphicsInitialized);
}
pub fn devices_enumerated(&self) {
self.send(&ServerMessage::DevicesEnumerated);
}
pub fn clear(&self) {
self.send(&ServerMessage::Clear);
}
pub fn idle(&self) {
self.send(&ServerMessage::Idle);
}
pub fn switch_event(&self, seat: SeatId, input_device: InputDeviceId, event: SwitchEvent) {
self.send(&ServerMessage::SwitchEvent {
seat: Seat(seat.raw() as _),
input_device: InputDevice(input_device.raw() as _),
event,
});
}
pub fn toplevel_removed(&self, id: ToplevelIdentifier) {
let Some(handler) = self.handler.get() else {
return;
};
if let Some(win) = handler.windows_from_tl_id.remove(&id) {
handler.windows_to_tl_id.remove(&win);
}
}
pub fn auto_focus(&self, data: &ToplevelData) -> bool {
let Some(handler) = self.handler.get() else {
return true;
};
handler.auto_focus(data)
}
pub fn initial_tile_state(&self, data: &ToplevelData) -> Option<TileState> {
self.handler.get()?.initial_tile_state(data)
}
}
impl Drop for ConfigProxy {
fn drop(&mut self) {
self.destroy();
}
}
unsafe fn default_client_init(
srv_data: *const u8,
srv_unref: Unref,
srv_handler: ServerHandler,
msg: InitMessage,
) -> *const u8 {
fn configure() {
jay_toml_config::configure();
}
unsafe {
init_client(srv_data, srv_unref, srv_handler, msg, configure)
}
}
impl ConfigProxy {
fn new(entry: &ConfigEntry, state: &Rc<State>) -> Self {
let version = entry.version.min(VERSION);
let data = Rc::new(ConfigProxyHandler {
client_data: Cell::new(ptr::null()),
dropped: Cell::new(false),
_version: version,
unref: entry.unref,
handle_msg: entry.handle_msg,
state: state.clone(),
next_id: NumCell::new(1),
keymaps: Default::default(),
workspace_ids: NumCell::new(1),
workspaces_by_name: Default::default(),
workspaces_by_id: Default::default(),
timer_ids: NumCell::new(1),
timers_by_name: Default::default(),
timers_by_id: Default::default(),
pollable_id: Default::default(),
pollables: Default::default(),
window_ids: NumCell::new(1),
windows_from_tl_id: Default::default(),
windows_to_tl_id: Default::default(),
client_matcher_ids: NumCell::new(1),
client_matchers: Default::default(),
client_matcher_cache: Default::default(),
client_matcher_leafs: Default::default(),
window_matcher_ids: NumCell::new(1),
window_matchers: Default::default(),
window_matcher_cache: Default::default(),
window_matcher_leafs: Default::default(),
window_matcher_std_kinds: state.tl_matcher_manager.kind(window::CLIENT_WINDOW),
window_matcher_no_auto_focus: Default::default(),
window_matcher_initial_tile_state: Default::default(),
});
let init_msg = InitMessage::V1(V1InitMessage {});
unsafe {
let client_data = (entry.init)(
Rc::into_raw(data.clone()) as _,
unref,
handle_msg,
init_msg,
);
data.client_data.set(client_data);
}
Self {
handler: CloneCell::new(Some(data)),
}
}
pub fn configure(&self, reload: bool) {
self.send(&ServerMessage::Features {
features: vec![ServerFeature::MOD_MASK, ServerFeature::SHOW_WORKSPACE_ON],
});
self.send(&ServerMessage::Configure { reload });
}
pub fn default(state: &Rc<State>) -> Self {
let entry = ConfigEntry {
version: VERSION,
init: default_client_init,
unref: unref_client,
handle_msg: handle_client_message,
};
Self::new(&entry, state)
}
#[cfg(feature = "it")]
pub fn for_test(state: &Rc<State>) -> Self {
Self::new(&TEST_CONFIG_ENTRY, state)
}
}
unsafe fn unref(data: *const u8) {
let server = data as *const ConfigProxyHandler;
unsafe {
drop(Rc::from_raw(server));
}
}
unsafe fn handle_msg(data: *const u8, msg: &ClientMessage<'_>) {
unsafe {
let server = (data as *const ConfigProxyHandler).deref();
if server.dropped.get() {
return;
}
let rc = Rc::from_raw(server);
rc.handle_request(msg);
mem::forget(rc);
}
}
pub struct InvokedShortcut {
pub unmasked_mods: Modifiers,
pub effective_mods: Modifiers,
pub sym: KeySym,
}