refactor: extract input handling

This commit is contained in:
drendog 2026-01-18 02:34:08 +01:00
parent d5b4953c1a
commit 4be98d3ba5
Signed by: dwenya
GPG key ID: 8DD77074645332D0
9 changed files with 533 additions and 246 deletions

View file

@ -0,0 +1,90 @@
use crate::wayland::surfaces::keyboard_state::{KeyboardState, keysym_to_text};
use slint::{SharedString, platform::WindowEvent};
use wayland_client::{
Proxy,
backend::ObjectId,
protocol::{wl_keyboard, wl_surface::WlSurface},
};
use xkbcommon::xkb;
use super::state::KeyboardInputState;
pub trait KeyboardEventTarget {
fn dispatch_event(&self, event: WindowEvent);
}
pub trait KeyboardSurfaceResolver {
type Target: KeyboardEventTarget;
fn find_surface(&self, surface_id: &ObjectId) -> Option<&Self::Target>;
}
pub fn handle_keyboard_enter<R: KeyboardSurfaceResolver>(
input_state: &mut KeyboardInputState,
resolver: &R,
surface: &WlSurface,
) -> bool {
let surface_id = surface.id();
if resolver.find_surface(&surface_id).is_some() {
input_state.set_focused_surface(Some(surface_id));
return true;
}
false
}
pub fn handle_keyboard_leave(input_state: &mut KeyboardInputState, surface: &WlSurface) -> bool {
let surface_id = surface.id();
if input_state.focused_surface_id() == Some(&surface_id) {
input_state.set_focused_surface(None);
return true;
}
false
}
pub fn handle_keyboard_key<R: KeyboardSurfaceResolver>(
input_state: &KeyboardInputState,
resolver: &R,
key: u32,
state: wl_keyboard::KeyState,
keyboard_state: &mut KeyboardState,
) -> bool {
let Some(surface_id) = input_state.focused_surface_id().cloned() else {
return false;
};
let Some(target) = resolver.find_surface(&surface_id) else {
return false;
};
let Some(xkb_state) = keyboard_state.xkb_state.as_mut() else {
return true;
};
let keycode = xkb::Keycode::new(key + 8);
let direction = match state {
wl_keyboard::KeyState::Pressed => xkb::KeyDirection::Down,
wl_keyboard::KeyState::Released => xkb::KeyDirection::Up,
_ => return true,
};
xkb_state.update_key(keycode, direction);
let text = xkb_state.key_get_utf8(keycode);
let text = if text.is_empty() {
let keysym = xkb_state.key_get_one_sym(keycode);
keysym_to_text(keysym)
} else {
Some(SharedString::from(text.as_str()))
};
let Some(text) = text else {
return true;
};
let event = match state {
wl_keyboard::KeyState::Pressed => WindowEvent::KeyPressed { text },
wl_keyboard::KeyState::Released => WindowEvent::KeyReleased { text },
_ => return true,
};
target.dispatch_event(event);
true
}

View file

@ -0,0 +1,7 @@
pub mod keyboard;
pub mod pointer;
pub mod state;
pub use keyboard::{KeyboardEventTarget, KeyboardSurfaceResolver};
pub use pointer::{PointerEventTarget, PointerSurfaceResolver};
pub use state::{KeyboardInputState, PointerInputState};

View file

