From b12a51a0f1346bf5b021bd1bec2ed532b9cfe101 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Sat, 21 Dec 2024 22:46:01 +0700 Subject: [PATCH] Implements RuntimeWindow::on_mouse_input (#1196) --- .vscode/launch.json | 24 +----------------------- gui/src/rt/mod.rs | 11 +++++++++++ gui/src/rt/window.rs | 8 +++++++- gui/src/ui/backend/window.rs | 35 +++++++++++++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 83afac719..e6ddbdacc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,29 +1,7 @@ { "configurations": [ { - "name": "Qt", - "type": "lldb", - "request": "launch", - "args": [ - "--kernel", - "${workspaceFolder}/build/obkrnl" - ], - "cwd": "${workspaceFolder}", - "windows": { - "program": "${workspaceFolder}/build/gui/Obliteration.exe", - "env": { - "Path": "${env:Path};${env:CMAKE_PREFIX_PATH}\\bin" - } - }, - "linux": { - "program": "${workspaceFolder}/build/gui/obliteration" - }, - "osx": { - "program": "${workspaceFolder}/build/gui/obliteration.app/Contents/MacOS/obliteration" - } - }, - { - "name": "Slint", + "name": "GUI", "type": "lldb", "request": "launch", "preLaunchTask": "Build", diff --git a/gui/src/rt/mod.rs b/gui/src/rt/mod.rs index 176160ddc..a4727a70a 100644 --- a/gui/src/rt/mod.rs +++ b/gui/src/rt/mod.rs @@ -228,6 +228,14 @@ impl ApplicationHandler for Runtime { _ => return, } } + WindowEvent::MouseInput { + device_id: dev, + state: st, + button: btn, + } => match self.dispatch_window(el, id, move |w| w.on_mouse_input(dev, st, btn)) { + Some(Err(e)) => RuntimeError::MouseInput(e), + _ => return, + }, WindowEvent::ScaleFactorChanged { scale_factor: new, inner_size_writer: sw, @@ -283,6 +291,9 @@ pub enum RuntimeError { #[error("couldn't handle cursor left")] CursorLeft(#[source] Box), + #[error("couldn't handle mouse input")] + MouseInput(#[source] Box), + #[error("couldn't handle scale factor changed")] ScaleFactorChanged(#[source] Box), diff --git a/gui/src/rt/window.rs b/gui/src/rt/window.rs index 5eb8606d5..c25dd943c 100644 --- a/gui/src/rt/window.rs +++ b/gui/src/rt/window.rs @@ -1,6 +1,6 @@ use std::error::Error; use winit::dpi::{PhysicalPosition, PhysicalSize}; -use winit::event::{DeviceId, InnerSizeWriter}; +use winit::event::{DeviceId, ElementState, InnerSizeWriter, MouseButton}; /// Encapsulates winit window with window-specific logic. /// @@ -14,6 +14,12 @@ pub trait RuntimeWindow { pos: PhysicalPosition, ) -> Result<(), Box>; fn on_cursor_left(&self, dev: DeviceId) -> Result<(), Box>; + fn on_mouse_input( + &self, + dev: DeviceId, + st: ElementState, + btn: MouseButton, + ) -> Result<(), Box>; fn on_scale_factor_changed( &self, new: f64, diff --git a/gui/src/ui/backend/window.rs b/gui/src/ui/backend/window.rs index d3d55dcf5..ac82d0147 100644 --- a/gui/src/ui/backend/window.rs +++ b/gui/src/ui/backend/window.rs @@ -2,13 +2,13 @@ use crate::rt::RuntimeWindow; use i_slint_core::window::WindowAdapterInternal; use i_slint_core::InternalToken; use i_slint_renderer_skia::SkiaRenderer; -use slint::platform::{Renderer, WindowAdapter, WindowEvent, WindowProperties}; +use slint::platform::{PointerEventButton, Renderer, WindowAdapter, WindowEvent, WindowProperties}; use slint::{LogicalPosition, LogicalSize, PhysicalSize, PlatformError, WindowSize}; use std::any::Any; use std::cell::Cell; use std::error::Error; use std::rc::Rc; -use winit::event::{DeviceId, InnerSizeWriter}; +use winit::event::{DeviceId, ElementState, InnerSizeWriter, MouseButton}; use winit::window::WindowId; /// Implementation of [`WindowAdapter`]. @@ -17,6 +17,7 @@ pub struct Window { slint: slint::Window, renderer: SkiaRenderer, visible: Cell>, // Wayland does not support this so we need to emulate it. + pointer: Cell, } impl Window { @@ -30,6 +31,7 @@ impl Window { slint, renderer, visible: Cell::new(None), + pointer: Cell::default(), } } @@ -68,6 +70,7 @@ impl RuntimeWindow for Window { self.slint .dispatch_event(WindowEvent::PointerMoved { position }); + self.pointer.set(position); Ok(()) } @@ -77,6 +80,34 @@ impl RuntimeWindow for Window { Ok(()) } + fn on_mouse_input( + &self, + _: DeviceId, + st: ElementState, + btn: MouseButton, + ) -> Result<(), Box> { + // Map button. + let button = match btn { + MouseButton::Left => PointerEventButton::Left, + MouseButton::Right => PointerEventButton::Right, + MouseButton::Middle => PointerEventButton::Middle, + MouseButton::Back => PointerEventButton::Back, + MouseButton::Forward => PointerEventButton::Forward, + MouseButton::Other(_) => PointerEventButton::Other, + }; + + // Dispatch to Slint. + let position = self.pointer.get(); + let ev = match st { + ElementState::Pressed => WindowEvent::PointerPressed { position, button }, + ElementState::Released => WindowEvent::PointerReleased { position, button }, + }; + + self.slint.dispatch_event(ev); + + Ok(()) + } + fn on_scale_factor_changed( &self, new: f64,