diff --git a/plugin-canvas-slint/src/window_adapter.rs b/plugin-canvas-slint/src/window_adapter.rs index b301c74..50335f0 100644 --- a/plugin-canvas-slint/src/window_adapter.rs +++ b/plugin-canvas-slint/src/window_adapter.rs @@ -319,11 +319,9 @@ impl PluginCanvasWindowAdapter { } fn convert_logical_position(&self, position: &plugin_canvas::LogicalPosition) -> slint::LogicalPosition { - let scale = self.scale.load(Ordering::Acquire); - slint::LogicalPosition { - x: (position.x / scale) as _, - y: (position.y / scale) as _, + x: position.x as _, + y: position.y as _, } } } @@ -357,7 +355,7 @@ impl WindowAdapter for PluginCanvasWindowAdapter { let logical_size = size.to_logical(os_scale as _); *self.physical_size.borrow_mut() = physical_size; - self.plugin_canvas_window.resized(LogicalSize::new(logical_size.width as _, logical_size.height as _)); + self.plugin_canvas_window.resized(LogicalSize::new(logical_size.width as _, logical_size.height as _), scale); let mut logical_size = size.to_logical(os_scale as _); logical_size.width /= scale as f32; diff --git a/plugin-canvas/Cargo.toml b/plugin-canvas/Cargo.toml index 34795d0..40fba88 100644 --- a/plugin-canvas/Cargo.toml +++ b/plugin-canvas/Cargo.toml @@ -12,6 +12,7 @@ license = "MIT" bitflags = "2" cursor-icon.workspace = true keyboard-types.workspace = true +portable-atomic.workspace = true raw-window-handle.workspace = true uuid = { version = "1", features = ["fast-rng", "v4"] } diff --git a/plugin-canvas/src/platform/interface.rs b/plugin-canvas/src/platform/interface.rs index a240252..e80aafc 100644 --- a/plugin-canvas/src/platform/interface.rs +++ b/plugin-canvas/src/platform/interface.rs @@ -14,7 +14,7 @@ pub(crate) trait OsWindowInterface: HasDisplayHandle + HasWindowHandle + Sized { fn os_scale(&self) -> f64; - fn resized(&self, size: LogicalSize); + fn resized(&self, size: LogicalSize, scale: f64); fn set_cursor(&self, cursor: Option); fn set_input_focus(&self, focus: bool); diff --git a/plugin-canvas/src/platform/mac/view.rs b/plugin-canvas/src/platform/mac/view.rs index 9690754..e0dc084 100644 --- a/plugin-canvas/src/platform/mac/view.rs +++ b/plugin-canvas/src/platform/mac/view.rs @@ -5,6 +5,7 @@ use objc2::runtime::{Sel, ProtocolObject}; use objc2_app_kit::{NSDragOperation, NSDraggingInfo, NSEvent, NSEventModifierFlags, NSPasteboardTypeFileURL, NSView}; use objc2_foundation::{NSPoint, NSRect, NSTimer, NSURL}; use objc2_quartz_core::CADisplayLink; +use portable_atomic::AtomicF64; use uuid::Uuid; use crate::{drag_drop::{DropData, DropOperation}, event::EventResponse, keyboard::KeyboardModifiers, thread_bound::ThreadBound, Event, LogicalPosition, MouseButton}; @@ -19,6 +20,7 @@ struct Context { os_window_ptr: AtomicPtr>, input_focus: AtomicU8, keyboard_modifiers: RefCell, + scale: AtomicF64, } unsafe impl Encode for Context { @@ -28,6 +30,7 @@ unsafe impl Encode for Context { AtomicPtr::::ENCODING, AtomicU8::ENCODING, AtomicUsize::ENCODING, + f64::ENCODING, ] ); } @@ -107,6 +110,10 @@ impl OsWindowView { }) } + pub(crate) fn set_scale(&self, scale: f64) { + self.with_context(|context| context.scale.store(scale, Ordering::Release)); + } + fn with_context(&self, f: impl FnOnce(&Context) -> T) -> T { let ivar = self.class().instance_variable(c"_context").unwrap(); let context: &Context = unsafe { ivar.load(self) }; @@ -131,7 +138,7 @@ impl OsWindowView { fn key_event_text(&self, event: *const NSEvent) -> Option { assert!(!event.is_null()); - + unsafe { (*event) .characters() @@ -163,7 +170,7 @@ impl OsWindowView { self.send_event(Event::KeyboardModifiers { modifiers: new_modifiers }); }); } - + fn handle_mouse_move_event(&self, event: *const NSEvent) { self.handle_modifier_event(event); @@ -220,10 +227,11 @@ impl OsWindowView { fn window_point_to_position(&self, point_in_window: NSPoint) -> LogicalPosition { let local_position = self.convertPoint_fromView(point_in_window, None); + let scale = self.with_context(|context| context.scale.load(Ordering::Acquire)); LogicalPosition { - x: local_position.x, - y: local_position.y, + x: local_position.x / scale, + y: local_position.y / scale, } } @@ -300,7 +308,7 @@ impl OsWindowView { unsafe extern "C" fn key_down(&self, _cmd: Sel, event: *const NSEvent) { let code = unsafe { (*event).keyCode() }; - let text = self.key_event_text(event); + let text = self.key_event_text(event); self.send_event( Event::KeyDown { @@ -316,7 +324,7 @@ impl OsWindowView { unsafe extern "C" fn key_up(&self, _cmd: Sel, event: *const NSEvent) { let code = unsafe { (*event).keyCode() }; - let text = self.key_event_text(event); + let text = self.key_event_text(event); self.send_event( Event::KeyUp { diff --git a/plugin-canvas/src/platform/mac/window.rs b/plugin-canvas/src/platform/mac/window.rs index 713ce0f..137d54e 100644 --- a/plugin-canvas/src/platform/mac/window.rs +++ b/plugin-canvas/src/platform/mac/window.rs @@ -125,6 +125,7 @@ impl OsWindowInterface for OsWindow { } view.set_os_window_ptr(Arc::downgrade(&window).into_raw() as _); + view.set_scale(window_attributes.scale()); Ok(OsWindowHandle::new(window)) } @@ -136,13 +137,14 @@ impl OsWindowInterface for OsWindow { .unwrap_or(1.0) } - fn resized(&self, size: crate::LogicalSize) { + fn resized(&self, size: crate::LogicalSize, scale: f64) { let cg_size = CGSize { width: size.width as _, height: size.height as _, }; self.view().setFrameSize(cg_size); + self.view().set_scale(scale); } fn set_cursor(&self, cursor: Option) { diff --git a/plugin-canvas/src/platform/win32/window.rs b/plugin-canvas/src/platform/win32/window.rs index 1e145cd..fd45f5b 100644 --- a/plugin-canvas/src/platform/win32/window.rs +++ b/plugin-canvas/src/platform/win32/window.rs @@ -5,6 +5,7 @@ use std::{cell::RefCell, ffi::OsString, mem::{size_of, transmute}, num::NonZeroI use cursor_icon::CursorIcon; use keyboard_types::Code; +use portable_atomic::AtomicF64; use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle, Win32WindowHandle}; use uuid::Uuid; use windows::Win32::UI::Input::KeyboardAndMouse::SetFocus; @@ -33,6 +34,7 @@ pub struct OsWindow { running: Arc, moved: Arc, + scale: AtomicF64, keyboard_modifiers: RefCell, } @@ -76,7 +78,7 @@ impl OsWindow { } fn logical_mouse_position(&self, lparam: LPARAM) -> LogicalPosition { - let scale = self.os_scale(); + let scale = self.os_scale() * self.scale.load(Ordering::Acquire); PhysicalPosition { x: (lparam.0 & 0xFFFF) as i16 as i32, @@ -202,6 +204,7 @@ impl OsWindowInterface for OsWindow { running, moved, + scale: window_attributes.scale().into(), keyboard_modifiers: Default::default(), }; @@ -226,8 +229,10 @@ impl OsWindowInterface for OsWindow { 1.0 } - fn resized(&self, size: LogicalSize) { + fn resized(&self, size: LogicalSize, scale: f64) { unsafe { MoveWindow(self.hwnd(), 0, 0, size.width as _, size.height as _, true).unwrap(); } + + self.scale.store(scale, Ordering::Release); } fn set_cursor(&self, cursor: Option) { diff --git a/plugin-canvas/src/platform/x11/window.rs b/plugin-canvas/src/platform/x11/window.rs index d6b91f8..797a280 100644 --- a/plugin-canvas/src/platform/x11/window.rs +++ b/plugin-canvas/src/platform/x11/window.rs @@ -3,6 +3,7 @@ use std::{cell::RefCell, ffi::OsStr, num::NonZeroU32, ptr::NonNull, sync::atomic use cursor_icon::CursorIcon; use keyboard_types::Code; +use portable_atomic::AtomicF64; use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle}; use x11rb::{COPY_DEPTH_FROM_PARENT, COPY_FROM_PARENT}; use x11rb::connection::Connection; @@ -30,6 +31,7 @@ pub struct OsWindow { keyboard_modifiers: RefCell, showing_cursor: AtomicBool, + scale: AtomicF64, } impl OsWindow { @@ -42,16 +44,13 @@ impl OsWindow { x11rb::protocol::Event::ButtonPress(event) => { self.update_modifiers_from_mask(event.state); - let position = LogicalPosition { - x: event.event_x as _, - y: event.event_y as _, - }; + let position = self.convert_mouse_position(event.event_x, event.event_y); if let Some(button) = Self::mouse_button_from_detail(event.detail) { self.send_event(Event::MouseButtonDown { button, position, - }); + }); } else if [4, 5].contains(&event.detail) { let delta_y = if event.detail == 4 { 1.0 @@ -70,16 +69,13 @@ impl OsWindow { x11rb::protocol::Event::ButtonRelease(event) => { self.update_modifiers_from_mask(event.state); - let position = LogicalPosition { - x: event.event_x as _, - y: event.event_y as _, - }; + let position = self.convert_mouse_position(event.event_x, event.event_y); if let Some(button) = Self::mouse_button_from_detail(event.detail) { self.send_event(Event::MouseButtonUp { button, position, - }); + }); } } @@ -132,7 +128,7 @@ impl OsWindow { let text = xkb_state.key_get_utf8(x11_keycode); xkb_state.update_key(x11_keycode, xkb::KeyDirection::Up); - + self.send_event(Event::KeyUp { key_code: keycode, text: Some(text), @@ -146,14 +142,11 @@ impl OsWindow { x11rb::protocol::Event::MotionNotify(event) => { self.update_modifiers_from_mask(event.state); - let position = LogicalPosition { - x: event.event_x as _, - y: event.event_y as _, - }; + let position = self.convert_mouse_position(event.event_x, event.event_y); self.send_event(Event::MouseMoved { position }); } - + _ => {}, } @@ -169,6 +162,15 @@ impl OsWindow { } } + fn convert_mouse_position(&self, x: i16, y: i16) -> LogicalPosition { + let scale = self.scale.load(Ordering::Acquire); + + LogicalPosition { + x: x as f64 / scale, + y: y as f64 / scale, + } + } + fn update_modifiers_from_keycode(&self, keycode: Code, down: bool) { let mut modifiers = self.keyboard_modifiers.borrow_mut(); let mut new_modifiers = *modifiers; @@ -220,7 +222,7 @@ impl OsWindow { locales.push("C".into()); let mut xkb_compose_state = None; - + for locale in locales.iter() { if let Ok(compose_table) = xkb::compose::Table::new_from_locale(&xkb_context, OsStr::new(&locale), 0) { xkb_compose_state = Some(xkb::compose::State::new(&compose_table, 0)); @@ -265,11 +267,11 @@ impl OsWindowInterface for OsWindow { COPY_FROM_PARENT, &CreateWindowAux::new() .event_mask( - EventMask::BUTTON_PRESS | + EventMask::BUTTON_PRESS | EventMask::BUTTON_RELEASE | - EventMask::KEY_PRESS | - EventMask::KEY_RELEASE | - EventMask::LEAVE_WINDOW | + EventMask::KEY_PRESS | + EventMask::KEY_RELEASE | + EventMask::LEAVE_WINDOW | EventMask::POINTER_MOTION ), )?; @@ -298,6 +300,7 @@ impl OsWindowInterface for OsWindow { keyboard_modifiers: KeyboardModifiers::empty().into(), showing_cursor: true.into(), + scale: window_attributes.scale().into(), }; Ok(OsWindowHandle::new(Arc::new(window.into()))) @@ -307,13 +310,15 @@ impl OsWindowInterface for OsWindow { 1.0 } - fn resized(&self, size: crate::LogicalSize) { + fn resized(&self, size: crate::LogicalSize, scale: f64) { self.connection.configure_window( self.window_handle.window.into(), &ConfigureWindowAux::new() .width(size.width as u32) .height(size.height as u32), ).unwrap(); + + self.scale.store(scale, Ordering::Release); } fn set_cursor(&self, cursor: Option) { diff --git a/plugin-canvas/src/window.rs b/plugin-canvas/src/window.rs index 003078f..d2b136a 100644 --- a/plugin-canvas/src/window.rs +++ b/plugin-canvas/src/window.rs @@ -70,8 +70,8 @@ impl Window { self.os_window_handle.os_scale() } - pub fn resized(&self, size: LogicalSize) { - self.os_window_handle.resized(size); + pub fn resized(&self, size: LogicalSize, scale: f64) { + self.os_window_handle.resized(size, scale); } /// This only needs to be called on Linux