@ -0,0 +1,196 @@
use crate::wayland::surfaces::pointer_utils::wayland_button_to_slint;
use slint::{LogicalPosition, platform::WindowEvent};
use wayland_client::{
Proxy, WEnum,
backend::ObjectId,
protocol::{wl_pointer, wl_surface::WlSurface},
};
use super::state::PointerInputState;
pub trait PointerEventTarget {
fn to_logical_position(&self, surface_x: f64, surface_y: f64) -> LogicalPosition;
fn dispatch_event(&self, event: WindowEvent);
}
pub trait PointerSurfaceResolver {
type Target: PointerEventTarget;
fn find_surface(&self, surface_id: &ObjectId) -> Option<&Self::Target>;
}
pub fn handle_pointer_enter<R: PointerSurfaceResolver>(
input_state: &mut PointerInputState,
resolver: &R,
_serial: u32,
surface: &WlSurface,
surface_x: f64,
surface_y: f64,
) -> bool {
let surface_id = surface.id();
let Some(target) = resolver.find_surface(&surface_id) else {
return false;
};
let position = target.to_logical_position(surface_x, surface_y);
input_state.set_active_surface(Some(surface_id));
input_state.set_current_position(position);
target.dispatch_event(WindowEvent::PointerMoved { position });
true
}
pub fn handle_pointer_motion<R: PointerSurfaceResolver>(
input_state: &mut PointerInputState,
resolver: &R,
surface_x: f64,
surface_y: f64,
) -> bool {
let Some(surface_id) = input_state.active_surface_id().cloned() else {
return false;
};
let Some(target) = resolver.find_surface(&surface_id) else {
return false;
};
let position = target.to_logical_position(surface_x, surface_y);
input_state.set_current_position(position);
target.dispatch_event(WindowEvent::PointerMoved { position });
true
}
pub fn handle_pointer_leave<R: PointerSurfaceResolver>(
input_state: &mut PointerInputState,
resolver: &R,
) -> bool {
let Some(surface_id) = input_state.active_surface_id().cloned() else {
return false;
};
if let Some(target) = resolver.find_surface(&surface_id) {
target.dispatch_event(WindowEvent::PointerExited);
}
input_state.set_active_surface(None);
true
}
pub fn handle_pointer_button<R: PointerSurfaceResolver>(
input_state: &PointerInputState,
resolver: &R,
_scale_factor: f32,
_serial: u32,
button: u32,
button_state: WEnum<wl_pointer::ButtonState>,
) -> bool {
let Some(surface_id) = input_state.active_surface_id() else {
return false;
};
let Some(target) = resolver.find_surface(surface_id) else {
return false;
};
let position = input_state.current_position();
let slint_button = wayland_button_to_slint(button);
let event = match button_state {
WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed {
button: slint_button,
position,
},
WEnum::Value(wl_pointer::ButtonState::Released) => WindowEvent::PointerReleased {
button: slint_button,
position,
},
_ => return true,
};
target.dispatch_event(event);
true
}
pub fn handle_axis_source(
input_state: &PointerInputState,
_axis_source: wl_pointer::AxisSource,
) -> bool {
input_state.has_active_surface()
}
pub fn handle_axis(
input_state: &mut PointerInputState,
axis: wl_pointer::Axis,
value: f64,
) -> bool {
if !input_state.has_active_surface() {
return false;
}
#[allow(clippy::cast_possible_truncation)]
let delta = value as f32;
match axis {
wl_pointer::Axis::HorizontalScroll => {
input_state.accumulate_axis_value(delta, 0.0);
}
wl_pointer::Axis::VerticalScroll => {
input_state.accumulate_axis_value(0.0, delta);
}
_ => {}
}
true
}
pub fn handle_axis_discrete(
input_state: &mut PointerInputState,
axis: wl_pointer::Axis,
discrete: i32,
) -> bool {
if !input_state.has_active_surface() {
return false;
}
#[allow(clippy::cast_precision_loss)]
let delta = (discrete as f32) * 60.0;
match axis {
wl_pointer::Axis::HorizontalScroll => {
input_state.accumulate_axis_value(delta, 0.0);
}
wl_pointer::Axis::VerticalScroll => {
input_state.accumulate_axis_value(0.0, delta);
}
_ => {}
}
true
}
pub fn handle_axis_stop(_input_state: &PointerInputState, _axis: wl_pointer::Axis) -> bool {
true
}
pub fn handle_pointer_frame<R: PointerSurfaceResolver>(
input_state: &mut PointerInputState,
resolver: &R,
) -> bool {
let Some(surface_id) = input_state.active_surface_id().cloned() else {
return false;
};
let (delta_x, delta_y) = input_state.take_accumulated_axis();
let Some(target) = resolver.find_surface(&surface_id) else {
return false;
};
if delta_x.abs() > f32::EPSILON || delta_y.abs() > f32::EPSILON {
let position = input_state.current_position();
target.dispatch_event(WindowEvent::PointerScrolled {
position,
delta_x,
delta_y,
});
}
true
}

