Skip to content

Commit dd350f8

Browse files
authored
Merge pull request #19 from ilmai/mouse-event-scaling
Pre-scale mouse events in plugin-canvas
2 parents 63fe93c + 753907e commit dd350f8

8 files changed

Lines changed: 58 additions & 39 deletions

File tree

plugin-canvas-slint/src/window_adapter.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,9 @@ impl PluginCanvasWindowAdapter {
319319
}
320320

321321
fn convert_logical_position(&self, position: &plugin_canvas::LogicalPosition) -> slint::LogicalPosition {
322-
let scale = self.scale.load(Ordering::Acquire);
323-
324322
slint::LogicalPosition {
325-
x: (position.x / scale) as _,
326-
y: (position.y / scale) as _,
323+
x: position.x as _,
324+
y: position.y as _,
327325
}
328326
}
329327
}
@@ -357,7 +355,7 @@ impl WindowAdapter for PluginCanvasWindowAdapter {
357355
let logical_size = size.to_logical(os_scale as _);
358356

359357
*self.physical_size.borrow_mut() = physical_size;
360-
self.plugin_canvas_window.resized(LogicalSize::new(logical_size.width as _, logical_size.height as _));
358+
self.plugin_canvas_window.resized(LogicalSize::new(logical_size.width as _, logical_size.height as _), scale);
361359

362360
let mut logical_size = size.to_logical(os_scale as _);
363361
logical_size.width /= scale as f32;

plugin-canvas/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ license = "MIT"
1212
bitflags = "2"
1313
cursor-icon.workspace = true
1414
keyboard-types.workspace = true
15+
portable-atomic.workspace = true
1516
raw-window-handle.workspace = true
1617
uuid = { version = "1", features = ["fast-rng", "v4"] }
1718

plugin-canvas/src/platform/interface.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub(crate) trait OsWindowInterface: HasDisplayHandle + HasWindowHandle + Sized {
1414

1515
fn os_scale(&self) -> f64;
1616

17-
fn resized(&self, size: LogicalSize);
17+
fn resized(&self, size: LogicalSize, scale: f64);
1818

1919
fn set_cursor(&self, cursor: Option<CursorIcon>);
2020
fn set_input_focus(&self, focus: bool);

plugin-canvas/src/platform/mac/view.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use objc2::runtime::{Sel, ProtocolObject};
55
use objc2_app_kit::{NSDragOperation, NSDraggingInfo, NSEvent, NSEventModifierFlags, NSPasteboardTypeFileURL, NSView};
66
use objc2_foundation::{NSPoint, NSRect, NSTimer, NSURL};
77
use objc2_quartz_core::CADisplayLink;
8+
use portable_atomic::AtomicF64;
89
use uuid::Uuid;
910

1011
use crate::{drag_drop::{DropData, DropOperation}, event::EventResponse, keyboard::KeyboardModifiers, thread_bound::ThreadBound, Event, LogicalPosition, MouseButton};
@@ -19,6 +20,7 @@ struct Context {
1920
os_window_ptr: AtomicPtr<ThreadBound<OsWindow>>,
2021
input_focus: AtomicU8,
2122
keyboard_modifiers: RefCell<KeyboardModifiers>,
23+
scale: AtomicF64,
2224
}
2325

2426
unsafe impl Encode for Context {
@@ -28,6 +30,7 @@ unsafe impl Encode for Context {
2830
AtomicPtr::<c_void>::ENCODING,
2931
AtomicU8::ENCODING,
3032
AtomicUsize::ENCODING,
33+
f64::ENCODING,
3134
]
3235
);
3336
}
@@ -107,6 +110,10 @@ impl OsWindowView {
107110
})
108111
}
109112

