layer-shika/crates/adapters/src/wayland/event_handling/event_dispatcher.rs

228 lines
7.4 KiB
Rust

use crate::wayland::surfaces::surface_state::SurfaceState;
use log::info;
use slint::{
PhysicalSize,
platform::{PointerEventButton, WindowEvent},
};
use smithay_client_toolkit::reexports::protocols_wlr::layer_shell::v1::client::{
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
};
use wayland_client::WEnum;
use wayland_client::{
Proxy,
protocol::{
wl_pointer,
wl_surface::WlSurface,
},
};
use wayland_protocols::wp::fractional_scale::v1::client::{
wp_fractional_scale_v1::WpFractionalScaleV1,
};
use wayland_protocols::xdg::shell::client::{
xdg_popup::XdgPopup,
xdg_surface::XdgSurface,
xdg_wm_base::XdgWmBase,
};
impl SurfaceState {
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_precision_loss)]
pub(crate) fn handle_layer_surface_configure(
&mut self,
layer_surface: &ZwlrLayerSurfaceV1,
serial: u32,
width: u32,
height: u32,
) {
info!("Layer surface configured with compositor size: {width}x{height}");
layer_surface.ack_configure(serial);
let output_width = self.output_size().width;
let scale_factor = self.scale_factor();
let target_width = if width == 0 || (width == 1 && output_width > 1) {
if scale_factor > 1.0 {
(output_width as f32 / scale_factor).round() as u32
} else {
output_width
}
} else {
width
};
let target_height = if height > 0 {
height
} else {
let h = self.height();
if scale_factor > 1.0 {
(h as f32 / scale_factor).round() as u32
} else {
h
}
};
let clamped_width = target_width.min(output_width);
info!(
"Using dimensions: {}x{} (clamped from {}x{}, output: {}x{})",
clamped_width,
target_height,
target_width,
target_height,
output_width,
self.output_size().height
);
self.update_size(clamped_width, target_height);
}
#[allow(clippy::unused_self)]
pub(crate) fn handle_layer_surface_closed(&mut self) {
info!("Layer surface closed");
}
pub(crate) fn handle_output_mode(&mut self, width: i32, height: i32) {
info!("WlOutput size changed to {width}x{height}");
let width = width.try_into().unwrap_or_default();
let height = height.try_into().unwrap_or_default();
self.set_output_size(PhysicalSize::new(width, height));
}
pub(crate) fn handle_pointer_enter(
&mut self,
serial: u32,
surface: &WlSurface,
surface_x: f64,
surface_y: f64,
) {
self.set_last_pointer_serial(serial);
self.set_current_pointer_position(surface_x, surface_y);
self.set_entered_surface(surface);
let position = self.current_pointer_position();
self.dispatch_to_active_window(WindowEvent::PointerMoved { position });
}
pub(crate) fn handle_pointer_motion(&mut self, surface_x: f64, surface_y: f64) {
self.set_current_pointer_position(surface_x, surface_y);
let position = self.current_pointer_position();
self.dispatch_to_active_window(WindowEvent::PointerMoved { position });
}
pub(crate) fn handle_pointer_leave(&mut self) {
self.dispatch_to_active_window(WindowEvent::PointerExited);
self.clear_entered_surface();
}
pub(crate) fn handle_pointer_button(
&mut self,
serial: u32,
button_state: WEnum<wl_pointer::ButtonState>,
) {
self.set_last_pointer_serial(serial);
let position = self.current_pointer_position();
let event = match button_state {
WEnum::Value(wl_pointer::ButtonState::Pressed) => WindowEvent::PointerPressed {
button: PointerEventButton::Left,
position,
},
_ => WindowEvent::PointerReleased {
button: PointerEventButton::Left,
position,
},
};
self.dispatch_to_active_window(event);
}
pub(crate) fn handle_axis_source(&mut self, axis_source: wl_pointer::AxisSource) {
self.set_axis_source(axis_source);
}
pub(crate) fn handle_axis(&mut self, _time: u32, axis: wl_pointer::Axis, value: f64) {
self.accumulate_axis(axis, value);
}
pub(crate) fn handle_axis_discrete(&mut self, axis: wl_pointer::Axis, discrete: i32) {
self.accumulate_axis_discrete(axis, discrete);
}
#[allow(clippy::unused_self)]
pub(crate) fn handle_axis_stop(&mut self, _time: u32, _axis: wl_pointer::Axis) {}
pub(crate) fn handle_pointer_frame(&mut self) {
let (delta_x, delta_y) = self.take_accumulated_axis();
if delta_x.abs() > f32::EPSILON || delta_y.abs() > f32::EPSILON {
let position = self.current_pointer_position();
self.dispatch_to_active_window(WindowEvent::PointerScrolled {
position,
delta_x,
delta_y,
});
}
}
pub(crate) fn handle_fractional_scale(&mut self, proxy: &WpFractionalScaleV1, scale: u32) {
use crate::wayland::surfaces::display_metrics::DisplayMetrics;
let scale_float = DisplayMetrics::scale_factor_from_120ths(scale);
info!("Fractional scale received: {scale_float} ({scale}x)");
self.update_scale_for_fractional_scale_object(proxy, scale);
}
pub(crate) fn handle_xdg_popup_configure(
&mut self,
xdg_popup: &XdgPopup,
x: i32,
y: i32,
width: i32,
height: i32,
) {
info!("XdgPopup Configure: position=({x}, {y}), size=({width}x{height})");
if let Some(popup_manager) = self.popup_manager() {
let popup_id = xdg_popup.id();
if let Some(handle) = popup_manager.find_by_xdg_popup(&popup_id) {
info!(
"Marking popup with handle {handle:?} as configured after XdgPopup::Configure"
);
popup_manager.mark_popup_configured(handle.key());
popup_manager.mark_all_popups_dirty();
}
}
}
pub(crate) fn handle_xdg_popup_done(&mut self, xdg_popup: &XdgPopup) {
info!("XdgPopup dismissed by compositor");
let popup_id = xdg_popup.id();
let popup_handle = self
.popup_manager()
.as_ref()
.and_then(|pm| pm.find_by_xdg_popup(&popup_id));
if let Some(handle) = popup_handle {
info!("Destroying popup with handle {handle:?}");
if let Some(popup_manager) = self.popup_manager() {
let _result = popup_manager.close(handle);
}
}
}
pub(crate) fn handle_xdg_surface_configure(&mut self, xdg_surface: &XdgSurface, serial: u32) {
info!("XdgSurface Configure received, sending ack with serial {serial}");
xdg_surface.ack_configure(serial);
if let Some(popup_manager) = self.popup_manager() {
info!("Marking all popups as dirty after Configure");
popup_manager.mark_all_popups_dirty();
}
}
pub(crate) fn handle_xdg_wm_base_ping(xdg_wm_base: &XdgWmBase, serial: u32) {
info!("XdgWmBase ping received, sending pong with serial {serial}");
xdg_wm_base.pong(serial);
}
}