fix(wayland): new API
This commit is contained in:
@@ -7,15 +7,22 @@ use crate::core::node_collections::LifeLinkedNodeMap;
|
|||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::nodes::fields::{find_field, FIELD_ALIAS_INFO};
|
use crate::nodes::fields::{find_field, FIELD_ALIAS_INFO};
|
||||||
use crate::nodes::spatial::find_spatial_parent;
|
use crate::nodes::spatial::find_spatial_parent;
|
||||||
use color_eyre::eyre::{ensure, eyre, Result};
|
use color_eyre::eyre::{bail, ensure, eyre, Result};
|
||||||
use glam::vec3a;
|
use glam::vec3a;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use mint::{Quaternion, Vector3};
|
use mint::{Quaternion, Vector3};
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use stardust_xr::schemas::flex::{deserialize, flexbuffers, serialize};
|
use stardust_xr::schemas::flex::{deserialize, flexbuffers, serialize};
|
||||||
use stardust_xr::values::Transform;
|
use stardust_xr::values::Transform;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref KEYMAPS: Mutex<FxHashMap<String, String>> = Mutex::new(FxHashMap::default());
|
||||||
|
}
|
||||||
|
|
||||||
static PULSE_SENDER_REGISTRY: Registry<PulseSender> = Registry::new();
|
static PULSE_SENDER_REGISTRY: Registry<PulseSender> = Registry::new();
|
||||||
pub static PULSE_RECEIVER_REGISTRY: Registry<PulseReceiver> = Registry::new();
|
pub static PULSE_RECEIVER_REGISTRY: Registry<PulseReceiver> = Registry::new();
|
||||||
|
|
||||||
@@ -231,6 +238,8 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
|||||||
let node = Node::create(client, "", "data", false);
|
let node = Node::create(client, "", "data", false);
|
||||||
node.add_local_signal("create_pulse_sender", create_pulse_sender_flex);
|
node.add_local_signal("create_pulse_sender", create_pulse_sender_flex);
|
||||||
node.add_local_signal("create_pulse_receiver", create_pulse_receiver_flex);
|
node.add_local_signal("create_pulse_receiver", create_pulse_receiver_flex);
|
||||||
|
node.add_local_method("register_keymap", register_keymap_flex);
|
||||||
|
node.add_local_method("get_keymap", get_keymap_flex);
|
||||||
node.add_to_scenegraph().map(|_| ())
|
node.add_to_scenegraph().map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,3 +295,36 @@ pub fn create_pulse_receiver_flex(
|
|||||||
PulseReceiver::add_to(&node, field, mask)?;
|
PulseReceiver::add_to(&node, field, mask)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn register_keymap_flex(
|
||||||
|
_node: &Node,
|
||||||
|
_calling_client: Arc<Client>,
|
||||||
|
message: Message,
|
||||||
|
) -> Result<Message> {
|
||||||
|
let keymap: String = deserialize(message.as_ref())?;
|
||||||
|
let mut keymaps = KEYMAPS.lock();
|
||||||
|
if let Some(found_keymap_id) = keymaps
|
||||||
|
.iter()
|
||||||
|
.filter(|(_k, v)| *v == &keymap)
|
||||||
|
.map(|(k, _v)| k)
|
||||||
|
.last()
|
||||||
|
{
|
||||||
|
return Ok(serialize(found_keymap_id)?.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let generated_id = nanoid!();
|
||||||
|
keymaps.insert(generated_id.clone(), keymap);
|
||||||
|
|
||||||
|
Ok(serialize(generated_id)?.into())
|
||||||
|
}
|
||||||
|
pub fn get_keymap_flex(
|
||||||
|
_node: &Node,
|
||||||
|
_calling_client: Arc<Client>,
|
||||||
|
message: Message,
|
||||||
|
) -> Result<Message> {
|
||||||
|
let keymap_id: &str = deserialize(message.as_ref())?;
|
||||||
|
let keymaps = KEYMAPS.lock();
|
||||||
|
let Some(keymap) = keymaps.get(keymap_id) else {bail!("Could not find keymap. Try registering it")};
|
||||||
|
|
||||||
|
Ok(serialize(keymap)?.into())
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ use glam::Mat4;
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{Deserializer, Error, SeqAccess, Visitor},
|
de::{Deserializer, Error, SeqAccess, Visitor},
|
||||||
ser::Serializer,
|
ser::Serializer,
|
||||||
Deserialize, Serialize,
|
Deserialize, Serialize,
|
||||||
};
|
};
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
|
||||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
use stardust_xr::schemas::flex::{deserialize, serialize};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@@ -29,20 +29,16 @@ lazy_static! {
|
|||||||
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
|
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
|
||||||
type_name: "panel",
|
type_name: "panel",
|
||||||
aliased_local_signals: vec![
|
aliased_local_signals: vec![
|
||||||
|
"start_data",
|
||||||
"apply_surface_material",
|
"apply_surface_material",
|
||||||
"close_toplevel",
|
"close_toplevel",
|
||||||
"auto_size_toplevel",
|
"auto_size_toplevel",
|
||||||
"set_toplevel_size_changed",
|
"set_toplevel_size",
|
||||||
"set_toplevel_state",
|
"set_toplevel_focused_visuals",
|
||||||
"set_toplevel_tiling",
|
|
||||||
"set_toplevel_bounds",
|
|
||||||
"set_maximize_enabled",
|
|
||||||
"set_minimize_enabled",
|
|
||||||
"set_fullscreen_enabled",
|
|
||||||
"set_window_menu_enabled",
|
|
||||||
"pointer_scroll",
|
|
||||||
"pointer_button",
|
|
||||||
"pointer_motion",
|
"pointer_motion",
|
||||||
|
"pointer_button",
|
||||||
|
"pointer_scroll",
|
||||||
|
"keyboard_keymap",
|
||||||
"keyboard_key",
|
"keyboard_key",
|
||||||
],
|
],
|
||||||
aliased_local_methods: vec![],
|
aliased_local_methods: vec![],
|
||||||
@@ -50,8 +46,7 @@ lazy_static! {
|
|||||||
"toplevel_parent_changed",
|
"toplevel_parent_changed",
|
||||||
"toplevel_title_changed",
|
"toplevel_title_changed",
|
||||||
"toplevel_app_id_changed",
|
"toplevel_app_id_changed",
|
||||||
"toplevel_window_menu",
|
"toplevel_fullscreen_active",
|
||||||
"recommend_toplevel_state",
|
|
||||||
"toplevel_move_request",
|
"toplevel_move_request",
|
||||||
"toplevel_resize_request",
|
"toplevel_resize_request",
|
||||||
"toplevel_size_changed",
|
"toplevel_size_changed",
|
||||||
@@ -155,40 +150,13 @@ pub struct ToplevelInfo {
|
|||||||
pub logical_rectangle: Geometry,
|
pub logical_rectangle: Geometry,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u32)]
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr)]
|
|
||||||
pub enum ToplevelState {
|
|
||||||
Floating,
|
|
||||||
Minimized,
|
|
||||||
UnMinimized,
|
|
||||||
Maximized,
|
|
||||||
UnMaximized,
|
|
||||||
Fullscreen,
|
|
||||||
UnFullscreen,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data on positioning a child
|
/// Data on positioning a child
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct ChildInfo {
|
pub struct ChildInfo {
|
||||||
pub uid: String,
|
|
||||||
pub parent: SurfaceID,
|
pub parent: SurfaceID,
|
||||||
pub geometry: Geometry,
|
pub geometry: Geometry,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize_repr)]
|
|
||||||
#[repr(u32)]
|
|
||||||
pub enum Edge {
|
|
||||||
None = 0,
|
|
||||||
Top = 1,
|
|
||||||
Bottom = 2,
|
|
||||||
Left = 4,
|
|
||||||
TopLeft = 5,
|
|
||||||
BottomLeft = 6,
|
|
||||||
Right = 8,
|
|
||||||
TopRight = 9,
|
|
||||||
BottomRight = 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The init data for the panel item.
|
/// The init data for the panel item.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct PanelItemInitData {
|
pub struct PanelItemInitData {
|
||||||
@@ -197,7 +165,7 @@ pub struct PanelItemInitData {
|
|||||||
/// Size of the toplevel surface in pixels.
|
/// Size of the toplevel surface in pixels.
|
||||||
pub toplevel: ToplevelInfo,
|
pub toplevel: ToplevelInfo,
|
||||||
/// Vector of childs that already exist
|
/// Vector of childs that already exist
|
||||||
pub children: Vec<ChildInfo>,
|
pub children: FxHashMap<String, ChildInfo>,
|
||||||
/// The surface, if any, that has exclusive input to the pointer.
|
/// The surface, if any, that has exclusive input to the pointer.
|
||||||
pub pointer_grab: Option<SurfaceID>,
|
pub pointer_grab: Option<SurfaceID>,
|
||||||
/// The surface, if any, that has exclusive input to the keyboard.
|
/// The surface, if any, that has exclusive input to the keyboard.
|
||||||
@@ -223,8 +191,7 @@ pub trait Backend: Send + Sync + 'static {
|
|||||||
scroll_steps: Option<Vector2<f32>>,
|
scroll_steps: Option<Vector2<f32>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn keyboard_keymap(&self, surface: &SurfaceID, keymap_id: &str);
|
fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec<i32>);
|
||||||
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panel_item_from_node(node: &Node) -> Option<Arc<dyn PanelItemTrait>> {
|
pub fn panel_item_from_node(node: &Node) -> Option<Arc<dyn PanelItemTrait>> {
|
||||||
@@ -243,7 +210,7 @@ pub struct PanelItem<B: Backend + ?Sized> {
|
|||||||
pub backend: Box<B>,
|
pub backend: Box<B>,
|
||||||
}
|
}
|
||||||
impl<B: Backend + ?Sized> PanelItem<B> {
|
impl<B: Backend + ?Sized> PanelItem<B> {
|
||||||
pub fn create(backend: Box<B>, pid: Option<i32>) -> (Arc<Node>, Arc<PanelItem<B>>) {
|
pub fn create(backend: Box<B>, pid: Option<i32>) -> Arc<PanelItem<B>> {
|
||||||
debug!(?pid, "Create panel item");
|
debug!(?pid, "Create panel item");
|
||||||
|
|
||||||
let startup_settings = pid
|
let startup_settings = pid
|
||||||
@@ -294,10 +261,9 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
node.add_local_signal("pointer_button", Self::pointer_button_flex);
|
node.add_local_signal("pointer_button", Self::pointer_button_flex);
|
||||||
node.add_local_signal("pointer_scroll", Self::pointer_scroll_flex);
|
node.add_local_signal("pointer_scroll", Self::pointer_scroll_flex);
|
||||||
|
|
||||||
node.add_local_signal("keyboard_keymap", Self::keyboard_keymap_flex);
|
node.add_local_signal("keyboard_key", Self::keyboard_keys_flex);
|
||||||
node.add_local_signal("keyboard_key", Self::keyboard_key_flex);
|
|
||||||
|
|
||||||
(node, panel_item)
|
panel_item
|
||||||
}
|
}
|
||||||
pub fn drop_toplevel(&self) {
|
pub fn drop_toplevel(&self) {
|
||||||
let Some(node) = self.node.upgrade() else {return};
|
let Some(node) = self.node.upgrade() else {return};
|
||||||
@@ -319,10 +285,6 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
let Some(node) = self.node.upgrade() else {return};
|
let Some(node) = self.node.upgrade() else {return};
|
||||||
let _ = node.send_remote_signal("toplevel_app_id_changed", serialize(app_id).unwrap());
|
let _ = node.send_remote_signal("toplevel_app_id_changed", serialize(app_id).unwrap());
|
||||||
}
|
}
|
||||||
pub fn toplevel_window_menu(&self, offset: Vector2<i32>) {
|
|
||||||
let Some(node) = self.node.upgrade() else {return};
|
|
||||||
let _ = node.send_remote_signal("toplevel_window_menu", serialize(offset).unwrap());
|
|
||||||
}
|
|
||||||
pub fn toplevel_fullscreen_active(&self, active: bool) {
|
pub fn toplevel_fullscreen_active(&self, active: bool) {
|
||||||
let Some(node) = self.node.upgrade() else {return};
|
let Some(node) = self.node.upgrade() else {return};
|
||||||
let _ = node.send_remote_signal("toplevel_fullscreen_active", serialize(active).unwrap());
|
let _ = node.send_remote_signal("toplevel_fullscreen_active", serialize(active).unwrap());
|
||||||
@@ -348,9 +310,9 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
let _ = node.send_remote_signal("set_cursor", serialize(geometry).unwrap());
|
let _ = node.send_remote_signal("set_cursor", serialize(geometry).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_child(&self, info: ChildInfo) {
|
pub fn new_child(&self, uid: &str, info: ChildInfo) {
|
||||||
let Some(node) = self.node.upgrade() else {return};
|
let Some(node) = self.node.upgrade() else {return};
|
||||||
let _ = node.send_remote_signal("new_child", serialize(info).unwrap());
|
let _ = node.send_remote_signal("new_child", serialize((uid, info)).unwrap());
|
||||||
}
|
}
|
||||||
pub fn reposition_child(&self, uid: &str, geometry: Geometry) {
|
pub fn reposition_child(&self, uid: &str, geometry: Geometry) {
|
||||||
let Some(node) = self.node.upgrade() else {return};
|
let Some(node) = self.node.upgrade() else {return};
|
||||||
@@ -460,29 +422,17 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_keymap_flex(
|
fn keyboard_keys_flex(
|
||||||
node: &Node,
|
node: &Node,
|
||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
message: Message,
|
message: Message,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
||||||
let (surface_id, keymap): (SurfaceID, &str) = deserialize(message.as_ref())?;
|
let (surface_id, keymap_id, keys): (SurfaceID, &str, Vec<i32>) =
|
||||||
debug!(?surface_id, keymap, "Set keyboard keymap");
|
deserialize(message.as_ref())?;
|
||||||
|
debug!(?keys, "Set keyboard key state");
|
||||||
|
|
||||||
panel_item.keyboard_keymap(&surface_id, keymap);
|
panel_item.keyboard_keys(&surface_id, keymap_id, keys);
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn keyboard_key_flex(
|
|
||||||
node: &Node,
|
|
||||||
_calling_client: Arc<Client>,
|
|
||||||
message: Message,
|
|
||||||
) -> Result<()> {
|
|
||||||
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
|
||||||
let (surface_id, key, state): (SurfaceID, u32, u32) = deserialize(message.as_ref())?;
|
|
||||||
debug!(key, state, "Set keyboard key state");
|
|
||||||
|
|
||||||
panel_item.keyboard_key(&surface_id, key, state == 0);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -540,11 +490,8 @@ impl<B: Backend + ?Sized> Backend for PanelItem<B> {
|
|||||||
.pointer_scroll(surface, scroll_distance, scroll_steps)
|
.pointer_scroll(surface, scroll_distance, scroll_steps)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_keymap(&self, surface: &SurfaceID, keymap_id: &str) {
|
fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec<i32>) {
|
||||||
self.backend.keyboard_keymap(surface, keymap_id)
|
self.backend.keyboard_keys(surface, keymap_id, keys)
|
||||||
}
|
|
||||||
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
|
|
||||||
self.backend.keyboard_key(surface, key, state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<B: Backend + ?Sized> Drop for PanelItem<B> {
|
impl<B: Backend + ?Sized> Drop for PanelItem<B> {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
core::task,
|
core::task,
|
||||||
nodes::items::panel::{Backend, Geometry, PanelItem},
|
nodes::items::panel::{Backend, Geometry, PanelItem},
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::{bail, eyre, Result};
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
@@ -15,7 +15,7 @@ use parking_lot::Mutex;
|
|||||||
use rand::{seq::IteratorRandom, thread_rng};
|
use rand::{seq::IteratorRandom, thread_rng};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
input::keyboard::ModifiersState,
|
input::keyboard::{KeymapFile, ModifiersState},
|
||||||
reexports::wayland_server::{
|
reexports::wayland_server::{
|
||||||
backend::{ClientId, GlobalId, ObjectId},
|
backend::{ClientId, GlobalId, ObjectId},
|
||||||
protocol::{
|
protocol::{
|
||||||
@@ -36,7 +36,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use tokio::sync::watch;
|
use tokio::sync::watch;
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
use xkbcommon::xkb::{self, Context, Keymap};
|
use xkbcommon::xkb::{self, ffi::XKB_KEYMAP_FORMAT_TEXT_V1, Keymap};
|
||||||
|
|
||||||
pub fn handle_cursor<B: Backend>(
|
pub fn handle_cursor<B: Backend>(
|
||||||
panel_item: &Arc<PanelItem<B>>,
|
panel_item: &Arc<PanelItem<B>>,
|
||||||
@@ -53,14 +53,18 @@ pub fn handle_cursor<B: Backend>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct KeyboardInfo {
|
pub struct KeyboardInfo {
|
||||||
|
keymap_string: String,
|
||||||
|
keymap: KeymapFile,
|
||||||
state: xkb::State,
|
state: xkb::State,
|
||||||
mods: ModifiersState,
|
mods: ModifiersState,
|
||||||
keys: FxHashSet<u32>,
|
keys: FxHashSet<u32>,
|
||||||
}
|
}
|
||||||
impl KeyboardInfo {
|
impl KeyboardInfo {
|
||||||
pub fn new(keymap: &Keymap) -> Self {
|
pub fn new(keymap_string: String, keymap: &Keymap) -> Self {
|
||||||
KeyboardInfo {
|
KeyboardInfo {
|
||||||
|
keymap_string,
|
||||||
state: xkb::State::new(keymap),
|
state: xkb::State::new(keymap),
|
||||||
|
keymap: KeymapFile::new(keymap),
|
||||||
mods: ModifiersState::default(),
|
mods: ModifiersState::default(),
|
||||||
keys: FxHashSet::default(),
|
keys: FxHashSet::default(),
|
||||||
}
|
}
|
||||||
@@ -116,6 +120,7 @@ pub enum PointerEvent {
|
|||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum KeyboardEvent {
|
pub enum KeyboardEvent {
|
||||||
|
Keymap,
|
||||||
Key { key: u32, state: u32 },
|
Key { key: u32, state: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +131,7 @@ struct SurfaceInfo {
|
|||||||
pointer_queue: VecDeque<PointerEvent>,
|
pointer_queue: VecDeque<PointerEvent>,
|
||||||
pointer_latest_event: Instant,
|
pointer_latest_event: Instant,
|
||||||
keyboard_queue: VecDeque<KeyboardEvent>,
|
keyboard_queue: VecDeque<KeyboardEvent>,
|
||||||
keyboard_info: KeyboardInfo,
|
keyboard_info: Option<KeyboardInfo>,
|
||||||
}
|
}
|
||||||
impl SurfaceInfo {
|
impl SurfaceInfo {
|
||||||
fn new(wl_surface: &WlSurface, cursor_sender: watch::Sender<Option<CursorInfo>>) -> Self {
|
fn new(wl_surface: &WlSurface, cursor_sender: watch::Sender<Option<CursorInfo>>) -> Self {
|
||||||
@@ -136,9 +141,7 @@ impl SurfaceInfo {
|
|||||||
pointer_queue: VecDeque::new(),
|
pointer_queue: VecDeque::new(),
|
||||||
pointer_latest_event: Instant::now(),
|
pointer_latest_event: Instant::now(),
|
||||||
keyboard_queue: VecDeque::new(),
|
keyboard_queue: VecDeque::new(),
|
||||||
keyboard_info: KeyboardInfo::new(
|
keyboard_info: None,
|
||||||
&Keymap::new_from_names(&Context::new(0), "", "", "", "", None, 0).unwrap(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn flush(&self) {
|
fn flush(&self) {
|
||||||
@@ -233,20 +236,25 @@ impl SurfaceInfo {
|
|||||||
|
|
||||||
locked
|
locked
|
||||||
}
|
}
|
||||||
fn handle_keyboard_events(&mut self, keyboard: &WlKeyboard, locked: bool) -> bool {
|
fn handle_keyboard_events(&mut self, keyboard: &WlKeyboard, mut locked: bool) -> bool {
|
||||||
let Ok(focus) = self.wl_surface.upgrade() else { return false; };
|
let Ok(focus) = self.wl_surface.upgrade() else { return false; };
|
||||||
|
let Some(info) = self.keyboard_info.as_mut() else { return true; };
|
||||||
|
|
||||||
if !locked {
|
if !locked {
|
||||||
keyboard.enter(0, &focus, vec![]);
|
keyboard.enter(0, &focus, vec![]);
|
||||||
if keyboard.version() >= wl_keyboard::EVT_REPEAT_INFO_SINCE {
|
if keyboard.version() >= wl_keyboard::EVT_REPEAT_INFO_SINCE {
|
||||||
keyboard.repeat_info(0, 0);
|
keyboard.repeat_info(0, 0);
|
||||||
}
|
}
|
||||||
|
locked = info.keymap.send(keyboard).is_ok();
|
||||||
}
|
}
|
||||||
while let Some(event) = self.keyboard_queue.pop_front() {
|
while let Some(event) = self.keyboard_queue.pop_front() {
|
||||||
debug!(locked, ?event, "Process keyboard event");
|
debug!(locked, ?event, "Process keyboard event");
|
||||||
match (locked, event) {
|
match (locked, event) {
|
||||||
|
(true, KeyboardEvent::Keymap) => {
|
||||||
|
let _ = info.keymap.send(keyboard);
|
||||||
|
}
|
||||||
(true, KeyboardEvent::Key { key, state }) => {
|
(true, KeyboardEvent::Key { key, state }) => {
|
||||||
if let Ok(key_count) = self.keyboard_info.process(key, state, keyboard) {
|
if let Ok(key_count) = info.process(key, state, keyboard) {
|
||||||
if key_count == 0 {
|
if key_count == 0 {
|
||||||
keyboard.leave(SERIAL_COUNTER.inc(), &focus);
|
keyboard.leave(SERIAL_COUNTER.inc(), &focus);
|
||||||
return false;
|
return false;
|
||||||
@@ -290,6 +298,31 @@ impl SeatData {
|
|||||||
seat_data
|
seat_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_keymap(&self, keymap_str: String, surfaces: Vec<WlSurface>) -> Result<()> {
|
||||||
|
let context = xkb::Context::new(0);
|
||||||
|
let keymap =
|
||||||
|
Keymap::new_from_string(&context, keymap_str.clone(), XKB_KEYMAP_FORMAT_TEXT_V1, 0)
|
||||||
|
.ok_or_else(|| eyre!("Keymap is not valid"))?;
|
||||||
|
let mut panels = self.surfaces.lock();
|
||||||
|
let Some((_, focus)) = self.keyboard.get() else {bail!("Could not get keyboard")};
|
||||||
|
for surface in surfaces {
|
||||||
|
let Some(surface_info) = panels.get_mut(&surface.id()) else {continue};
|
||||||
|
if let Some(keyboard_info) = &mut surface_info.keyboard_info {
|
||||||
|
if &keyboard_info.keymap_string == &keymap_str {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
surface_info
|
||||||
|
.keyboard_info
|
||||||
|
.replace(KeyboardInfo::new(keymap_str.clone(), &keymap));
|
||||||
|
|
||||||
|
if *focus.lock() == surface.id() {
|
||||||
|
surface_info.keyboard_queue.push_back(KeyboardEvent::Keymap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pointer_event(&self, surface: &WlSurface, event: PointerEvent) {
|
pub fn pointer_event(&self, surface: &WlSurface, event: PointerEvent) {
|
||||||
let mut surfaces = self.surfaces.lock();
|
let mut surfaces = self.surfaces.lock();
|
||||||
let Some(surface_info) = surfaces.get_mut(&surface.id()) else {return};
|
let Some(surface_info) = surfaces.get_mut(&surface.id()) else {return};
|
||||||
@@ -345,6 +378,7 @@ impl SeatData {
|
|||||||
if keyboard_focus.is_null() {
|
if keyboard_focus.is_null() {
|
||||||
*keyboard_focus = surfaces
|
*keyboard_focus = surfaces
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|(_k, v)| v.keyboard_info.is_some())
|
||||||
.filter(|(_k, v)| !v.keyboard_queue.is_empty())
|
.filter(|(_k, v)| !v.keyboard_queue.is_empty())
|
||||||
.map(|(k, _v)| k)
|
.map(|(k, _v)| k)
|
||||||
.choose(&mut thread_rng())
|
.choose(&mut thread_rng())
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
nodes::{
|
nodes::{
|
||||||
|
data::KEYMAPS,
|
||||||
drawable::model::ModelPart,
|
drawable::model::ModelPart,
|
||||||
items::panel::{
|
items::panel::{
|
||||||
Backend, ChildInfo, Geometry, PanelItem, PanelItemInitData, SurfaceID, ToplevelInfo,
|
Backend, ChildInfo, Geometry, PanelItem, PanelItemInitData, SurfaceID, ToplevelInfo,
|
||||||
},
|
},
|
||||||
Node,
|
|
||||||
},
|
},
|
||||||
wayland::seat::handle_cursor,
|
wayland::seat::handle_cursor,
|
||||||
};
|
};
|
||||||
@@ -378,11 +378,10 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
|
|
||||||
xdg_surface_data.lock().surface_id = SurfaceID::Toplevel;
|
xdg_surface_data.lock().surface_id = SurfaceID::Toplevel;
|
||||||
let Some(backend) = XDGBackend::create(toplevel.clone(), seat_data.clone()) else {return};
|
let Some(backend) = XDGBackend::create(toplevel.clone(), seat_data.clone()) else {return};
|
||||||
let (node, panel_item) = PanelItem::create(
|
let panel_item = PanelItem::create(
|
||||||
Box::new(backend),
|
Box::new(backend),
|
||||||
client_credentials.map(|c| c.pid),
|
client_credentials.map(|c| c.pid),
|
||||||
);
|
);
|
||||||
toplevel_data.lock().panel_item_node.replace(node);
|
|
||||||
xdg_surface_data.lock().panel_item = Arc::downgrade(&panel_item);
|
xdg_surface_data.lock().panel_item = Arc::downgrade(&panel_item);
|
||||||
handle_cursor(&panel_item, panel_item.backend.cursor.clone());
|
handle_cursor(&panel_item, panel_item.backend.cursor.clone());
|
||||||
}
|
}
|
||||||
@@ -509,7 +508,6 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ToplevelData {
|
pub struct ToplevelData {
|
||||||
panel_item_node: Option<Arc<Node>>,
|
|
||||||
xdg_surface: WlWeak<XdgSurface>,
|
xdg_surface: WlWeak<XdgSurface>,
|
||||||
parent: Option<WlWeak<XdgToplevel>>,
|
parent: Option<WlWeak<XdgToplevel>>,
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
@@ -520,7 +518,6 @@ pub struct ToplevelData {
|
|||||||
impl ToplevelData {
|
impl ToplevelData {
|
||||||
fn new(xdg_surface: &XdgSurface) -> Self {
|
fn new(xdg_surface: &XdgSurface) -> Self {
|
||||||
ToplevelData {
|
ToplevelData {
|
||||||
panel_item_node: None,
|
|
||||||
xdg_surface: xdg_surface.downgrade(),
|
xdg_surface: xdg_surface.downgrade(),
|
||||||
parent: None,
|
parent: None,
|
||||||
title: None,
|
title: None,
|
||||||
@@ -543,6 +540,12 @@ impl ToplevelData {
|
|||||||
xdg_surface_data.panel_item()
|
xdg_surface_data.panel_item()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Drop for ToplevelData {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let Some(panel_item) = self.panel_item() else {return};
|
||||||
|
panel_item.drop_toplevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
|
impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
|
||||||
fn request(
|
fn request(
|
||||||
_state: &mut WaylandState,
|
_state: &mut WaylandState,
|
||||||
@@ -578,15 +581,6 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
|
|||||||
let Some(panel_item) = data.lock().panel_item() else {return};
|
let Some(panel_item) = data.lock().panel_item() else {return};
|
||||||
panel_item.toplevel_app_id_changed(&app_id);
|
panel_item.toplevel_app_id_changed(&app_id);
|
||||||
}
|
}
|
||||||
xdg_toplevel::Request::ShowWindowMenu {
|
|
||||||
seat: _,
|
|
||||||
serial: _,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
} => {
|
|
||||||
let Some(panel_item) = data.lock().panel_item() else {return};
|
|
||||||
panel_item.toplevel_window_menu([x, y].into());
|
|
||||||
}
|
|
||||||
xdg_toplevel::Request::Move { seat, serial } => {
|
xdg_toplevel::Request::Move { seat, serial } => {
|
||||||
debug!(?xdg_toplevel, ?seat, serial, "XDG Toplevel move request");
|
debug!(?xdg_toplevel, ?seat, serial, "XDG Toplevel move request");
|
||||||
let Some(panel_item) = data.lock().panel_item() else {return};
|
let Some(panel_item) = data.lock().panel_item() else {return};
|
||||||
@@ -629,8 +623,6 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
|
|||||||
data.lock().min_size = (width > 1 || height > 1)
|
data.lock().min_size = (width > 1 || height > 1)
|
||||||
.then_some(Vector2::from([width as u32, height as u32]));
|
.then_some(Vector2::from([width as u32, height as u32]));
|
||||||
}
|
}
|
||||||
xdg_toplevel::Request::SetMaximized => {}
|
|
||||||
xdg_toplevel::Request::UnsetMaximized => {}
|
|
||||||
xdg_toplevel::Request::SetFullscreen { output: _ } => {
|
xdg_toplevel::Request::SetFullscreen { output: _ } => {
|
||||||
let Some(panel_item) = data.lock().panel_item() else {return};
|
let Some(panel_item) = data.lock().panel_item() else {return};
|
||||||
panel_item.backend.toplevel_state.lock().fullscreen = true;
|
panel_item.backend.toplevel_state.lock().fullscreen = true;
|
||||||
@@ -641,13 +633,12 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
|
|||||||
panel_item.backend.toplevel_state.lock().fullscreen = false;
|
panel_item.backend.toplevel_state.lock().fullscreen = false;
|
||||||
panel_item.backend.configure(None);
|
panel_item.backend.configure(None);
|
||||||
}
|
}
|
||||||
xdg_toplevel::Request::SetMinimized => {}
|
|
||||||
xdg_toplevel::Request::Destroy => {
|
xdg_toplevel::Request::Destroy => {
|
||||||
debug!(?xdg_toplevel, "Destroy XDG Toplevel");
|
debug!(?xdg_toplevel, "Destroy XDG Toplevel");
|
||||||
let Some(panel_item) = data.lock().panel_item() else {return};
|
let Some(panel_item) = data.lock().panel_item() else {return};
|
||||||
panel_item.drop_toplevel();
|
panel_item.drop_toplevel();
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -863,16 +854,18 @@ impl XDGBackend {
|
|||||||
popup: &XdgPopup,
|
popup: &XdgPopup,
|
||||||
data: &PopupData,
|
data: &PopupData,
|
||||||
) {
|
) {
|
||||||
let uid = data.uid.clone();
|
self.popups
|
||||||
|
.lock()
|
||||||
self.popups.lock().insert(uid.clone(), popup.downgrade());
|
.insert(data.uid.clone(), popup.downgrade());
|
||||||
|
|
||||||
let Some(positioner_data) = data.positioner_data() else {return};
|
let Some(positioner_data) = data.positioner_data() else {return};
|
||||||
panel_item.new_child(ChildInfo {
|
panel_item.new_child(
|
||||||
uid,
|
&data.uid,
|
||||||
parent: data.parent_id.clone(),
|
ChildInfo {
|
||||||
geometry: positioner_data.into(),
|
parent: data.parent_id.clone(),
|
||||||
})
|
geometry: positioner_data.into(),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
pub fn reposition_popup(&self, panel_item: &PanelItem<XDGBackend>, popup_state: &PopupData) {
|
pub fn reposition_popup(&self, panel_item: &PanelItem<XDGBackend>, popup_state: &PopupData) {
|
||||||
let Some(positioner_data) = popup_state.positioner_data() else {return};
|
let Some(positioner_data) = popup_state.positioner_data() else {return};
|
||||||
@@ -890,21 +883,19 @@ impl XDGBackend {
|
|||||||
self.seat.drop_surface(&wl_surface);
|
self.seat.drop_surface(&wl_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_data(&self) -> Vec<ChildInfo> {
|
fn child_data(&self) -> FxHashMap<String, ChildInfo> {
|
||||||
self.popups
|
FxHashMap::from_iter(self.popups.lock().values().filter_map(|v| {
|
||||||
.lock()
|
let popup = v.upgrade().ok()?;
|
||||||
.values()
|
let data = PopupData::get(&popup)?;
|
||||||
.filter_map(|v| {
|
let data_lock = data.lock();
|
||||||
let popup = v.upgrade().ok()?;
|
Some((
|
||||||
let data = PopupData::get(&popup)?;
|
data_lock.uid.clone(),
|
||||||
let data_lock = data.lock();
|
ChildInfo {
|
||||||
Some(ChildInfo {
|
|
||||||
uid: data_lock.uid.clone(),
|
|
||||||
parent: data_lock.parent_id.clone(),
|
parent: data_lock.parent_id.clone(),
|
||||||
geometry: data_lock.positioner_data()?.into(),
|
geometry: data_lock.positioner_data()?.into(),
|
||||||
})
|
},
|
||||||
})
|
))
|
||||||
.collect::<Vec<_>>()
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_client(&self) {
|
fn flush_client(&self) {
|
||||||
@@ -952,7 +943,10 @@ impl Backend for XDGBackend {
|
|||||||
.lock()
|
.lock()
|
||||||
.geometry
|
.geometry
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap(),
|
.unwrap_or_else(|| Geometry {
|
||||||
|
origin: [0, 0].into(),
|
||||||
|
size,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(PanelItemInitData {
|
Ok(PanelItemInitData {
|
||||||
@@ -1017,18 +1011,21 @@ impl Backend for XDGBackend {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
|
fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec<i32>) {
|
||||||
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
||||||
self.seat.keyboard_event(
|
let keymaps = KEYMAPS.lock();
|
||||||
&surface,
|
let Some(keymap) = keymaps.get(keymap_id).cloned() else {return};
|
||||||
KeyboardEvent::Key {
|
if self.seat.set_keymap(keymap, vec![surface.clone()]).is_err() {
|
||||||
key,
|
return;
|
||||||
state: if state { 1 } else { 0 },
|
}
|
||||||
},
|
for key in keys {
|
||||||
)
|
self.seat.keyboard_event(
|
||||||
}
|
&surface,
|
||||||
|
KeyboardEvent::Key {
|
||||||
fn keyboard_keymap(&self, _surface: &SurfaceID, _keymap_id: &str) {
|
key: key.abs() as u32,
|
||||||
todo!()
|
state: if key < 0 { 1 } else { 0 },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
nodes::{
|
nodes::{
|
||||||
|
data::KEYMAPS,
|
||||||
drawable::model::ModelPart,
|
drawable::model::ModelPart,
|
||||||
items::panel::{Backend, Geometry, PanelItem, PanelItemInitData, SurfaceID, ToplevelInfo},
|
items::panel::{Backend, Geometry, PanelItem, PanelItemInitData, SurfaceID, ToplevelInfo},
|
||||||
},
|
},
|
||||||
@@ -13,6 +14,7 @@ use color_eyre::eyre::Result;
|
|||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::{EventLoop, LoopSignal},
|
calloop::{EventLoop, LoopSignal},
|
||||||
@@ -42,7 +44,7 @@ impl XWaylandState {
|
|||||||
|
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
std::thread::spawn(move || {
|
||||||
let mut event_loop: EventLoop<XWaylandHandler> = EventLoop::try_new()?;
|
let mut event_loop: EventLoop<XWaylandHandler> = EventLoop::try_new()?;
|
||||||
let (xwayland, connection) = XWayland::new(&dh);
|
let (xwayland, connection) = XWayland::new(&dh);
|
||||||
let handle = event_loop.handle();
|
let handle = event_loop.handle();
|
||||||
@@ -144,7 +146,7 @@ impl XwmHandler for XWaylandHandler {
|
|||||||
let Some(wl_surface) = window.wl_surface() else {return};
|
let Some(wl_surface) = window.wl_surface() else {return};
|
||||||
let seat = seat.clone();
|
let seat = seat.clone();
|
||||||
window.user_data().insert_if_missing_threadsafe(|| {
|
window.user_data().insert_if_missing_threadsafe(|| {
|
||||||
let (_node, panel_item) = PanelItem::create(
|
let panel_item = PanelItem::create(
|
||||||
Box::new(X11Backend {
|
Box::new(X11Backend {
|
||||||
toplevel_parent: None,
|
toplevel_parent: None,
|
||||||
toplevel: window.clone(),
|
toplevel: window.clone(),
|
||||||
@@ -357,7 +359,7 @@ impl Backend for X11Backend {
|
|||||||
.into(),
|
.into(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
children: vec![],
|
children: FxHashMap::default(),
|
||||||
pointer_grab: self._pointer_grab.lock().clone(),
|
pointer_grab: self._pointer_grab.lock().clone(),
|
||||||
keyboard_grab: self._keyboard_grab.lock().clone(),
|
keyboard_grab: self._keyboard_grab.lock().clone(),
|
||||||
})
|
})
|
||||||
@@ -415,17 +417,21 @@ impl Backend for X11Backend {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_keymap(&self, surface: &SurfaceID, keymap_id: &str) {
|
fn keyboard_keys(&self, surface: &SurfaceID, keymap_id: &str, keys: Vec<i32>) {
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
|
|
||||||
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
let Some(surface) = self.wl_surface_from_id(surface) else {return};
|
||||||
self.seat.keyboard_event(
|
let keymaps = KEYMAPS.lock();
|
||||||
&surface,
|
let Some(keymap) = keymaps.get(keymap_id).cloned() else {return};
|
||||||
KeyboardEvent::Key {
|
if self.seat.set_keymap(keymap, vec![surface.clone()]).is_err() {
|
||||||
key,
|
return;
|
||||||
state: if state { 1 } else { 0 },
|
}
|
||||||
},
|
for key in keys {
|
||||||
)
|
self.seat.keyboard_event(
|
||||||
|
&surface,
|
||||||
|
KeyboardEvent::Key {
|
||||||
|
key: key.abs() as u32,
|
||||||
|
state: if key < 0 { 1 } else { 0 },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user