Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/gain-plugin/src/editor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc};

use plinth_plugin::{raw_window_handle::RawWindowHandle, Editor, Host};
use plugin_canvas_slint::{editor::{EditorHandle, SlintEditor}, plugin_canvas::window::WindowAttributes};
use plugin_canvas_slint::{editor::{EditorHandle, SlintEditor}, plugin_canvas::{window::WindowAttributes}};

use crate::{parameters::GainParameters, view::GainPluginView};

Expand All @@ -12,7 +12,7 @@ pub struct EditorSettings {
impl Default for EditorSettings {
fn default() -> Self {
Self {
scale: 1.0,
scale: EditorHandle::default_scale(),
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions plugin-canvas-slint/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ pub struct EditorHandle {
}

impl EditorHandle {
pub fn default_scale() -> f64 {
// On macOS the system's window backend scaling gets applied in the OSWindow impl, so there's no need to scale the slint UIs too
#[cfg(target_os="macos")]
{
1.0
}
// On Windows and Linux the window backends do not use the system's DPI settings, so we scale the slint UIs to match the default screens scaling by default
#[cfg(any(target_os="windows", target_os="linux"))]
{
plugin_canvas::Window::os_screen_scale()
}
}

pub fn window(&self) -> Option<&plugin_canvas::Window> {
self.window_adapter()
.map(|window_adapter| window_adapter.plugin_canvas_window())
Expand Down
1 change: 1 addition & 0 deletions plugin-canvas/src/platform/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub(crate) trait OsWindowInterface: HasDisplayHandle + HasWindowHandle + Sized {
event_callback: Box<EventCallback>,
) -> Result<OsWindowHandle, Error>;

fn os_screen_scale() -> f64;
fn os_scale(&self) -> f64;

fn resized(&self, size: LogicalSize);
Expand Down
13 changes: 13 additions & 0 deletions plugin-canvas/src/platform/mac/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@ impl OsWindowInterface for OsWindow {
Ok(OsWindowHandle::new(window))
}

fn os_screen_scale() -> f64 {
if let Some(main_thread_marker) = MainThreadMarker::new() {
if let Some(screen) = NSScreen::mainScreen(main_thread_marker) {
return screen.backingScaleFactor()
}
}
else {
#[cfg(debug_assertions)]
panic!("Calling os_screen_scale from an unexpected thread");
}
1.0
}

fn os_scale(&self) -> f64 {
self.view()
.window()
Expand Down
31 changes: 10 additions & 21 deletions plugin-canvas/src/platform/win32/drop_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@ use std::ptr::null_mut;
use std::sync::Weak;

use windows::Win32::Foundation::{POINTL, POINT};
use windows::Win32::Graphics::Gdi::MapWindowPoints;
use windows::Win32::Graphics::Gdi::ScreenToClient;
use windows::Win32::System::Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYMED_HGLOBAL};
use windows::Win32::System::SystemServices::MODIFIERKEYS_FLAGS;
use windows::Win32::UI::Shell::{DragQueryFileW, HDROP};
use windows::core::implement;
use windows::Win32::System::Ole::{IDropTarget, IDropTarget_Impl, DROPEFFECT, CF_HDROP, DROPEFFECT_NONE, DROPEFFECT_COPY, DROPEFFECT_MOVE, DROPEFFECT_LINK};
use windows::Win32::UI::WindowsAndMessaging::HWND_DESKTOP;

use crate::event::EventResponse;
use crate::platform::interface::OsWindowInterface;
use crate::thread_bound::ThreadBound;
use crate::{LogicalPosition, PhysicalPosition};
use crate::LogicalPosition;
use crate::drag_drop::{DropData, DropOperation};
use super::window::OsWindow;

Expand Down Expand Up @@ -92,23 +90,14 @@ impl DropTarget {
}

fn convert_coordinates(&self, point: &POINTL) -> LogicalPosition {
let Some(window) = self.window.upgrade() else {
return LogicalPosition::default();
};

let scale = window.os_scale();

// It looks like MapWindowPoints isn't DPI aware (and neither is ScreenToClient),
// so we need to pre-scale the point here?
// TODO: Find out what's going on
let mut points = [POINT { x: (point.x as f64 / scale) as i32, y: (point.y as f64 / scale) as i32 }];

unsafe { MapWindowPoints(Some(HWND_DESKTOP), Some(window.hwnd()), &mut points); }

PhysicalPosition {
x: points[0].x,
y: points[0].y,
}.to_logical(1.0)
if let Some(window) = self.window.upgrade() {
let mut point = POINT { x: point.x, y: point.y };
if unsafe { ScreenToClient(window.hwnd(), &mut point).as_bool() } {
// see `OsWindow.os_scale`: we don't use DPI scaling on Windows
return LogicalPosition { x: point.x as f64, y: point.y as f64 };
}
}
LogicalPosition::default()
}
}

Expand Down
33 changes: 25 additions & 8 deletions plugin-canvas/src/platform/win32/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use cursor_icon::CursorIcon;
use keyboard_types::Code;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle, Win32WindowHandle};
use uuid::Uuid;
use windows::Win32::Graphics::Gdi::{GetDC, GetDeviceCaps, LOGPIXELSX, LOGPIXELSY, ReleaseDC};
use windows::Win32::UI::Input::KeyboardAndMouse::SetFocus;
use windows::Win32::UI::WindowsAndMessaging::{GetParent, WM_CANCELMODE, WM_SETFOCUS, WM_SETCURSOR};
use windows::{core::PCWSTR, Win32::UI::Input::KeyboardAndMouse::{VK_LWIN, VK_RWIN}};
Expand Down Expand Up @@ -36,6 +37,20 @@ pub struct OsWindow {
keyboard_modifiers: RefCell<KeyboardModifiers>,
}

fn window_scale(hwnd: Option<HWND>) -> f64 {
// Could use `GetDpiForWindow` here, but that's available for Windows 10 only
unsafe {
let hdc = GetDC(hwnd);
if !hdc.is_invalid() {
let dpi = GetDeviceCaps(Some(hdc), LOGPIXELSX).min(GetDeviceCaps(Some(hdc), LOGPIXELSY));
ReleaseDC(hwnd, hdc);
dpi.max(96) as f64 / 96.0
} else {
1.0
}
}
}

impl OsWindow {
pub(super) fn send_event(&self, event: Event) -> EventResponse {
(self.event_callback)(event)
Expand Down Expand Up @@ -75,12 +90,11 @@ impl OsWindow {
}

fn logical_mouse_position(&self, lparam: LPARAM) -> LogicalPosition {
let scale = self.os_scale();

// see `os_scale`: we don't use DPI scaling on Windows
PhysicalPosition {
x: (lparam.0 & 0xFFFF) as i16 as i32,
y: ((lparam.0 >> 16) & 0xFFFF) as i16 as i32,
}.to_logical(scale)
}.to_logical(1.0)
}

fn update_modifiers(&self) {
Expand Down Expand Up @@ -216,7 +230,13 @@ impl OsWindowInterface for OsWindow {
Ok(OsWindowHandle::new(window))
}

fn os_screen_scale() -> f64 {
window_scale(None)
}

fn os_scale(&self) -> f64 {
// os window DPI scaling is not used on Window: window sizes and positions are treated as logical positions,
// custom scaling is applied by scaling the slint window content, using `os_screen_scale` as default.
1.0
}

Expand Down Expand Up @@ -278,12 +298,9 @@ impl OsWindowInterface for OsWindow {
}

fn warp_mouse(&self, position: LogicalPosition) {
let scale = self.os_scale();
let physical_position = position.to_physical(scale);

let mut point = POINT {
x: physical_position.x,
y: physical_position.y,
x: position.x as i32,
y: position.y as i32,
};

unsafe {
Expand Down
11 changes: 11 additions & 0 deletions plugin-canvas/src/platform/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,18 @@ impl OsWindowInterface for OsWindow {
Ok(OsWindowHandle::new(Arc::new(window.into())))
}

fn os_screen_scale() -> f64 {
if let Ok((connection, screen_num)) = x11rb::connect(None) {
let screen = &connection.setup().roots[screen_num];
(screen.height_in_pixels as f64 * 25.4 / screen.height_in_millimeters as f64).max(96.0) / 96.0
} else {
1.0
}
}

fn os_scale(&self) -> f64 {
// os window DPI scaling is not used on Linux: window sizes and positions are treated as logical positions,
// custom scaling is applied by scaling the slint window content, using `os_screen_scale` as default.
1.0
}

Expand Down
10 changes: 7 additions & 3 deletions plugin-canvas/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,18 @@ impl Window {
})
}

pub fn attributes(&self) -> &WindowAttributes {
&self.attributes
pub fn os_screen_scale() -> f64 {
OsWindow::os_screen_scale()
}

pub fn os_scale(&self) -> f64 {
self.os_window_handle.os_scale()
}

pub fn attributes(&self) -> &WindowAttributes {
&self.attributes
}

pub fn resized(&self, size: LogicalSize) {
self.os_window_handle.resized(size);
}
Expand Down
Loading