feat: input multiplexing
This commit is contained in:
@@ -20,7 +20,7 @@ mint = "0.5.9"
|
||||
nanoid = "0.4.0"
|
||||
once_cell = "1.12.0"
|
||||
parking_lot = "0.12.1"
|
||||
portable-atomic = {version = "0.3.0", features = ["float", "std"]}
|
||||
portable-atomic = {version = "1.0.0", features = ["float", "std"]}
|
||||
rustc-hash = "1.1.0"
|
||||
slab = "0.4.6"
|
||||
tokio = { version = "1", features = ["rt", "signal"] }
|
||||
@@ -28,13 +28,14 @@ send_wrapper = "0.6.0"
|
||||
prisma = "0.1.1"
|
||||
slog = "2.7.0"
|
||||
xkbcommon = { version = "0.5.0", default-features = false, optional = true }
|
||||
stardust-xr = "0.10.0"
|
||||
stardust-xr = "0.10.4"
|
||||
directories = "4.0.1"
|
||||
serde = { version = "1.0.145", features = ["derive"] }
|
||||
tracing = "0.1.37"
|
||||
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||
tracing-slog = "0.2.0"
|
||||
global_counter = "0.2.2"
|
||||
rand = "0.8.5"
|
||||
|
||||
[dependencies.stereokit]
|
||||
default-features = false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{
|
||||
seat::{Cursor, KeyboardInfo, SeatData},
|
||||
seat::{Cursor, SeatData},
|
||||
surface::CoreSurface,
|
||||
xdg_shell::{XdgSurfaceData, XdgToplevelData},
|
||||
SERIAL_COUNTER,
|
||||
@@ -14,8 +14,9 @@ use crate::{
|
||||
spatial::Spatial,
|
||||
Node,
|
||||
},
|
||||
wayland::seat::{KeyboardEvent, PointerEvent},
|
||||
};
|
||||
use color_eyre::eyre::{bail, eyre, Result};
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use glam::Mat4;
|
||||
use lazy_static::lazy_static;
|
||||
use mint::Vector2;
|
||||
@@ -28,12 +29,7 @@ use smithay::{
|
||||
XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE, EVT_WM_CAPABILITIES_SINCE,
|
||||
},
|
||||
wayland_server::{
|
||||
backend::Credentials,
|
||||
protocol::{
|
||||
wl_pointer::{Axis, ButtonState},
|
||||
wl_surface::WlSurface,
|
||||
},
|
||||
Resource, Weak as WlWeak,
|
||||
backend::Credentials, protocol::wl_surface::WlSurface, Resource, Weak as WlWeak,
|
||||
},
|
||||
},
|
||||
wayland::compositor,
|
||||
@@ -47,17 +43,18 @@ lazy_static! {
|
||||
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
|
||||
type_name: "panel",
|
||||
aliased_local_signals: vec![
|
||||
"apply_cursor_material",
|
||||
"apply_toplevel_material",
|
||||
"configure_toplevel",
|
||||
"set_toplevel_capabilities",
|
||||
"apply_cursor_material",
|
||||
"pointer_deactivate",
|
||||
"pointer_set_active",
|
||||
"pointer_scroll",
|
||||
"pointer_button",
|
||||
"pointer_motion",
|
||||
"keyboard_set_active",
|
||||
"keyboard_set_keyState",
|
||||
"keyboard_set_modifiers",
|
||||
"keyboard_key",
|
||||
"keyboard_set_keymap_names",
|
||||
"keyboard_set_keymap_string",
|
||||
"close",
|
||||
],
|
||||
aliased_local_methods: vec![],
|
||||
@@ -112,14 +109,14 @@ pub enum RecommendedState {
|
||||
pub struct PanelItem {
|
||||
node: Weak<Node>,
|
||||
client_credentials: Option<Credentials>,
|
||||
toplevel_surface: WlWeak<WlSurface>,
|
||||
pub toplevel: WlWeak<XdgToplevel>,
|
||||
toplevel: WlWeak<XdgToplevel>,
|
||||
pub cursor: Mutex<Option<WlWeak<WlSurface>>>,
|
||||
seat_data: SeatData,
|
||||
}
|
||||
impl PanelItem {
|
||||
pub fn create(
|
||||
toplevel: XdgToplevel,
|
||||
wl_surface: WlSurface,
|
||||
client_credentials: Option<Credentials>,
|
||||
seat_data: SeatData,
|
||||
) -> (Arc<Node>, Arc<PanelItem>) {
|
||||
@@ -134,20 +131,14 @@ impl PanelItem {
|
||||
let panel_item = Arc::new(PanelItem {
|
||||
node: Arc::downgrade(&node),
|
||||
client_credentials,
|
||||
toplevel_surface: toplevel
|
||||
.data::<XdgToplevelData>()
|
||||
.unwrap()
|
||||
.xdg_surface_data
|
||||
.wl_surface
|
||||
.clone(),
|
||||
toplevel: toplevel.downgrade(),
|
||||
cursor: Mutex::new(None),
|
||||
seat_data,
|
||||
});
|
||||
let _ = panel_item
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.panel_item
|
||||
.set(Arc::downgrade(&panel_item));
|
||||
.new_panel_item(&panel_item, &toplevel, &wl_surface);
|
||||
|
||||
let item = Item::add_to(
|
||||
&node,
|
||||
@@ -169,20 +160,21 @@ impl PanelItem {
|
||||
"apply_cursor_material",
|
||||
PanelItem::apply_cursor_material_flex,
|
||||
);
|
||||
node.add_local_signal("pointer_deactivate", PanelItem::pointer_deactivate_flex);
|
||||
node.add_local_signal("pointer_set_active", PanelItem::pointer_set_active_flex);
|
||||
node.add_local_signal("pointer_scroll", PanelItem::pointer_scroll_flex);
|
||||
node.add_local_signal("pointer_button", PanelItem::pointer_button_flex);
|
||||
node.add_local_signal("pointer_motion", PanelItem::pointer_motion_flex);
|
||||
|
||||
node.add_local_signal("keyboard_set_active", PanelItem::keyboard_set_active_flex);
|
||||
node.add_local_signal(
|
||||
"keyboard_activate_string",
|
||||
PanelItem::keyboard_activate_string_flex,
|
||||
"keyboard_set_keymap_string",
|
||||
PanelItem::keyboard_set_keymap_string_flex,
|
||||
);
|
||||
node.add_local_signal(
|
||||
"keyboard_activate_names",
|
||||
PanelItem::keyboard_activate_names_flex,
|
||||
"keyboard_set_keymap_names",
|
||||
PanelItem::keyboard_set_keymap_names_flex,
|
||||
);
|
||||
node.add_local_signal("keyboard_deactivate", PanelItem::keyboard_deactivate_flex);
|
||||
node.add_local_signal("keyboard_key_state", PanelItem::keyboard_key_state_flex);
|
||||
node.add_local_signal("keyboard_key", PanelItem::keyboard_key_flex);
|
||||
|
||||
if let Some(startup_settings) = panel_item
|
||||
.client_credentials
|
||||
@@ -219,7 +211,7 @@ impl PanelItem {
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
pub fn toplevel_state(&self) -> Option<Arc<Mutex<ToplevelState>>> {
|
||||
fn toplevel_state(&self) -> Option<Arc<Mutex<ToplevelState>>> {
|
||||
Some(
|
||||
self.toplevel
|
||||
.upgrade()
|
||||
@@ -229,7 +221,7 @@ impl PanelItem {
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
fn toplevel_wl_surface(&self) -> Option<WlSurface> {
|
||||
pub fn toplevel_wl_surface(&self) -> Option<WlSurface> {
|
||||
self.toplevel_surface_data()?.wl_surface.upgrade().ok()
|
||||
}
|
||||
fn core_surface(&self) -> Option<Arc<CoreSurface>> {
|
||||
@@ -237,6 +229,11 @@ impl PanelItem {
|
||||
data.data_map.get::<Arc<CoreSurface>>().cloned()
|
||||
})
|
||||
}
|
||||
fn flush_clients(&self) {
|
||||
if let Some(core_surface) = self.core_surface() {
|
||||
core_surface.flush_clients();
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_toplevel_material_flex(
|
||||
node: &Node,
|
||||
@@ -274,7 +271,7 @@ impl PanelItem {
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(cursor) = panel_item.seat_data.cursor() else { return Ok(())};
|
||||
let Some(cursor) = panel_item.cursor.lock().as_ref().and_then(|c| c.upgrade().ok()) else { return Ok(())};
|
||||
let Some(core_surface) = CoreSurface::from_wl_surface(&cursor) else { return Ok(()) };
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -298,130 +295,73 @@ impl PanelItem {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pointer_deactivate_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
_data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
if !panel_item.seat_data.pointer_active() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
|
||||
debug!(?wl_surface, ?pointer, "Pointer deactivate");
|
||||
pointer.leave(SERIAL_COUNTER.inc(), &wl_surface);
|
||||
*panel_item.seat_data.pointer_focus.lock() = None;
|
||||
pointer.frame();
|
||||
core_surface.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pointer_motion_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = core_surface.wl_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
debug!(?toplevel, "Pointer deactivate");
|
||||
|
||||
let Some(pointer_surface_size) =
|
||||
core_surface.with_data(|data| data.size) else { return Ok(()) };
|
||||
|
||||
let mut position: Vector2<f64> = deserialize(data)?;
|
||||
position.x = position.x.clamp(0.0, pointer_surface_size.x as f64);
|
||||
position.y = position.y.clamp(0.0, pointer_surface_size.y as f64);
|
||||
debug!(?wl_surface, ?pointer, ?position, "Pointer motion");
|
||||
|
||||
let mut pointer_focus = panel_item.seat_data.pointer_focus.lock();
|
||||
if let Some(old_surface) = pointer_focus
|
||||
.as_ref()
|
||||
.and_then(|surf| surf.upgrade().ok())
|
||||
.filter(|surf| surf.id() != wl_surface.id())
|
||||
{
|
||||
pointer.leave(SERIAL_COUNTER.inc(), &old_surface);
|
||||
*pointer_focus = None;
|
||||
}
|
||||
if pointer_focus.is_none() {
|
||||
pointer.enter(SERIAL_COUNTER.inc(), &wl_surface, position.x, position.y);
|
||||
*pointer_focus = Some(wl_surface.downgrade());
|
||||
} else {
|
||||
pointer.motion(0, position.x, position.y);
|
||||
}
|
||||
pointer.frame();
|
||||
core_surface.flush_clients();
|
||||
panel_item
|
||||
.seat_data
|
||||
.pointer_event(&toplevel, PointerEvent::Motion(deserialize(data)?));
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pointer_button_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
if !panel_item.seat_data.pointer_active() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
|
||||
let (button, state): (u32, u32) = deserialize(data)?;
|
||||
debug!(?pointer, button, state, "Pointer button");
|
||||
pointer.button(
|
||||
SERIAL_COUNTER.inc(),
|
||||
0,
|
||||
button,
|
||||
match state {
|
||||
0 => ButtonState::Released,
|
||||
1 => ButtonState::Pressed,
|
||||
_ => {
|
||||
bail!("Button state is out of bounds")
|
||||
}
|
||||
},
|
||||
);
|
||||
pointer.frame();
|
||||
core_surface.flush_clients();
|
||||
debug!(button, state, "Pointer button");
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.pointer_event(&toplevel, PointerEvent::Button { button, state });
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pointer_scroll_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
if !panel_item.seat_data.pointer_active() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(pointer) = panel_item.seat_data.pointer() else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PointerScrollArgs {
|
||||
axis_continuous: Vector2<f32>,
|
||||
axis_discrete: Option<Vector2<f32>>,
|
||||
}
|
||||
let args: Option<PointerScrollArgs> = deserialize(data)?;
|
||||
|
||||
debug!(?pointer, "Pointer scroll");
|
||||
debug!(?args, "Pointer scroll");
|
||||
|
||||
match args {
|
||||
Some(args) => {
|
||||
pointer.axis(0, Axis::HorizontalScroll, args.axis_continuous.x as f64);
|
||||
pointer.axis(0, Axis::VerticalScroll, args.axis_continuous.y as f64);
|
||||
if let Some(axis_discrete_vec) = args.axis_discrete {
|
||||
pointer.axis_discrete(Axis::HorizontalScroll, axis_discrete_vec.x as i32);
|
||||
pointer.axis_discrete(Axis::VerticalScroll, axis_discrete_vec.y as i32);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
pointer.axis_stop(0, Axis::HorizontalScroll);
|
||||
pointer.axis_stop(0, Axis::VerticalScroll);
|
||||
}
|
||||
};
|
||||
panel_item.seat_data.pointer_event(
|
||||
&toplevel,
|
||||
PointerEvent::Scroll {
|
||||
axis_continuous: args.as_ref().map(|a| a.axis_continuous),
|
||||
axis_discrete: args.and_then(|a| a.axis_discrete),
|
||||
},
|
||||
);
|
||||
panel_item.flush_clients();
|
||||
|
||||
pointer.frame();
|
||||
core_surface.flush_clients();
|
||||
Ok(())
|
||||
}
|
||||
fn pointer_set_active_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let active: bool = deserialize(data)?;
|
||||
debug!(?toplevel, active, "Pointer set active");
|
||||
|
||||
panel_item.seat_data.set_pointer_active(&toplevel, active);
|
||||
panel_item.flush_clients();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_activate_string_flex(
|
||||
fn keyboard_set_keymap_string_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
@@ -431,10 +371,9 @@ impl PanelItem {
|
||||
Keymap::new_from_string(&context, deserialize(data)?, XKB_KEYMAP_FORMAT_TEXT_V1, 0)
|
||||
.ok_or_else(|| eyre!("Keymap is not valid"))?;
|
||||
|
||||
PanelItem::keyboard_activate_flex(node, &keymap)
|
||||
PanelItem::keyboard_set_keymap_flex(node, &keymap)
|
||||
}
|
||||
|
||||
fn keyboard_activate_names_flex(
|
||||
fn keyboard_set_keymap_names_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
@@ -460,66 +399,42 @@ impl PanelItem {
|
||||
)
|
||||
.ok_or_else(|| eyre!("Keymap is not valid"))?;
|
||||
|
||||
PanelItem::keyboard_activate_flex(node, &keymap)
|
||||
PanelItem::keyboard_set_keymap_flex(node, &keymap)
|
||||
}
|
||||
|
||||
fn keyboard_activate_flex(node: &Node, keymap: &Keymap) -> Result<()> {
|
||||
fn keyboard_set_keymap_flex(node: &Node, keymap: &Keymap) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = panel_item.toplevel_wl_surface() else { return Ok(()) };
|
||||
let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
debug!(?toplevel, "Keyboard set keymap");
|
||||
|
||||
let mut keyboard_info = panel_item.seat_data.keyboard_info.lock();
|
||||
if keyboard_info.is_none() {
|
||||
debug!(?keyboard, ?wl_surface, "Activate keyboard");
|
||||
keyboard.enter(SERIAL_COUNTER.inc(), &wl_surface, vec![]);
|
||||
keyboard.repeat_info(0, 0);
|
||||
keyboard_info.replace(KeyboardInfo::new(keymap));
|
||||
keyboard_info.as_ref().unwrap().keymap.send(keyboard)?;
|
||||
core_surface.flush_clients();
|
||||
}
|
||||
panel_item.seat_data.set_keymap(&toplevel, keymap);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_deactivate_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
_data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(wl_surface) = panel_item.toplevel_wl_surface() else { return Ok(()) };
|
||||
let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) };
|
||||
|
||||
debug!(?keyboard, ?wl_surface, "Deactivate keyboard");
|
||||
|
||||
let mut keyboard_info = panel_item.seat_data.keyboard_info.lock();
|
||||
if keyboard_info.is_some() {
|
||||
keyboard.leave(SERIAL_COUNTER.inc(), &wl_surface);
|
||||
*keyboard_info = None;
|
||||
core_surface.flush_clients();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_key_state_flex(
|
||||
fn keyboard_set_active_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
|
||||
let Some(keyboard) = panel_item.seat_data.keyboard() else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let active: bool = deserialize(data)?;
|
||||
debug!(?toplevel, active, "Keyboard set active");
|
||||
|
||||
let mut keyboard_info = panel_item.seat_data.keyboard_info.lock();
|
||||
if let Some(keyboard_info) = &mut *keyboard_info {
|
||||
let (key, state): (u32, u32) = deserialize(data)?;
|
||||
debug!(?keyboard, key, state, "Set keyboard key state");
|
||||
keyboard_info.process(key, state, keyboard)?;
|
||||
core_surface.flush_clients();
|
||||
}
|
||||
panel_item.seat_data.set_keyboard_active(&toplevel, active);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keyboard_key_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
|
||||
let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
|
||||
let (key, state): (u32, u32) = deserialize(data)?;
|
||||
debug!(key, state, "Set keyboard key state");
|
||||
|
||||
panel_item
|
||||
.seat_data
|
||||
.keyboard_event(&toplevel, KeyboardEvent::Key { key, state });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -586,36 +501,24 @@ impl PanelItem {
|
||||
}
|
||||
|
||||
pub fn commit_toplevel(&self) {
|
||||
let mapped = self.core_surface().map(|c| c.mapped()).unwrap_or(false);
|
||||
let mapped_size = self.core_surface().and_then(|c| c.size());
|
||||
let Some(state) = self.toplevel_state() else { return };
|
||||
let Some(surface_data) = self.toplevel_surface_data() else { return };
|
||||
let mut state = state.lock();
|
||||
{
|
||||
let queued_state = state.queued_state.as_mut().unwrap();
|
||||
queued_state.mapped = mapped;
|
||||
if mapped {
|
||||
queued_state.size = surface_data
|
||||
.geometry
|
||||
.lock()
|
||||
.as_ref()
|
||||
.map(|geo| geo.size)
|
||||
.unwrap_or_else(|| {
|
||||
self.core_surface()
|
||||
.unwrap()
|
||||
.with_data(|data| Vector2::from([data.size.x / 2, data.size.y / 2]))
|
||||
.unwrap()
|
||||
});
|
||||
}
|
||||
let mut queued_state = state.queued_state.take().unwrap();
|
||||
queued_state.mapped =
|
||||
mapped_size.is_some() && mapped_size.unwrap().x > 0 && mapped_size.unwrap().y > 0;
|
||||
if let Some(size) = mapped_size {
|
||||
queued_state.size = size;
|
||||
}
|
||||
|
||||
debug!(state = ?&*state, "Commit toplevel");
|
||||
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let queued_state = state.queued_state.take().unwrap();
|
||||
*state = (*queued_state).clone();
|
||||
state.queued_state = Some(queued_state);
|
||||
|
||||
let _ = node.send_remote_signal("commit_toplevel", &serialize(&*state).unwrap());
|
||||
debug!(state = ?&state.mapped.then_some(&*state), "Commit toplevel");
|
||||
let Some(node) = self.node.upgrade() else { return };
|
||||
let _ = node.send_remote_signal(
|
||||
"commit_toplevel",
|
||||
&serialize(&state.mapped.then_some(&*state)).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn recommend_toplevel_state(&self, state: RecommendedState) {
|
||||
@@ -633,27 +536,21 @@ impl PanelItem {
|
||||
|
||||
let cursor_size = surface
|
||||
.and_then(|c| CoreSurface::from_wl_surface(c))
|
||||
.and_then(|c| c.with_data(|data| data.size));
|
||||
.and_then(|c| c.size());
|
||||
|
||||
if let Some(size) = cursor_size {
|
||||
data = serialize((size, (hotspot_x, hotspot_y))).unwrap();
|
||||
}
|
||||
|
||||
let _ = node.send_remote_signal("set_cursor", &data);
|
||||
*self.cursor.lock() = surface.map(|surf| surf.downgrade());
|
||||
}
|
||||
|
||||
pub fn on_drop(&self) {
|
||||
let Ok(toplevel_surface) = self.toplevel_surface.upgrade() else { return; };
|
||||
let Some(focused_surface) = self.seat_data.pointer_focused_surface() else { return; };
|
||||
let Ok(toplevel) = self.toplevel.upgrade() else { return; };
|
||||
self.seat_data.drop_panel_item(&toplevel);
|
||||
|
||||
debug!("Drop panel item");
|
||||
|
||||
if focused_surface.id() == toplevel_surface.id() {
|
||||
let Some(pointer) = self.seat_data.pointer() else { return };
|
||||
pointer.leave(SERIAL_COUNTER.inc(), &toplevel_surface);
|
||||
pointer.frame();
|
||||
*self.seat_data.pointer_focus.lock() = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ItemSpecialization for PanelItem {
|
||||
@@ -662,7 +559,7 @@ impl ItemSpecialization for PanelItem {
|
||||
let cursor_size = cursor
|
||||
.as_ref()
|
||||
.and_then(|c| CoreSurface::from_wl_surface(&c))
|
||||
.and_then(|c| c.with_data(|data| data.size));
|
||||
.and_then(|c| c.size());
|
||||
let cursor_hotspot = cursor
|
||||
.and_then(|c| {
|
||||
compositor::with_states(&c, |data| data.data_map.get::<Arc<Cursor>>().cloned())
|
||||
@@ -671,13 +568,9 @@ impl ItemSpecialization for PanelItem {
|
||||
|
||||
let toplevel_state = self.toplevel_state();
|
||||
let toplevel_state = toplevel_state.as_ref().map(|state| state.lock());
|
||||
serialize((
|
||||
id,
|
||||
(
|
||||
toplevel_state.and_then(|state| state.mapped.then_some(state.clone())),
|
||||
cursor_size.zip(cursor_hotspot),
|
||||
),
|
||||
))
|
||||
.unwrap()
|
||||
let toplevel_state = toplevel_state.and_then(|state| {
|
||||
(state.mapped && state.size.x > 0 && state.size.y > 0).then_some(state.clone())
|
||||
});
|
||||
serialize((id, (toplevel_state, cursor_size.zip(cursor_hotspot)))).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,35 +9,70 @@ use mint::Vector2;
|
||||
use nanoid::nanoid;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use rand::{seq::IteratorRandom, thread_rng};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smithay::{
|
||||
input::keyboard::{KeymapFile, ModifiersState},
|
||||
reexports::wayland_server::{
|
||||
backend::{ClientId, GlobalId},
|
||||
protocol::{
|
||||
wl_keyboard::{self, KeyState, WlKeyboard},
|
||||
wl_pointer::{self, WlPointer},
|
||||
wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE},
|
||||
wl_surface::WlSurface,
|
||||
wl_touch::{self, WlTouch},
|
||||
reexports::{
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel,
|
||||
wayland_server::{
|
||||
backend::{ClientId, GlobalId, ObjectId},
|
||||
protocol::{
|
||||
wl_keyboard::{self, KeyState, WlKeyboard},
|
||||
wl_pointer::{self, Axis, ButtonState, WlPointer},
|
||||
wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE},
|
||||
wl_surface::WlSurface,
|
||||
wl_touch::{self, WlTouch},
|
||||
},
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
||||
Weak as WlWeak,
|
||||
},
|
||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak as WlWeak,
|
||||
},
|
||||
wayland::compositor,
|
||||
};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
ops::Deref,
|
||||
sync::{Arc, Weak},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use tracing::{debug, warn};
|
||||
use xkbcommon::xkb::{self, Keymap};
|
||||
|
||||
pub struct Cursor {
|
||||
pub hotspot: Vector2<i32>,
|
||||
#[derive(Clone)]
|
||||
pub struct SeatData(Arc<SeatDataInner>);
|
||||
impl SeatData {
|
||||
pub fn new(dh: &DisplayHandle, client: ClientId) -> Self {
|
||||
let seat_data = SeatData(Arc::new(SeatDataInner {
|
||||
client,
|
||||
global_id: OnceCell::new(),
|
||||
panels: Mutex::new(FxHashMap::default()),
|
||||
pointer: OnceCell::new(),
|
||||
keyboard: OnceCell::new(),
|
||||
touch: OnceCell::new(),
|
||||
}));
|
||||
|
||||
seat_data
|
||||
.global_id
|
||||
.set(dh.create_global::<WaylandState, _, _>(7, seat_data.clone()))
|
||||
.unwrap();
|
||||
|
||||
seat_data
|
||||
}
|
||||
}
|
||||
impl Deref for SeatData {
|
||||
type Target = SeatDataInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KeyboardInfo {
|
||||
pub keymap: KeymapFile,
|
||||
pub state: xkb::State,
|
||||
pub mods: ModifiersState,
|
||||
keymap: KeymapFile,
|
||||
state: xkb::State,
|
||||
mods: ModifiersState,
|
||||
keys: FxHashSet<u32>,
|
||||
}
|
||||
impl KeyboardInfo {
|
||||
pub fn new(keymap: &Keymap) -> Self {
|
||||
@@ -45,9 +80,10 @@ impl KeyboardInfo {
|
||||
state: xkb::State::new(keymap),
|
||||
keymap: KeymapFile::new(keymap, None),
|
||||
mods: ModifiersState::default(),
|
||||
keys: FxHashSet::default(),
|
||||
}
|
||||
}
|
||||
pub fn process(&mut self, key: u32, state: u32, keyboard: &WlKeyboard) -> Result<()> {
|
||||
pub fn process(&mut self, key: u32, state: u32, keyboard: &WlKeyboard) -> Result<usize> {
|
||||
let wl_key_state = match state {
|
||||
0 => KeyState::Released,
|
||||
1 => KeyState::Pressed,
|
||||
@@ -70,81 +106,343 @@ impl KeyboardInfo {
|
||||
);
|
||||
}
|
||||
keyboard.key(SERIAL_COUNTER.inc(), 0, key, wl_key_state);
|
||||
Ok(())
|
||||
match wl_key_state {
|
||||
KeyState::Pressed => {
|
||||
self.keys.insert(key);
|
||||
}
|
||||
KeyState::Released => {
|
||||
self.keys.remove(&key);
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
Ok(self.keys.len())
|
||||
}
|
||||
}
|
||||
unsafe impl Send for KeyboardInfo {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SeatData(Arc<SeatDataInner>);
|
||||
impl SeatData {
|
||||
pub fn new(dh: &DisplayHandle, client: ClientId) -> Self {
|
||||
let seat_data = SeatData(Arc::new(SeatDataInner {
|
||||
client,
|
||||
global_id: OnceCell::new(),
|
||||
panel_item: OnceCell::new(),
|
||||
pointer: OnceCell::new(),
|
||||
pointer_focus: Mutex::new(None),
|
||||
keyboard: OnceCell::new(),
|
||||
keyboard_info: Mutex::new(None),
|
||||
touch: OnceCell::new(),
|
||||
}));
|
||||
|
||||
seat_data
|
||||
.global_id
|
||||
.set(dh.create_global::<WaylandState, _, _>(7, seat_data.clone()))
|
||||
.unwrap();
|
||||
|
||||
seat_data
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PointerEvent {
|
||||
Motion(Vector2<f64>),
|
||||
Button {
|
||||
button: u32,
|
||||
state: u32,
|
||||
},
|
||||
Scroll {
|
||||
axis_continuous: Option<Vector2<f32>>,
|
||||
axis_discrete: Option<Vector2<f32>>,
|
||||
},
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum KeyboardEvent {
|
||||
Keymap,
|
||||
Key { key: u32, state: u32 },
|
||||
}
|
||||
impl Deref for SeatData {
|
||||
type Target = SeatDataInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
const POINTER_EVENT_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
struct PanelInfo {
|
||||
panel_item: Weak<PanelItem>,
|
||||
toplevel: WlWeak<XdgToplevel>,
|
||||
focus: WlWeak<WlSurface>,
|
||||
pointer_queue: Option<VecDeque<PointerEvent>>,
|
||||
pointer_latest_event: Instant,
|
||||
keyboard_queue: Option<VecDeque<KeyboardEvent>>,
|
||||
keyboard_info: Option<KeyboardInfo>,
|
||||
}
|
||||
impl PanelInfo {
|
||||
fn new(panel_item: &Arc<PanelItem>, toplevel: &XdgToplevel, focus: &WlSurface) -> Self {
|
||||
PanelInfo {
|
||||
toplevel: toplevel.downgrade(),
|
||||
panel_item: Arc::downgrade(panel_item),
|
||||
focus: focus.downgrade(),
|
||||
pointer_queue: None,
|
||||
pointer_latest_event: Instant::now(),
|
||||
keyboard_queue: None,
|
||||
keyboard_info: None,
|
||||
}
|
||||
}
|
||||
pub fn set_pointer_active(&mut self, seat_data: &SeatDataInner, active: bool) {
|
||||
if active && self.pointer_queue.is_none() {
|
||||
self.pointer_queue.replace(Default::default());
|
||||
}
|
||||
|
||||
if !active && self.pointer_queue.is_some() {
|
||||
self.pointer_queue.take();
|
||||
let Ok(focus) = self.focus.upgrade() else {return};
|
||||
let Some((pointer, pointer_focus)) = seat_data.pointer.get() else {return};
|
||||
if &*pointer_focus.lock() == &Some(self.toplevel.id()) {
|
||||
pointer.leave(SERIAL_COUNTER.inc(), &focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn handle_pointer_events(&mut self, pointer: &WlPointer, mut locked: bool) -> bool {
|
||||
let Ok(focus) = self.focus.upgrade() else { return false; };
|
||||
let Some(pointer_queue) = self.pointer_queue.as_mut() else { return false; };
|
||||
let Some(core_surface) = CoreSurface::from_wl_surface(&focus) else { return false; };
|
||||
let Some(focus_size) = core_surface.size() else { return false; };
|
||||
|
||||
if !pointer_queue.is_empty() {
|
||||
self.pointer_latest_event = Instant::now();
|
||||
}
|
||||
while let Some(event) = pointer_queue.pop_front() {
|
||||
match (locked, event) {
|
||||
(false, PointerEvent::Motion(pos)) => {
|
||||
pointer.enter(
|
||||
SERIAL_COUNTER.inc(),
|
||||
&focus,
|
||||
pos.x.clamp(0.0, focus_size.x as f64),
|
||||
pos.y.clamp(0.0, focus_size.y as f64),
|
||||
);
|
||||
locked = true;
|
||||
}
|
||||
(true, PointerEvent::Motion(pos)) => {
|
||||
pointer.motion(
|
||||
0,
|
||||
pos.x.clamp(0.0, focus_size.x as f64),
|
||||
pos.y.clamp(0.0, focus_size.y as f64),
|
||||
);
|
||||
pointer.frame();
|
||||
}
|
||||
(true, PointerEvent::Button { button, state }) => {
|
||||
pointer.button(
|
||||
0,
|
||||
0,
|
||||
button,
|
||||
match state {
|
||||
0 => ButtonState::Released,
|
||||
1 => ButtonState::Pressed,
|
||||
_ => continue,
|
||||
},
|
||||
);
|
||||
pointer.frame();
|
||||
}
|
||||
(
|
||||
true,
|
||||
PointerEvent::Scroll {
|
||||
axis_continuous,
|
||||
axis_discrete,
|
||||
},
|
||||
) => {
|
||||
if let Some(axis_continuous) = axis_continuous {
|
||||
pointer.axis(0, Axis::HorizontalScroll, axis_continuous.x as f64);
|
||||
pointer.axis(0, Axis::VerticalScroll, axis_continuous.y as f64);
|
||||
}
|
||||
if let Some(axis_discrete) = axis_discrete {
|
||||
pointer.axis_discrete(Axis::HorizontalScroll, axis_discrete.x as i32);
|
||||
pointer.axis_discrete(Axis::VerticalScroll, axis_discrete.y as i32);
|
||||
}
|
||||
if axis_discrete.is_none() && axis_continuous.is_none() {
|
||||
pointer.axis_stop(0, Axis::HorizontalScroll);
|
||||
pointer.axis_stop(0, Axis::VerticalScroll);
|
||||
}
|
||||
pointer.frame();
|
||||
}
|
||||
(locked, event) => {
|
||||
warn!(locked, ?event, "Invalid pointer event!");
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.pointer_latest_event.elapsed() > POINTER_EVENT_TIMEOUT {
|
||||
pointer.leave(SERIAL_COUNTER.inc(), &focus);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
locked
|
||||
}
|
||||
pub fn set_keyboard_active(&mut self, seat_data: &SeatDataInner, active: bool) {
|
||||
if active && self.keyboard_queue.is_none() {
|
||||
self.keyboard_queue.replace(Default::default());
|
||||
}
|
||||
if !active && self.keyboard_queue.is_some() {
|
||||
self.keyboard_queue.take();
|
||||
let Ok(focus) = self.focus.upgrade() else {return};
|
||||
let Some((keyboard, keyboard_focus)) = seat_data.keyboard.get() else {return};
|
||||
if &*keyboard_focus.lock() == &Some(self.toplevel.id()) {
|
||||
keyboard.leave(SERIAL_COUNTER.inc(), &focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn handle_keyboard_events(&mut self, keyboard: &WlKeyboard, mut locked: bool) -> bool {
|
||||
let Ok(focus) = self.focus.upgrade() else { return false; };
|
||||
let Some(keyboard_queue) = self.keyboard_queue.as_mut() else { return false; };
|
||||
let Some(info) = self.keyboard_info.as_mut() else { return true; };
|
||||
|
||||
if !locked {
|
||||
keyboard.enter(0, &focus, vec![]);
|
||||
keyboard.repeat_info(0, 0);
|
||||
locked = info.keymap.send(keyboard).is_ok();
|
||||
}
|
||||
while let Some(event) = keyboard_queue.pop_front() {
|
||||
debug!(locked, ?event, "Process keyboard event");
|
||||
match (locked, event) {
|
||||
(true, KeyboardEvent::Keymap) => {
|
||||
let _ = info.keymap.send(keyboard);
|
||||
}
|
||||
(true, KeyboardEvent::Key { key, state }) => {
|
||||
if let Ok(key_count) = info.process(key, state, keyboard) {
|
||||
if key_count == 0 {
|
||||
keyboard.leave(SERIAL_COUNTER.inc(), &focus);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
(locked, event) => {
|
||||
warn!(locked, ?event, "Invalid keyboard event!");
|
||||
}
|
||||
}
|
||||
}
|
||||
locked
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SeatDataInner {
|
||||
client: ClientId,
|
||||
global_id: OnceCell<GlobalId>,
|
||||
pub panel_item: OnceCell<Weak<PanelItem>>,
|
||||
pointer: OnceCell<WlPointer>,
|
||||
pub pointer_focus: Mutex<Option<WlWeak<WlSurface>>>,
|
||||
keyboard: OnceCell<WlKeyboard>,
|
||||
pub keyboard_info: Mutex<Option<KeyboardInfo>>,
|
||||
panels: Mutex<FxHashMap<ObjectId, PanelInfo>>,
|
||||
pointer: OnceCell<(WlPointer, Mutex<Option<ObjectId>>)>,
|
||||
keyboard: OnceCell<(WlKeyboard, Mutex<Option<ObjectId>>)>,
|
||||
touch: OnceCell<WlTouch>,
|
||||
}
|
||||
impl SeatDataInner {
|
||||
pub fn pointer(&self) -> Option<&WlPointer> {
|
||||
self.pointer.get()
|
||||
// pub fn set_focus(&self, toplevel: &WlSurface, focus: &WlSurface) {
|
||||
// if let Some(panel_info) = self.panels.lock().get_mut(&toplevel.id()) {
|
||||
// panel_info.focus = focus.downgrade();
|
||||
// match panel_info.pointer_queue.back() {
|
||||
// None => (),
|
||||
// Some(&PointerEvent::Leave) => (),
|
||||
// _ => panel_info.pointer_queue.push_back(PointerEvent::Leave),
|
||||
// };
|
||||
// match panel_info.keyboard_queue.back() {
|
||||
// None => (),
|
||||
// Some(&KeyboardEvent::Leave) => (),
|
||||
// _ => panel_info.keyboard_queue.push_back(KeyboardEvent::Leave),
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
pub fn set_pointer_active(&self, toplevel: &XdgToplevel, active: bool) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return};
|
||||
panel_info.set_pointer_active(self, active);
|
||||
}
|
||||
pub fn pointer_active(&self) -> bool {
|
||||
self.pointer_focus.lock().is_some()
|
||||
pub fn set_keyboard_active(&self, toplevel: &XdgToplevel, active: bool) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return};
|
||||
panel_info.set_keyboard_active(self, active);
|
||||
}
|
||||
pub fn pointer_focused_surface(&self) -> Option<WlSurface> {
|
||||
self.pointer_focus
|
||||
.lock()
|
||||
.as_ref()
|
||||
.and_then(|focus| focus.upgrade().ok())
|
||||
}
|
||||
pub fn keyboard(&self) -> Option<&WlKeyboard> {
|
||||
self.keyboard.get()
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn touch(&self) -> Option<&WlTouch> {
|
||||
self.touch.get()
|
||||
pub fn set_keymap(&self, toplevel: &XdgToplevel, keymap: &Keymap) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return};
|
||||
panel_info.keyboard_info.replace(KeyboardInfo::new(keymap));
|
||||
|
||||
let Some(keyboard_queue) = panel_info.keyboard_queue.as_mut() else {return};
|
||||
let Some((_, focus)) = self.keyboard.get() else {return};
|
||||
let Some(id) = &*focus.lock() else {return};
|
||||
if id == &toplevel.id() {
|
||||
keyboard_queue.push_back(KeyboardEvent::Keymap);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> Option<WlSurface> {
|
||||
self.panel_item
|
||||
.get()?
|
||||
.upgrade()?
|
||||
.cursor
|
||||
pub fn pointer_event(&self, toplevel: &XdgToplevel, event: PointerEvent) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return};
|
||||
let Some(pointer_queue) = panel_info.pointer_queue.as_mut() else {return};
|
||||
pointer_queue.push_back(event);
|
||||
drop(panels);
|
||||
self.handle_pointer_events();
|
||||
}
|
||||
pub fn keyboard_event(&self, toplevel: &XdgToplevel, event: KeyboardEvent) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return};
|
||||
let Some(keyboard_queue) = panel_info.keyboard_queue.as_mut() else {return};
|
||||
keyboard_queue.push_back(event);
|
||||
drop(panels);
|
||||
self.handle_keyboard_events();
|
||||
}
|
||||
|
||||
fn handle_pointer_events(&self) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some((pointer, pointer_focus)) = self.pointer.get() else {return};
|
||||
let mut pointer_focus = pointer_focus.lock();
|
||||
|
||||
loop {
|
||||
let locked = pointer_focus.is_some();
|
||||
// Pick a pointer to focus on if there is none
|
||||
if pointer_focus.is_none() {
|
||||
*pointer_focus = panels
|
||||
.iter()
|
||||
.filter(|(_k, v)| v.pointer_queue.is_some())
|
||||
.filter(|(_k, v)| !v.pointer_queue.as_ref().unwrap().is_empty())
|
||||
.map(|(k, _v)| k)
|
||||
.choose(&mut thread_rng())
|
||||
.cloned();
|
||||
}
|
||||
if pointer_focus.is_none() {
|
||||
// If there's still none, guess we're done with pointer events for the time being
|
||||
break;
|
||||
}
|
||||
let Some(panel_info) = panels.get_mut(pointer_focus.as_ref().unwrap()) else {break};
|
||||
if panel_info.handle_pointer_events(pointer, locked) {
|
||||
// We haven't gotten to a point where we can switch the focus
|
||||
break;
|
||||
} else {
|
||||
pointer_focus.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
fn handle_keyboard_events(&self) {
|
||||
let mut panels = self.panels.lock();
|
||||
let Some((keyboard, keyboard_focus)) = self.keyboard.get() else {return};
|
||||
let mut keyboard_focus = keyboard_focus.lock();
|
||||
loop {
|
||||
let locked = keyboard_focus.is_some();
|
||||
// Pick a keyboard to focus on if there is none
|
||||
if keyboard_focus.is_none() {
|
||||
*keyboard_focus = panels
|
||||
.iter()
|
||||
.filter(|(_k, v)| v.keyboard_info.is_some())
|
||||
.filter(|(_k, v)| v.keyboard_queue.is_some())
|
||||
.filter(|(_k, v)| !v.keyboard_queue.as_ref().unwrap().is_empty())
|
||||
.map(|(k, _v)| k)
|
||||
.choose(&mut thread_rng())
|
||||
.cloned();
|
||||
}
|
||||
if keyboard_focus.is_none() {
|
||||
// If there's still none, guess we're done with keyboard events for the time being
|
||||
break;
|
||||
}
|
||||
let Some(panel_info) = panels.get_mut(keyboard_focus.as_ref().unwrap()) else {break};
|
||||
if panel_info.handle_keyboard_events(keyboard, locked) {
|
||||
// We haven't gotten to a point where we can switch the focus
|
||||
break;
|
||||
} else {
|
||||
keyboard_focus.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_panel_item(
|
||||
&self,
|
||||
panel_item: &Arc<PanelItem>,
|
||||
toplevel: &XdgToplevel,
|
||||
focus: &WlSurface,
|
||||
) {
|
||||
self.panels
|
||||
.lock()
|
||||
.as_ref()
|
||||
.and_then(|c| c.upgrade().ok())
|
||||
.insert(toplevel.id(), PanelInfo::new(panel_item, toplevel, focus));
|
||||
}
|
||||
pub fn drop_panel_item(&self, toplevel: &XdgToplevel) {
|
||||
self.panels.lock().remove(&toplevel.id());
|
||||
if let Some((_, pointer_focus)) = self.pointer.get() {
|
||||
let mut pointer_focus = pointer_focus.lock();
|
||||
if *pointer_focus == Some(toplevel.id()) {
|
||||
pointer_focus.take();
|
||||
}
|
||||
}
|
||||
if let Some((_, keyboard_focus)) = self.keyboard.get() {
|
||||
let mut keyboard_focus = keyboard_focus.lock();
|
||||
if *keyboard_focus == Some(toplevel.id()) {
|
||||
keyboard_focus.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for SeatDataInner {
|
||||
@@ -184,19 +482,20 @@ impl Dispatch<WlSeat, SeatData, WaylandState> for WaylandState {
|
||||
_state: &mut WaylandState,
|
||||
_client: &Client,
|
||||
_resource: &WlSeat,
|
||||
request: <WlSeat as Resource>::Request,
|
||||
request: wl_seat::Request,
|
||||
data: &SeatData,
|
||||
_dh: &DisplayHandle,
|
||||
data_init: &mut DataInit<'_, WaylandState>,
|
||||
) {
|
||||
match request {
|
||||
wl_seat::Request::GetPointer { id } => {
|
||||
let _ = data.0.pointer.set(data_init.init(id, data.clone()));
|
||||
let pointer = data_init.init(id, data.clone());
|
||||
let _ = data.0.pointer.set((pointer, Mutex::new(None)));
|
||||
}
|
||||
wl_seat::Request::GetKeyboard { id } => {
|
||||
let keyboard = data_init.init(id, data.clone());
|
||||
keyboard.repeat_info(0, 0);
|
||||
let _ = data.0.keyboard.set(keyboard);
|
||||
let _ = data.0.keyboard.set((keyboard, Mutex::new(None)));
|
||||
}
|
||||
wl_seat::Request::GetTouch { id } => {
|
||||
let _ = data.0.touch.set(data_init.init(id, data.clone()));
|
||||
@@ -207,6 +506,9 @@ impl Dispatch<WlSeat, SeatData, WaylandState> for WaylandState {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Cursor {
|
||||
pub hotspot: Vector2<i32>,
|
||||
}
|
||||
impl Dispatch<WlPointer, SeatData, WaylandState> for WaylandState {
|
||||
fn request(
|
||||
state: &mut WaylandState,
|
||||
@@ -241,10 +543,13 @@ impl Dispatch<WlPointer, SeatData, WaylandState> for WaylandState {
|
||||
})
|
||||
}
|
||||
|
||||
if let Some(panel_item) = seat_data.panel_item.get().and_then(|i| i.upgrade()) {
|
||||
panel_item.set_cursor(surface.as_ref(), hotspot_x, hotspot_y);
|
||||
*panel_item.cursor.lock() = surface.as_ref().map(|surf| surf.downgrade());
|
||||
}
|
||||
let Some((_, focus)) = seat_data.pointer.get() else {return};
|
||||
let focus = focus.lock();
|
||||
let Some(id) = &*focus else {return};
|
||||
let panels = seat_data.panels.lock();
|
||||
let Some(panel_info) = panels.get(&id) else {return};
|
||||
let Some(panel_item) = panel_info.panel_item.upgrade() else {return};
|
||||
panel_item.set_cursor(surface.as_ref(), hotspot_x, hotspot_y);
|
||||
}
|
||||
wl_pointer::Request::Release => (),
|
||||
_ => unreachable!(),
|
||||
|
||||
@@ -174,21 +174,6 @@ impl CoreSurface {
|
||||
if let Some(material_offset) = self.material_offset.lock().delta() {
|
||||
sk_mat.set_queue_offset(sk, *material_offset as i32);
|
||||
}
|
||||
// if let Some(geometry) = self.geometry.lock().delta().cloned().unwrap_or_default() {
|
||||
// let buffer_size = renderer_surface_state.buffer_size().unwrap();
|
||||
// let surface_size = dbg!(vec2(buffer_size.w as f32, buffer_size.h as f32));
|
||||
// let geometry_origin =
|
||||
// dbg!(vec2(geometry.origin.x as f32, geometry.origin.y as f32));
|
||||
// let geometry_size = dbg!(vec2(geometry.size.x as f32, geometry.size.y as f32));
|
||||
// sk_mat.set_parameter(
|
||||
// "uv_offset",
|
||||
// &Vector2::from(dbg!(geometry_origin / surface_size)),
|
||||
// );
|
||||
// sk_mat.set_parameter(
|
||||
// "uv_scale",
|
||||
// &Vector2::from(dbg!(geometry_size / surface_size)),
|
||||
// );
|
||||
// }
|
||||
|
||||
let surface_size = renderer_surface_state.surface_size().unwrap();
|
||||
let new_mapped_data = CoreSurfaceData {
|
||||
@@ -196,7 +181,6 @@ impl CoreSurface {
|
||||
wl_tex: Some(SendWrapper::new(smithay_tex)),
|
||||
};
|
||||
*mapped_data = Some(new_mapped_data);
|
||||
// }
|
||||
});
|
||||
self.apply_surface_materials();
|
||||
|
||||
@@ -209,10 +193,6 @@ impl CoreSurface {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn mapped(&self) -> bool {
|
||||
self.mapped_data.lock().is_some()
|
||||
}
|
||||
|
||||
pub fn set_material_offset(&self, material_offset: u32) {
|
||||
*self.material_offset.lock().value_mut() = material_offset;
|
||||
}
|
||||
@@ -248,11 +228,8 @@ impl CoreSurface {
|
||||
.map(|wl_surface| compositor::with_states(&wl_surface, f))
|
||||
}
|
||||
|
||||
pub fn with_data<F, T>(&self, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&mut CoreSurfaceData) -> T,
|
||||
{
|
||||
self.mapped_data.lock().as_mut().map(f)
|
||||
pub fn size(&self) -> Option<Vector2<u32>> {
|
||||
self.mapped_data.lock().as_ref().map(|d| d.size)
|
||||
}
|
||||
|
||||
pub fn flush_clients(&self) {
|
||||
|
||||
@@ -238,6 +238,7 @@ impl Dispatch<XdgSurface, WaylandSurface, WaylandState> for WaylandState {
|
||||
|
||||
let (node, item) = PanelItem::create(
|
||||
toplevel,
|
||||
data.wl_surface.upgrade().unwrap(),
|
||||
client.get_credentials(&state.display_handle).ok(),
|
||||
state.seats.get(&client.id()).unwrap().clone(),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user