View file

@ -0,0 +1,112 @@
use slint::LogicalPosition;
use wayland_client::backend::ObjectId;
pub struct PointerInputState {
active_surface_id: Option<ObjectId>,
current_position: LogicalPosition,
accumulated_axis_x: f32,
accumulated_axis_y: f32,
}
impl PointerInputState {
pub const fn new() -> Self {
Self {
active_surface_id: None,
current_position: LogicalPosition::new(0.0, 0.0),
accumulated_axis_x: 0.0,
accumulated_axis_y: 0.0,
}
}
pub const fn active_surface_id(&self) -> Option<&ObjectId> {
self.active_surface_id.as_ref()
}
pub fn set_active_surface(&mut self, surface_id: Option<ObjectId>) {
self.active_surface_id = surface_id;
}
pub const fn current_position(&self) -> LogicalPosition {
self.current_position
}
pub fn set_current_position(&mut self, position: LogicalPosition) {
self.current_position = position;
}
pub fn accumulate_axis_value(&mut self, delta_x: f32, delta_y: f32) {
self.accumulated_axis_x += delta_x;
self.accumulated_axis_y += delta_y;
}
pub fn take_accumulated_axis(&mut self) -> (f32, f32) {
let delta_x = self.accumulated_axis_x;
let delta_y = self.accumulated_axis_y;
self.accumulated_axis_x = 0.0;
self.accumulated_axis_y = 0.0;
(delta_x, delta_y)
}
pub fn reset(&mut self) {
self.active_surface_id = None;
self.current_position = LogicalPosition::new(0.0, 0.0);
self.accumulated_axis_x = 0.0;
self.accumulated_axis_y = 0.0;
}
pub fn clear_surface_if_matches(&mut self, surface_id: &ObjectId) {
if self.active_surface_id.as_ref() == Some(surface_id) {
self.active_surface_id = None;
}
}
pub const fn has_active_surface(&self) -> bool {
self.active_surface_id.is_some()
}
}
impl Default for PointerInputState {
fn default() -> Self {
Self::new()
}
}
pub struct KeyboardInputState {
focused_surface_id: Option<ObjectId>,
}
impl KeyboardInputState {
pub const fn new() -> Self {
Self {
focused_surface_id: None,
}
}
pub const fn focused_surface_id(&self) -> Option<&ObjectId> {
self.focused_surface_id.as_ref()
}
pub fn set_focused_surface(&mut self, surface_id: Option<ObjectId>) {
self.focused_surface_id = surface_id;
}
pub fn reset(&mut self) {
self.focused_surface_id = None;
}
pub fn clear_surface_if_matches(&mut self, surface_id: &ObjectId) {
if self.focused_surface_id.as_ref() == Some(surface_id) {
self.focused_surface_id = None;
}
}
pub const fn has_focused_surface(&self) -> bool {
self.focused_surface_id.is_some()
}
}
impl Default for KeyboardInputState {
fn default() -> Self {
Self::new()
}
}

View file

@ -1,6 +1,7 @@
pub(crate) mod config;
pub(crate) mod event_handling;
pub(crate) mod globals;
pub(crate) mod input;
pub(crate) mod managed_proxies;
pub mod ops;
pub(crate) mod outputs;

View file