113+
pub(crate) fn set_scale(&self, scale: f64) {
114+
self.with_context(|context| context.scale.store(scale, Ordering::Release));
115+
}
116+
110117
fn with_context<T>(&self, f: impl FnOnce(&Context) -> T) -> T {
111118
let ivar = self.class().instance_variable(c"_context").unwrap();
112119
let context: &Context = unsafe { ivar.load(self) };
@@ -131,7 +138,7 @@ impl OsWindowView {
131138

132139
fn key_event_text(&self, event: *const NSEvent) -> Option<String> {
133140
assert!(!event.is_null());
134-
141+
135142
unsafe {
136143
(*event)
137144
.characters()
@@ -163,7 +170,7 @@ impl OsWindowView {
163170
self.send_event(Event::KeyboardModifiers { modifiers: new_modifiers });
164171
});
165172
}
166-
173+
167174
fn handle_mouse_move_event(&self, event: *const NSEvent) {
168175
self.handle_modifier_event(event);
169176

@@ -220,10 +227,11 @@ impl OsWindowView {
220227

221228
fn window_point_to_position(&self, point_in_window: NSPoint) -> LogicalPosition {
222229
let local_position = self.convertPoint_fromView(point_in_window, None);
230+
let scale = self.with_context(|context| context.scale.load(Ordering::Acquire));
223231

224232
LogicalPosition {
225-
x: local_position.x,
226-
y: local_position.y,
233+
x: local_position.x / scale,
234+
y: local_position.y / scale,
227235
}
228236
}
229237

@@ -300,7 +308,7 @@ impl OsWindowView {
300308

301309
unsafe extern "C" fn key_down(&self, _cmd: Sel, event: *const NSEvent) {
302310
let code = unsafe { (*event).keyCode() };
303-
let text = self.key_event_text(event);
311+
let text = self.key_event_text(event);
304312

305313
self.send_event(
306314
Event::KeyDown {
@@ -316,7 +324,7 @@ impl OsWindowView {
316324

317325
unsafe extern "C" fn key_up(&self, _cmd: Sel, event: *const NSEvent) {
318326
let code = unsafe { (*event).keyCode() };
319-
let text = self.key_event_text(event);
327+
let text = self.key_event_text(event);
320328

321329
self.send_event(
322330
Event::KeyUp {

plugin-canvas/src/platform/mac/window.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ impl OsWindowInterface for OsWindow {
125125
}
126126

127127
view.set_os_window_ptr(Arc::downgrade(&window).into_raw() as _);
128+
view.set_scale(window_attributes.scale());
128129

129130
Ok(OsWindowHandle::new(window))
130131
}
@@ -136,13 +137,14 @@ impl OsWindowInterface for OsWindow {
136137
.unwrap_or(1.0)
137138
}
138139

139-
fn resized(&self, size: crate::LogicalSize) {
140+
fn resized(&self, size: crate::LogicalSize, scale: f64) {
140141
let cg_size = CGSize {
141142
width: size.width as _,
142143
height: size.height as _,
143144
};
144145

145146
self.view().setFrameSize(cg_size);
147+
self.view().set_scale(scale);
146148
}
147149

148150
fn set_cursor(&self, cursor: Option<CursorIcon>) {

plugin-canvas/src/platform/win32/window.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{cell::RefCell, ffi::OsString, mem::{size_of, transmute}, num::NonZeroI
55

66
use cursor_icon::CursorIcon;
77
use keyboard_types::Code;
8+
use portable_atomic::AtomicF64;
89
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle, Win32WindowHandle};
910
use uuid::Uuid;
1011
use windows::Win32::UI::Input::KeyboardAndMouse::SetFocus;
@@ -33,6 +34,7 @@ pub struct OsWindow {
3334

3435
running: Arc<AtomicBool>,
3536
moved: Arc<AtomicBool>,
37+
scale: AtomicF64,
3638

3739
keyboard_modifiers: RefCell<KeyboardModifiers>,
3840
}
@@ -76,7 +78,7 @@ impl OsWindow {
7678
}
7779

7880
fn logical_mouse_position(&self, lparam: LPARAM) -> LogicalPosition {
79-
let scale = self.os_scale();
81+
let scale = self.os_scale() * self.scale.load(Ordering::Acquire);
8082

8183
PhysicalPosition {
8284
x: (lparam.0 & 0xFFFF) as i16 as i32,
@@ -202,6 +204,7 @@ impl OsWindowInterface for OsWindow {
202204

203205
running,
204206
moved,
207+
scale: window_attributes.scale().into(),
205208

206209
keyboard_modifiers: Default::default(),
207210
};
@@ -226,8 +229,10 @@ impl OsWindowInterface for OsWindow {
226229
1.0
227230
}
228231

229-
fn resized(&self, size: LogicalSize) {
232+
fn resized(&self, size: LogicalSize, scale: f64) {
230233
unsafe { MoveWindow(self.hwnd(), 0, 0, size.width as _, size.height as _, true).unwrap(); }
234+
235+
self.scale.store(scale, Ordering::Release);
231236
}
232237

233238
fn set_cursor(&self, cursor: Option<CursorIcon>) {

plugin-canvas/src/platform/x11/window.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::{cell::RefCell, ffi::OsStr, num::NonZeroU32, ptr::NonNull, sync::atomic
33

44
use cursor_icon::CursorIcon;
55
use keyboard_types::Code;
6+
use portable_atomic::AtomicF64;
67
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle};
78
use x11rb::{COPY_DEPTH_FROM_PARENT, COPY_FROM_PARENT};
89
use x11rb::connection::Connection;
@@ -30,6 +31,7 @@ pub struct OsWindow {
3031
keyboard_modifiers: RefCell<KeyboardModifiers>,
3132

3233
showing_cursor: AtomicBool,
34+
scale: AtomicF64,
3335
}
3436

3537
impl OsWindow {
@@ -42,16 +44,13 @@ impl OsWindow {
4244
x11rb::protocol::Event::ButtonPress(event) => {
4345
self.update_modifiers_from_mask(event.state);
4446

45-
let position = LogicalPosition {
46-
x: event.event_x as _,
47-
y: event.event_y as _,
48-
};
47+
let position = self.convert_mouse_position(event.event_x, event.event_y);
4948

5049
if let Some(button) = Self::mouse_button_from_detail(event.detail) {
5150
self.send_event(Event::MouseButtonDown {
5251
button,
5352
position,
54-
});
53+
});
5554
} else if [4, 5].contains(&event.detail) {
5655
let delta_y = if event.detail == 4 {
5756
1.0
@@ -70,16 +69,13 @@ impl OsWindow {
7069
x11rb::protocol::Event::ButtonRelease(event) => {
7170
self.update_modifiers_from_mask(event.state);
7271

73-
let position = LogicalPosition {
74-
x: event.event_x as _,
75-
y: event.event_y as _,
76-
};
72+
let position = self.convert_mouse_position(event.event_x, event.event_y);
7773

7874
if let Some(button) = Self::mouse_button_from_detail(event.detail) {
7975
self.send_event(Event::MouseButtonUp {
8076
button,
8177
position,
82-
});
78+
});
8379
}
8480
}
8581

@@ -132,7 +128,7 @@ impl OsWindow {
132128

133129
let text = xkb_state.key_get_utf8(x11_keycode);
134130
xkb_state.update_key(x11_keycode, xkb::KeyDirection::Up);
135-
131+
136132
self.send_event(Event::KeyUp {
137133
key_code: keycode,
138134
text: Some(text),
@@ -146,14 +142,11 @@ impl OsWindow {
146142
x11rb::protocol::Event::MotionNotify(event) => {
147143
self.update_modifiers_from_mask(event.state);
148144

149-
let position = LogicalPosition {
150-
x: event.event_x as _,
151-
y: event.event_y as _,
152-
};
145+
let position = self.convert_mouse_position(event.event_x, event.event_y);
153146

154147
self.send_event(Event::MouseMoved { position });
155148
}
156-
149+
157150
_ => {},
158151
}
159152

@@ -169,6 +162,15 @@ impl OsWindow {
169162
}
170163
}
171164

165+
fn convert_mouse_position(&self, x: i16, y: i16) -> LogicalPosition {
166+
let scale = self.scale.load(Ordering::Acquire);
167+
168+
LogicalPosition {
169+
x: x as f64 / scale,
170+
y: y as f64 / scale,
171+
}
172+
}
173+
172174
fn update_modifiers_from_keycode(&self, keycode: Code, down: bool) {
173175
let mut modifiers = self.keyboard_modifiers.borrow_mut();
174176
let mut new_modifiers = *modifiers;
@@ -220,7 +222,7 @@ impl OsWindow {
220222
locales.push("C".into());
221223

222224
let mut xkb_compose_state = None;
223-
225+
224226
for locale in locales.iter() {
225227
if let Ok(compose_table) = xkb::compose::Table::new_from_locale(&xkb_context, OsStr::new(&locale), 0) {
226228
xkb_compose_state = Some(xkb::compose::State::new(&compose_table, 0));
@@ -265,11 +267,11 @@ impl OsWindowInterface for OsWindow {
265267
COPY_FROM_PARENT,
266268
&CreateWindowAux::new()
267269
.event_mask(
268-
EventMask::BUTTON_PRESS |
270+
EventMask::BUTTON_PRESS |
269271
EventMask::BUTTON_RELEASE |
270-
EventMask::KEY_PRESS |
271-
EventMask::KEY_RELEASE |
272-
EventMask::LEAVE_WINDOW |
272+
EventMask::KEY_PRESS |
273+
EventMask::KEY_RELEASE |
274+
EventMask::LEAVE_WINDOW |
273275
EventMask::POINTER_MOTION
274276
),
275277
)?;
@@ -298,6 +300,7 @@ impl OsWindowInterface for OsWindow {
298300
keyboard_modifiers: KeyboardModifiers::empty().into(),
299301

300302
showing_cursor: true.into(),
303+
scale: window_attributes.scale().into(),
301304
};
302305

303306
Ok(OsWindowHandle::new(Arc::new(window.into())))
@@ -307,13 +310,15 @@ impl OsWindowInterface for OsWindow {
307310
1.0
308311
}
309312

310-
fn resized(&self, size: crate::LogicalSize) {
313+
fn resized(&self, size: crate::LogicalSize, scale: f64) {
311314
self.connection.configure_window(
312315
self.window_handle.window.into(),
313316
&ConfigureWindowAux::new()
314317
.width(size.width as u32)
315318
.height(size.height as u32),
316319
).unwrap();
320+
321+
self.scale.store(scale, Ordering::Release);
317322
}
318323

319324
fn set_cursor(&self, cursor: Option<cursor_icon::CursorIcon>) {

plugin-canvas/src/window.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ impl Window {
7070
self.os_window_handle.os_scale()
7171
}
7272

73-
pub fn resized(&self, size: LogicalSize) {
74-
self.os_window_handle.resized(size);
73+
pub fn resized(&self, size: LogicalSize, scale: f64) {
74+
self.os_window_handle.resized(size, scale);
7575
}
7676

7777
/// This only needs to be called on Linux

0 commit comments

Comments
 (0)