@ -1,87 +1,113 @@
use crate::wayland::surfaces::keyboard_state::{KeyboardState, keysym_to_text};
use crate::wayland::surfaces::pointer_utils::wayland_button_to_slint;
use log::info;
use slint::{
LogicalPosition, SharedString,
platform::{WindowAdapter, WindowEvent},
use crate::wayland::input::keyboard::{
handle_keyboard_enter as shared_keyboard_enter, handle_keyboard_key as shared_keyboard_key,
handle_keyboard_leave as shared_keyboard_leave,
};
use crate::wayland::input::pointer::{
handle_axis as shared_axis, handle_axis_discrete as shared_axis_discrete,
handle_axis_source as shared_axis_source, handle_axis_stop as shared_axis_stop,
handle_pointer_button as shared_pointer_button, handle_pointer_enter as shared_pointer_enter,
handle_pointer_frame as shared_pointer_frame, handle_pointer_leave as shared_pointer_leave,
handle_pointer_motion as shared_pointer_motion,
};
use crate::wayland::input::{
KeyboardEventTarget, KeyboardInputState, KeyboardSurfaceResolver, PointerEventTarget,
PointerInputState, PointerSurfaceResolver,
};
use crate::wayland::surfaces::keyboard_state::KeyboardState;
use slint::{LogicalPosition, platform::WindowEvent};
use wayland_client::{
Proxy, WEnum,
WEnum,
backend::ObjectId,
protocol::{wl_keyboard, wl_pointer, wl_surface::WlSurface},
};
use xkbcommon::xkb;
use super::state::ActiveLockSurface;
pub(super) struct InputState {
pub active_pointer_surface_id: Option<ObjectId>,
pub keyboard_focus_surface_id: Option<ObjectId>,
pub current_pointer_position: LogicalPosition,
pub accumulated_axis_x: f32,
pub accumulated_axis_y: f32,
pub pointer: PointerInputState,
pub keyboard: KeyboardInputState,
}
impl InputState {
pub fn new() -> Self {
Self {
active_pointer_surface_id: None,
keyboard_focus_surface_id: None,
current_pointer_position: LogicalPosition::new(0.0, 0.0),
accumulated_axis_x: 0.0,
accumulated_axis_y: 0.0,
pointer: PointerInputState::new(),
keyboard: KeyboardInputState::new(),
}
}
pub fn reset(&mut self) {
self.active_pointer_surface_id = None;
self.keyboard_focus_surface_id = None;
self.current_pointer_position = LogicalPosition::new(0.0, 0.0);
self.accumulated_axis_x = 0.0;
self.accumulated_axis_y = 0.0;
self.pointer.reset();
self.keyboard.reset();
}
pub fn clear_surface_refs(&mut self, surface_id: &ObjectId) {
if self.active_pointer_surface_id.as_ref() == Some(surface_id) {
self.active_pointer_surface_id = None;
}
if self.keyboard_focus_surface_id.as_ref() == Some(surface_id) {
self.keyboard_focus_surface_id = None;
}
self.pointer.clear_surface_if_matches(surface_id);
self.keyboard.clear_surface_if_matches(surface_id);
}
pub const fn has_active_pointer(&self) -> bool {
self.active_pointer_surface_id.is_some()
self.pointer.has_active_surface()
}
pub const fn has_keyboard_focus(&self) -> bool {
self.keyboard_focus_surface_id.is_some()
self.keyboard.has_focused_surface()
}
}
impl PointerEventTarget for ActiveLockSurface {
fn to_logical_position(&self, surface_x: f64, surface_y: f64) -> LogicalPosition {
ActiveLockSurface::to_logical_position(self, surface_x, surface_y)
}
fn dispatch_event(&self, event: WindowEvent) {
ActiveLockSurface::dispatch_event(self, event);
}
}
impl KeyboardEventTarget for ActiveLockSurface {
fn dispatch_event(&self, event: WindowEvent) {
ActiveLockSurface::dispatch_event(self, event);
}
}
struct LockSurfaceResolver<'a> {
lock_surfaces: &'a [(ObjectId, ActiveLockSurface)],
}
impl PointerSurfaceResolver for LockSurfaceResolver<'_> {
type Target = ActiveLockSurface;
fn find_surface(&self, surface_id: &ObjectId) -> Option<&Self::Target> {
find_surface_by_surface_id(self.lock_surfaces, surface_id)
}
}
impl KeyboardSurfaceResolver for LockSurfaceResolver<'_> {
type Target = ActiveLockSurface;
fn find_surface(&self, surface_id: &ObjectId) -> Option<&Self::Target> {
find_surface_by_surface_id(self.lock_surfaces, surface_id)
}
}
pub(super) fn handle_pointer_enter(
input_state: &mut InputState,
lock_surfaces: &[(ObjectId, ActiveLockSurface)],
_serial: u32,
serial: u32,
surface: &WlSurface,
surface_x: f64,
surface_y: f64,
) -> bool {
let surface_id = surface.id();
let Some(active_surface) = find_surface_by_surface_id(lock_surfaces, &surface_id) else {
return false;
};
let position = active_surface.to_logical_position(surface_x, surface_y);
let window = active_surface.window_rc();
input_state.active_pointer_surface_id = Some(surface_id.clone());
input_state.current_pointer_position = position;
info!("Lock pointer enter on {:?}", surface_id);
window
.window()
.dispatch_event(WindowEvent::PointerMoved { position });
true
let resolver = LockSurfaceResolver { lock_surfaces };
shared_pointer_enter(
&mut input_state.pointer,
&resolver,
serial,
surface,
surface_x,
surface_y,
)
}
pub(super) fn handle_pointer_motion(
@ -90,80 +116,42 @@ pub(super) fn handle_pointer_motion(
surface_x: f64,
surface_y: f64,
) -> bool {
let Some(surface_id) = input_state.active_pointer_surface_id.clone() else {
return false;
};
let Some(active_surface) = find_surface_by_surface_id(lock_surfaces, &surface_id) else {
return false;
};
let position = active_surface.to_logical_position(surface_x, surface_y);
let window = active_surface.window_rc();
input_state.current_pointer_position = position;
window
.window()
.dispatch_event(WindowEvent::PointerMoved { position });
true
let resolver = LockSurfaceResolver { lock_surfaces };
shared_pointer_motion(&mut input_state.pointer, &resolver, surface_x, surface_y)
}
pub(super) fn handle_pointer_leave(
input_state: &mut InputState,
lock_surfaces: &[(ObjectId, ActiveLockSurface)],
) -> bool {
let Some(surface_id) = input_state.active_pointer_surface_id.take() else {
return false;
};
if let Some(active_surface) = find_surface_by_surface_id(lock_surfaces, &surface_id) {
active_surface.dispatch_event(WindowEvent::PointerExited);
}
true
let resolver = LockSurfaceResolver { lock_surfaces };
shared_pointer_leave(&mut input_state.pointer, &resolver)
}
pub(super) fn handle_pointer_button(
input_state: &mut InputState,
lock_surfaces: &[(ObjectId, ActiveLockSurface)],
scale_factor: f32,
_serial: u32,
serial: u32,
button: u32,
button_state: WEnum<wl_pointer::ButtonState>,
) -> bool {
let Some(surface_id) = input_state.active_pointer_surface_id.clone() else {
return false;
};
let Some(active_surface) = find_surface_by_surface_id(lock_surfaces, &surface_id) else {
return false;
};
let window = active_surface.window_rc();
let position = input_state.current_pointer_position;
let slint_button = wayland_button_to_slint(button);
let event = match button_state {
WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed {
button: slint_button,
position,
},
WEnum::Value(wl_pointer::ButtonState::Released) => WindowEvent::PointerReleased {
button: slint_button,
position,
},
_ => return true,
};
info!(
"Lock pointer button {:?} at {:?} (scale {})",
button_state, position, scale_factor
);
window.window().dispatch_event(event);
true
let resolver = LockSurfaceResolver { lock_surfaces };
shared_pointer_button(
&input_state.pointer,
&resolver,
scale_factor,
serial,
button,
button_state,
)
}
pub(super) fn handle_axis_source(
input_state: &InputState,
_axis_source: wl_pointer::AxisSource,
axis_source: wl_pointer::AxisSource,
) -> bool {
input_state.active_pointer_surface_id.is_some()
shared_axis_source(&input_state.pointer, axis_source)
}
pub(super) fn handle_axis(
@ -171,24 +159,7 @@ pub(super) fn handle_axis(
axis: wl_pointer::Axis,
value: f64,
) -> bool {
if input_state.active_pointer_surface_id.is_none() {
return false;
}
match axis {
wl_pointer::Axis::HorizontalScroll => {
#[allow(clippy::cast_possible_truncation)]
let delta = value as f32;
input_state.accumulated_axis_x += delta;
}
wl_pointer::Axis::VerticalScroll => {
#[allow(clippy::cast_possible_truncation)]
let delta = value as f32;
input_state.accumulated_axis_y += delta;
}
_ => {}
}
true
shared_axis(&mut input_state.pointer, axis, value)
}
pub(super) fn handle_axis_discrete(
@ -196,58 +167,19 @@ pub(super) fn handle_axis_discrete(
axis: wl_pointer::Axis,
discrete: i32,
) -> bool {
if input_state.active_pointer_surface_id.is_none() {
return false;
shared_axis_discrete(&mut input_state.pointer, axis, discrete)
}
#[allow(clippy::cast_precision_loss)]
let delta = (discrete as f32) * 60.0;
match axis {
wl_pointer::Axis::HorizontalScroll => {
input_state.accumulated_axis_x += delta;
}
wl_pointer::Axis::VerticalScroll => {
input_state.accumulated_axis_y += delta;
}
_ => {}
}
true
}
pub(super) fn handle_axis_stop(input_state: &InputState, _axis: wl_pointer::Axis) -> bool {
input_state.active_pointer_surface_id.is_some()
pub(super) fn handle_axis_stop(input_state: &InputState, axis: wl_pointer::Axis) -> bool {
shared_axis_stop(&input_state.pointer, axis)
}
pub(super) fn handle_pointer_frame(
input_state: &mut InputState,
lock_surfaces: &[(ObjectId, ActiveLockSurface)],
) -> bool {
let Some(surface_id) = input_state.active_pointer_surface_id.clone() else {
return false;
};
let delta_x = input_state.accumulated_axis_x;
let delta_y = input_state.accumulated_axis_y;
input_state.accumulated_axis_x = 0.0;
input_state.accumulated_axis_y = 0.0;
let Some(active_surface) = find_surface_by_surface_id(lock_surfaces, &surface_id) else {
return false;
};
let window = active_surface.window_rc();
if delta_x.abs() > f32::EPSILON || delta_y.abs() > f32::EPSILON {
let position = input_state.current_pointer_position;
window
.window()
.dispatch_event(WindowEvent::PointerScrolled {
position,
delta_x,
delta_y,
});
}
true
let resolver = LockSurfaceResolver { lock_surfaces };
shared_pointer_frame(&mut input_state.pointer, &resolver)
}
pub(super) fn handle_keyboard_enter(
@ -255,21 +187,12 @@ pub(super) fn handle_keyboard_enter(
lock_surfaces: &[(ObjectId, ActiveLockSurface)],
surface: &WlSurface,
) -> bool {
let surface_id = surface.id();
if find_surface_by_surface_id(lock_surfaces, &surface_id).is_some() {
input_state.keyboard_focus_surface_id = Some(surface_id);
return true;
}
false
let resolver = LockSurfaceResolver { lock_surfaces };
shared_keyboard_enter(&mut input_state.keyboard, &resolver, surface)
}
pub(super) fn handle_keyboard_leave(input_state: &mut InputState, surface: &WlSurface) -> bool {
let surface_id = surface.id();
if input_state.keyboard_focus_surface_id.as_ref() == Some(&surface_id) {
input_state.keyboard_focus_surface_id = None;
return true;
}
false
shared_keyboard_leave(&mut input_state.keyboard, surface)
}
pub(super) fn handle_keyboard_key(
@ -279,45 +202,8 @@ pub(super) fn handle_keyboard_key(
state: wl_keyboard::KeyState,
keyboard_state: &mut KeyboardState,
) -> bool {
let Some(surface_id) = input_state.keyboard_focus_surface_id.clone() else {
return false;
};
let Some(active_surface) = find_surface_by_surface_id(lock_surfaces, &surface_id) else {
return false;
};
let Some(xkb_state) = keyboard_state.xkb_state.as_mut() else {
return true;
};
let keycode = xkb::Keycode::new(key + 8);
let direction = match state {
wl_keyboard::KeyState::Pressed => xkb::KeyDirection::Down,
wl_keyboard::KeyState::Released => xkb::KeyDirection::Up,
_ => return true,
};
xkb_state.update_key(keycode, direction);
let text = xkb_state.key_get_utf8(keycode);
let text = if text.is_empty() {
let keysym = xkb_state.key_get_one_sym(keycode);
keysym_to_text(keysym)
} else {
Some(SharedString::from(text.as_str()))
};
let Some(text) = text else {
return true;
};
let event = match state {
wl_keyboard::KeyState::Pressed => WindowEvent::KeyPressed { text },
wl_keyboard::KeyState::Released => WindowEvent::KeyReleased { text },
_ => return true,
};
info!("Lock key event {:?}", state);
active_surface.dispatch_event(event);
true
let resolver = LockSurfaceResolver { lock_surfaces };
shared_keyboard_key(&input_state.keyboard, &resolver, key, state, keyboard_state)
}
fn find_surface_by_surface_id<'a>(

View file

@ -273,10 +273,6 @@ impl ActiveLockSurface {
self.window.window().dispatch_event(event);
}
pub fn window_rc(&self) -> Rc<FemtoVGWindow> {
Rc::clone(&self.window)
}
pub const fn surface(&self) -> &LockSurface {
&self.surface
}

View file

@ -5,6 +5,7 @@ use crate::errors::{LayerShikaError, Result};
use crate::rendering::egl::context_factory::RenderContextFactory;
use crate::rendering::slint_integration::platform::CustomSlintPlatform;
use crate::wayland::globals::context::GlobalContext;
use crate::wayland::input::KeyboardInputState;
use crate::wayland::managed_proxies::{ManagedWlKeyboard, ManagedWlPointer};
use crate::wayland::outputs::{OutputManager, OutputMapping};
use crate::wayland::session_lock::lock_context::SessionLockContext;
@ -63,7 +64,7 @@ pub struct AppState {
registry_name_to_output_id: HashMap<u32, ObjectId>,
active_surface_key: Option<ShellSurfaceKey>,
keyboard_focus_key: Option<ShellSurfaceKey>,
keyboard_focus_surface_id: Option<ObjectId>,
keyboard_input_state: KeyboardInputState,
keyboard_state: KeyboardState,
lock_manager: Option<SessionLockManager>,
lock_callbacks: Vec<LockCallback>,
@ -92,7 +93,7 @@ impl AppState {
registry_name_to_output_id: HashMap::new(),
active_surface_key: None,
keyboard_focus_key: None,
keyboard_focus_surface_id: None,
keyboard_input_state: KeyboardInputState::new(),
keyboard_state: KeyboardState::new(),
lock_manager: None,
lock_callbacks: Vec::new(),
@ -626,19 +627,23 @@ impl AppState {
pub fn handle_keyboard_enter(&mut self, _serial: u32, surface: &WlSurface, _keys: &[u8]) {
if let Some(manager) = self.lock_manager.as_mut() {
if manager.handle_keyboard_enter(surface) {
self.set_keyboard_focus(None, None);
self.set_keyboard_focus(None);
return;
}
}
let surface_id = surface.id();
if let Some(key) = self.get_key_by_surface(&surface_id).cloned() {
self.set_keyboard_focus(Some(key), Some(surface_id));
self.keyboard_input_state
.set_focused_surface(Some(surface_id.clone()));
self.set_keyboard_focus(Some(key));
return;
}
if let Some(key) = self.get_key_by_popup(&surface_id).cloned() {
self.set_keyboard_focus(Some(key), Some(surface_id));
self.keyboard_input_state
.set_focused_surface(Some(surface_id));
self.set_keyboard_focus(Some(key));
}
}
@ -649,8 +654,10 @@ impl AppState {
}
}
if self.keyboard_focus_surface_id == Some(surface.id()) {
self.set_keyboard_focus(None, None);
let surface_id = surface.id();
if self.keyboard_input_state.focused_surface_id() == Some(&surface_id) {
self.keyboard_input_state.reset();
self.set_keyboard_focus(None);
}
}
@ -664,7 +671,7 @@ impl AppState {
let Some(focus_key) = self.keyboard_focus_key.clone() else {
return;
};
let Some(surface_id) = self.keyboard_focus_surface_id.clone() else {
let Some(surface_id) = self.keyboard_input_state.focused_surface_id().cloned() else {
return;
};
@ -691,12 +698,11 @@ impl AppState {
self.keyboard_state.repeat_delay = delay;
}
fn set_keyboard_focus(&mut self, key: Option<ShellSurfaceKey>, surface_id: Option<ObjectId>) {
fn set_keyboard_focus(&mut self, key: Option<ShellSurfaceKey>) {
if let Some(ref k) = key {
self.output_registry.set_active(Some(k.output_handle));
}
self.keyboard_focus_key = key;
self.keyboard_focus_surface_id = surface_id;
}
pub fn find_output_by_popup(&self, popup_surface_id: &ObjectId) -> Option<&PerOutputSurface> {

View file

@ -1,4 +1,5 @@
use crate::rendering::femtovg::main_window::FemtoVGWindow;
use crate::wayland::input::PointerInputState;
use crate::wayland::surfaces::display_metrics::SharedDisplayMetrics;
use crate::wayland::surfaces::popup_manager::{ActiveWindow, PopupManager};
use slint::platform::{WindowAdapter, WindowEvent};
@ -43,12 +44,10 @@ pub struct EventContext {
main_surface_id: ObjectId,
popup_manager: Option<Rc<PopupManager>>,
display_metrics: SharedDisplayMetrics,
current_pointer_position: LogicalPosition,
pointer_state: PointerInputState,
last_pointer_serial: u32,
shared_pointer_serial: Option<Rc<SharedPointerSerial>>,
active_surface: ActiveWindow,
accumulated_axis_x: f32,
accumulated_axis_y: f32,
axis_source: Option<wl_pointer::AxisSource>,
}
@ -64,12 +63,10 @@ impl EventContext {
main_surface_id,
popup_manager: None,
display_metrics,
current_pointer_position: LogicalPosition::new(0.0, 0.0),
pointer_state: PointerInputState::new(),
last_pointer_serial: 0,
shared_pointer_serial: None,
active_surface: ActiveWindow::None,
accumulated_axis_x: 0.0,
accumulated_axis_y: 0.0,
axis_source: None,
}
}
@ -101,7 +98,7 @@ impl EventContext {
}
pub const fn current_pointer_position(&self) -> LogicalPosition {
self.current_pointer_position
self.pointer_state.current_position()
}
#[allow(clippy::cast_possible_truncation)]
@ -117,7 +114,7 @@ impl EventContext {
(physical_y / f64::from(scale_factor)) as f32,
)
};
self.current_pointer_position = logical_position;
self.pointer_state.set_current_position(logical_position);
}
pub const fn last_pointer_serial(&self) -> u32 {
@ -222,12 +219,13 @@ impl EventContext {
#[allow(clippy::cast_possible_truncation)]
pub fn accumulate_axis(&mut self, axis: wl_pointer::Axis, value: f64) {
let delta = value as f32;
match axis {
wl_pointer::Axis::HorizontalScroll => {
self.accumulated_axis_x += value as f32;
self.pointer_state.accumulate_axis_value(delta, 0.0);
}
wl_pointer::Axis::VerticalScroll => {
self.accumulated_axis_y += value as f32;
self.pointer_state.accumulate_axis_value(0.0, delta);
}
_ => {}
}
@ -239,23 +237,18 @@ impl EventContext {
match axis {
wl_pointer::Axis::HorizontalScroll => {
self.accumulated_axis_x += delta;
self.pointer_state.accumulate_axis_value(delta, 0.0);
}
wl_pointer::Axis::VerticalScroll => {
self.accumulated_axis_y += delta;
self.pointer_state.accumulate_axis_value(0.0, delta);
}
_ => {}
}
}
pub fn take_accumulated_axis(&mut self) -> (f32, f32) {
let delta_x = self.accumulated_axis_x;
let delta_y = self.accumulated_axis_y;
self.accumulated_axis_x = 0.0;
self.accumulated_axis_y = 0.0;
let (delta_x, delta_y) = self.pointer_state.take_accumulated_axis();
self.axis_source = None;
(delta_x, delta_y)
}
}