From 44a8d054b484af782a0e638d03ceb542888ae6ce Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Mon, 5 Oct 2026 18:48:31 +0200 Subject: [PATCH 1/7] Move dpi stuff to baseview-host --- Cargo.toml | 5 +- host/Cargo.toml | 17 +++ host/src/dpi.rs | 7 ++ host/src/dpi/native_size.rs | 108 +++++++++++++++++ host/src/dpi/window_size.rs | 64 ++++++++++ host/src/lib.rs | 1 + src/dpi.rs | 111 +----------------- src/lib.rs | 3 +- src/platform/macos/damage.rs | 2 +- src/platform/win/error.rs | 2 +- src/platform/win/mod.rs | 2 +- src/platform/x11/xcb_connection/size_hints.rs | 0 src/utils.rs | 3 +- src/window.rs | 63 +--------- src/wrappers/win32.rs | 2 +- src/wrappers/win32/rect.rs | 2 +- 16 files changed, 211 insertions(+), 181 deletions(-) create mode 100644 host/Cargo.toml create mode 100644 host/src/dpi.rs create mode 100644 host/src/dpi/native_size.rs create mode 100644 host/src/dpi/window_size.rs create mode 100644 host/src/lib.rs create mode 100644 src/platform/x11/xcb_connection/size_hints.rs diff --git a/Cargo.toml b/Cargo.toml index f67b2d96..f3aa6f04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ opengl = [ [dependencies] keyboard-types = { version = "0.8.3" } raw-window-handle = "0.6.2" -dpi = "0.1.2" +baseview-host = { path = "./host", version = "0.1.0" } tracing = { version = "0.1", optional = true } [target.'cfg(target_os="linux")'.dependencies] @@ -97,6 +97,7 @@ objc2-app-kit = { version = "0.3.2", default-features = false, features = [ [workspace] members = [ + "host", "examples/cursors", "examples/open_parented", "examples/open_window", @@ -108,7 +109,7 @@ members = [ "examples/timers", "examples/external-wakeup", "tests/partial-rendering" -] + , "host"] [lints.clippy] missing_safety_doc = "allow" diff --git a/host/Cargo.toml b/host/Cargo.toml new file mode 100644 index 00000000..641ab7a5 --- /dev/null +++ b/host/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "baseview-host" +version = "0.1.0" +authors = [ + "Adrien Prokopowicz " +] +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Interoperability library for plugin UIs" +keywords = ["windowing", "audio", "plugin"] +categories = ["gui"] +repository = "https://github.com/RustAudio/baseview" + +rust-version = "1.82" + +[dependencies] +dpi = "0.1.2" diff --git a/host/src/dpi.rs b/host/src/dpi.rs new file mode 100644 index 00000000..6d3ef5cf --- /dev/null +++ b/host/src/dpi.rs @@ -0,0 +1,7 @@ +pub use dpi::*; + +mod native_size; +mod window_size; + +pub use native_size::*; +pub use window_size::*; diff --git a/host/src/dpi/native_size.rs b/host/src/dpi/native_size.rs new file mode 100644 index 00000000..71783741 --- /dev/null +++ b/host/src/dpi/native_size.rs @@ -0,0 +1,108 @@ +use crate::dpi::*; + +/// A size represented in the platform's native pixels. +/// +/// This size is represented in physical pixels on Windows and Linux, and in logical pixels on macOS. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct NativeSize

{ + pub width: P, + pub height: P, +} + +#[cfg(target_os = "macos")] +const NATIVE_IS_LOGICAL: bool = true; +#[cfg(not(target_os = "macos"))] +const NATIVE_IS_LOGICAL: bool = false; + +impl

NativeSize

{ + #[inline] + pub const fn new(width: P, height: P) -> Self { + NativeSize { width, height } + } + + /// This is `true` if the platform's native size is represented in logical pixels, and `false` otherwise. + /// + /// This is `true` on macOS, and `false` on Windows and Linux. + pub const IS_LOGICAL: bool = NATIVE_IS_LOGICAL; +} + +impl NativeSize

{ + #[inline] + pub fn from_size(size: Size, scale_factor: f64) -> Self { + #[cfg(target_os = "macos")] + { + let size = size.to_logical(scale_factor); + Self { width: size.width, height: size.height } + } + + #[cfg(not(target_os = "macos"))] + { + let size = size.to_physical(scale_factor); + Self { width: size.width, height: size.height } + } + } + + #[inline] + pub fn cast(&self) -> NativeSize { + NativeSize { width: self.width.cast(), height: self.height.cast() } + } + + #[inline] + pub fn to_physical(self, scale_factor: f64) -> PhysicalSize

{ + #[cfg(target_os = "macos")] + { + let size = LogicalSize { width: self.width, height: self.height }; + size.to_physical(scale_factor) + } + #[cfg(not(target_os = "macos"))] + { + let _ = scale_factor; + PhysicalSize { width: self.width, height: self.height } + } + } + + #[inline] + pub fn to_logical(self, scale_factor: f64) -> LogicalSize

{ + #[cfg(target_os = "macos")] + { + let _ = scale_factor; + LogicalSize { width: self.width, height: self.height } + } + #[cfg(not(target_os = "macos"))] + { + let size = PhysicalSize { width: self.width, height: self.height }; + size.to_logical(scale_factor) + } + } +} + +impl From for NativeSize

{ + #[inline] + fn from(size: WindowSize) -> Self { + #[cfg(target_os = "macos")] + { + let size = size.logical.cast(); + Self { width: size.width, height: size.height } + } + + #[cfg(not(target_os = "macos"))] + { + let size = size.physical.cast(); + Self { width: size.width, height: size.height } + } + } +} + +impl From> for Size { + #[inline] + fn from(size: NativeSize

) -> Self { + #[cfg(target_os = "macos")] + { + Size::Logical(LogicalSize::new(size.width, size.height).cast()) + } + #[cfg(not(target_os = "macos"))] + { + Size::Physical(PhysicalSize::new(size.width, size.height).cast()) + } + } +} diff --git a/host/src/dpi/window_size.rs b/host/src/dpi/window_size.rs new file mode 100644 index 00000000..079ccec1 --- /dev/null +++ b/host/src/dpi/window_size.rs @@ -0,0 +1,64 @@ +use crate::dpi::*; + +/// A window's size, which can be read in either logical or physical pixels. +/// +/// Methods that produce this type in baseview guarantee that either the physical or the logical +/// size is directly from the underlying platform API. +/// +/// This means that for either of the size types, there is at most only one conversion performed, +/// which minimizes errors that may occur due to rounding. +#[derive(Debug, Copy, Clone)] +pub struct WindowSize { + /// The window's size in physical pixels. + pub physical: PhysicalSize, + /// The window's size in logical pixels. + pub logical: LogicalSize, + /// The backing scale factor of the window. + /// + /// This is the value used to convert between the physical and logical sizes. + pub scale_factor: f64, +} + +impl WindowSize { + /// Constructs a [`WindowSize`] from a given [`PhysicalSize`] and `scale_factor`. + /// + /// The [`LogicalSize`] is converted from the given physical size, using the given scale factor. + #[inline] + pub fn from_physical(physical: PhysicalSize, scale_factor: f64) -> Self { + Self { physical, logical: physical.to_logical(scale_factor), scale_factor } + } + + /// Constructs a [`WindowSize`] from a given [`LogicalSize`] and `scale_factor`. + /// + /// The [`PhysicalSize`] is converted from the given physical size, using the given scale factor. + #[inline] + pub fn from_logical(logical: LogicalSize, scale_factor: f64) -> Self { + Self { physical: logical.to_physical(scale_factor), logical, scale_factor } + } + + #[inline] + pub fn to_native_size(&self) -> NativeSize

{ + (*self).into() + } +} + +impl From for PhysicalSize

{ + #[inline] + fn from(size: WindowSize) -> Self { + size.physical.cast() + } +} + +impl From for LogicalSize

{ + #[inline] + fn from(size: WindowSize) -> Self { + size.logical.cast() + } +} + +impl From for Size { + #[inline] + fn from(value: WindowSize) -> Self { + value.to_native_size::().into() + } +} diff --git a/host/src/lib.rs b/host/src/lib.rs new file mode 100644 index 00000000..b39b3ed8 --- /dev/null +++ b/host/src/lib.rs @@ -0,0 +1 @@ +pub mod dpi; diff --git a/src/dpi.rs b/src/dpi.rs index 9d3e9e53..588d8715 100644 --- a/src/dpi.rs +++ b/src/dpi.rs @@ -1,109 +1,2 @@ -use crate::WindowSize; -pub use dpi::*; - -/// A size represented in the platform's native pixels. -/// -/// This size is represented in physical pixels on Windows and Linux, and in logical pixels on macOS. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct NativeSize

{ - pub width: P, - pub height: P, -} - -#[cfg(target_os = "macos")] -const NATIVE_IS_LOGICAL: bool = true; -#[cfg(not(target_os = "macos"))] -const NATIVE_IS_LOGICAL: bool = false; - -impl

NativeSize

{ - #[inline] - pub const fn new(width: P, height: P) -> Self { - NativeSize { width, height } - } - - /// This is `true` if the platform's native size is represented in logical pixels, and `false` otherwise. - /// - /// This is `true` on macOS, and `false` on Windows and Linux. - pub const IS_LOGICAL: bool = NATIVE_IS_LOGICAL; -} - -impl NativeSize

{ - #[inline] - pub fn from_size(size: Size, scale_factor: f64) -> Self { - #[cfg(target_os = "macos")] - { - let size = size.to_logical(scale_factor); - Self { width: size.width, height: size.height } - } - - #[cfg(not(target_os = "macos"))] - { - let size = size.to_physical(scale_factor); - Self { width: size.width, height: size.height } - } - } - - #[inline] - pub fn cast(&self) -> NativeSize { - NativeSize { width: self.width.cast(), height: self.height.cast() } - } - - #[inline] - pub fn to_physical(self, scale_factor: f64) -> PhysicalSize

{ - #[cfg(target_os = "macos")] - { - let size = LogicalSize { width: self.width, height: self.height }; - size.to_physical(scale_factor) - } - #[cfg(not(target_os = "macos"))] - { - let _ = scale_factor; - PhysicalSize { width: self.width, height: self.height } - } - } - - #[inline] - pub fn to_logical(self, scale_factor: f64) -> LogicalSize

{ - #[cfg(target_os = "macos")] - { - let _ = scale_factor; - LogicalSize { width: self.width, height: self.height } - } - #[cfg(not(target_os = "macos"))] - { - let size = PhysicalSize { width: self.width, height: self.height }; - size.to_logical(scale_factor) - } - } -} - -impl From for NativeSize

{ - #[inline] - fn from(size: WindowSize) -> Self { - #[cfg(target_os = "macos")] - { - let size = size.logical.cast(); - Self { width: size.width, height: size.height } - } - - #[cfg(not(target_os = "macos"))] - { - let size = size.physical.cast(); - Self { width: size.width, height: size.height } - } - } -} - -impl From> for Size { - #[inline] - fn from(size: NativeSize

) -> Self { - #[cfg(target_os = "macos")] - { - Size::Logical(LogicalSize::new(size.width, size.height).cast()) - } - #[cfg(not(target_os = "macos"))] - { - Size::Physical(PhysicalSize::new(size.width, size.height).cast()) - } - } -} +pub use baseview_host::dpi::WindowSize; +pub use baseview_host::dpi::*; diff --git a/src/lib.rs b/src/lib.rs index b43bbfca..f1097725 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ mod clipboard; mod context; mod damage; -pub mod dpi; mod error; mod event; mod handler; @@ -31,6 +30,8 @@ pub use timer::TimerHandle; pub use waker::WindowWaker; pub use window::*; +pub mod dpi; + #[allow(unused, reason = "Some platforms may not use all exports from this mod")] pub(crate) use tracing::*; diff --git a/src/platform/macos/damage.rs b/src/platform/macos/damage.rs index 1d0f1442..c244f350 100644 --- a/src/platform/macos/damage.rs +++ b/src/platform/macos/damage.rs @@ -1,4 +1,4 @@ -use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; +use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; use objc2_foundation::NSRect; #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/src/platform/win/error.rs b/src/platform/win/error.rs index 91742dd2..d2fecdca 100644 --- a/src/platform/win/error.rs +++ b/src/platform/win/error.rs @@ -1,5 +1,5 @@ +use crate::dpi::PhysicalSize; use crate::HandlerError; -use dpi::PhysicalSize; use std::fmt::Display; pub type Result = std::result::Result; diff --git a/src/platform/win/mod.rs b/src/platform/win/mod.rs index 6d38d505..312436dc 100644 --- a/src/platform/win/mod.rs +++ b/src/platform/win/mod.rs @@ -7,10 +7,10 @@ mod waker; mod window; mod window_state; +pub(crate) use crate::dpi::DpiScalingStrategy; use crate::wrappers::win32::h_instance::HInstance; use crate::wrappers::win32::window::HWnd; use crate::wrappers::win32::{Rect, TimerId}; -pub(crate) use dpi::DpiScalingStrategy; pub use error::{PlatformError, Result}; use raw_window_handle::{ DisplayHandle, HandleError, HasWindowHandle, RawWindowHandle, Win32WindowHandle, diff --git a/src/platform/x11/xcb_connection/size_hints.rs b/src/platform/x11/xcb_connection/size_hints.rs new file mode 100644 index 00000000..e69de29b diff --git a/src/utils.rs b/src/utils.rs index 934ad460..42cdc300 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,5 @@ -use crate::dpi::Size; +use crate::dpi::{LogicalSize, PhysicalSize, Size}; use crate::{WindowSettings, WindowSize}; -use dpi::{LogicalSize, PhysicalSize}; #[derive(Copy, Clone)] pub(crate) enum SizingStrategy { diff --git a/src/window.rs b/src/window.rs index 2708e7c2..ce10c2a7 100644 --- a/src/window.rs +++ b/src/window.rs @@ -246,65 +246,4 @@ pub(crate) struct WindowInitializer { pub host: Host, } -/// A window's size, which can be read in either logical or physical pixels. -/// -/// Methods that produce this type in baseview guarantee that either the physical or the logical -/// size is directly from the underlying platform API. -/// -/// This means that for either of the size types, there is at most only one conversion performed, -/// which minimizes errors that may occur due to rounding. -#[derive(Debug, Copy, Clone)] -pub struct WindowSize { - /// The window's size in physical pixels. - pub physical: PhysicalSize, - /// The window's size in logical pixels. - pub logical: LogicalSize, - /// The backing scale factor of the window. - /// - /// This is the value used to convert between the physical and logical sizes. - pub scale_factor: f64, -} - -impl WindowSize { - /// Constructs a [`WindowSize`] from a given [`PhysicalSize`] and `scale_factor`. - /// - /// The [`LogicalSize`] is converted from the given physical size, using the given scale factor. - #[inline] - pub fn from_physical(physical: PhysicalSize, scale_factor: f64) -> Self { - Self { physical, logical: physical.to_logical(scale_factor), scale_factor } - } - - /// Constructs a [`WindowSize`] from a given [`LogicalSize`] and `scale_factor`. - /// - /// The [`PhysicalSize`] is converted from the given physical size, using the given scale factor. - #[inline] - pub fn from_logical(logical: LogicalSize, scale_factor: f64) -> Self { - Self { physical: logical.to_physical(scale_factor), logical, scale_factor } - } - - #[inline] - pub fn to_native_size(&self) -> NativeSize

{ - (*self).into() - } -} - -impl From for PhysicalSize

{ - #[inline] - fn from(size: WindowSize) -> Self { - size.physical.cast() - } -} - -impl From for LogicalSize

{ - #[inline] - fn from(size: WindowSize) -> Self { - size.logical.cast() - } -} - -impl From for Size { - #[inline] - fn from(value: WindowSize) -> Self { - value.to_native_size::().into() - } -} +pub use baseview_host::dpi::WindowSize; diff --git a/src/wrappers/win32.rs b/src/wrappers/win32.rs index 80f15105..4e5b3d3c 100644 --- a/src/wrappers/win32.rs +++ b/src/wrappers/win32.rs @@ -10,7 +10,7 @@ mod user32; pub mod uuid; pub mod window; -pub use dpi::*; +pub use crate::dpi::*; pub use library::*; pub use rect::Rect; pub use shcore::*; diff --git a/src/wrappers/win32/rect.rs b/src/wrappers/win32/rect.rs index cf09c35f..4410577c 100644 --- a/src/wrappers/win32/rect.rs +++ b/src/wrappers/win32/rect.rs @@ -1,5 +1,5 @@ +use crate::dpi::PhysicalPosition; use crate::dpi::PhysicalSize; -use dpi::PhysicalPosition; use std::fmt::Debug; use windows_sys::Win32::Foundation::RECT; From 966e36f76b34f79a231bb83c203804692c5bbad2 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Mon, 5 Oct 2026 21:57:30 +0200 Subject: [PATCH 2/7] wip --- host/Cargo.toml | 1 + host/src/lib.rs | 1 + host/src/window.rs | 137 ++++++++++++++++++++++++++++++++++++++++ src/platform/x11/mod.rs | 2 +- src/settings.rs | 4 +- src/window.rs | 86 +++++++++++++++++++++++++ 6 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 host/src/window.rs diff --git a/host/Cargo.toml b/host/Cargo.toml index 641ab7a5..bd7afaef 100644 --- a/host/Cargo.toml +++ b/host/Cargo.toml @@ -15,3 +15,4 @@ rust-version = "1.82" [dependencies] dpi = "0.1.2" +raw-window-handle = "0.6.2" diff --git a/host/src/lib.rs b/host/src/lib.rs index b39b3ed8..a1430388 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -1 +1,2 @@ pub mod dpi; +pub mod window; diff --git a/host/src/window.rs b/host/src/window.rs new file mode 100644 index 00000000..b0ce820e --- /dev/null +++ b/host/src/window.rs @@ -0,0 +1,137 @@ +use crate::dpi::{NativeSize, WindowSize}; +use dpi::Size; +use raw_window_handle::HasWindowHandle; +use std::error::Error; + +/// A handle to a hostable Window. +/// +/// Unlike some other windowing libraries like `winit`, [`HostedWindow`]s manage their own +/// lifecycle. +/// +/// All of its events and internal operations (such as rendering) are handled in a separate +/// type, which is owned by the window itself. +/// +/// Dropping this [`HostedWindow`] handle will always destroy the window. +/// +/// # Window lifecycle and ownership +/// +/// Owning this [`HostedWindow`] does not mean you fully own the window itself, per se. +/// While you may have control over when the window is created, you do not have the sole control +/// over when it is destroyed. +/// +/// The lifetime of this [`HostedWindow`] handle is going to be the longest possible lifetime for the +/// underlying platform window, but it can be destroyed earlier than this. +/// +/// This is because while dropping this handle will always destroy the window, it can be destroyed +/// from other factors, such as: +/// +/// * The implementation decided to close the window itself, e.g. from the user clicking an internal "close" button; +/// * The implementation encountered a fatal error (e.g. during rendering) or panicked, and cannot operate anymore. +/// * The underlying platform closed or destroyed the window directly. +/// * The connection to the display server (on e.g. X11) was lost. +/// +/// This type makes enables to handle those cases safely: most methods will either return errors or +/// become no-ops. You can use the [`HostedWindow::is_open`] method to know if the window has been closed. +/// +pub trait HostedWindow { + /// Blocks the thread and runs an event loop until the window is closed. + /// + /// The window is shown automatically if it wasn't already. + fn run_until_closed(self) -> Result<(), Box> + where + Self: Sized; + + /// The current size of the window. + fn size(&self) -> WindowSize; + + /// Resizes the window to the given [`Size`]. + /// + /// The `size` can be provided in either physical or logical pixels. + /// + /// Using this method does *not* trigger the [`HostCallbacks::request_resize`](host::HostCallbacks) callback. + fn resize(&self, size: Size) -> Result<(), Box>; + + /// Suggests a fallback scale factor, if Baseview couldn't get one from the platform. + /// + /// If the platform does already provide an accurate scaling factor, this doesn't do anything. + /// + /// If the given fallback scale factor is actually useful and different from the current one + /// (1.0 by default), this will resize and redraw the window accordingly. + /// + /// # Platform compatibility notes. + /// + /// On Win32, this value is used if running on early versions of Windows 10 (or earlier). + /// + /// On X11, this value is used if no `Xft.dpi`setting is set. + /// + /// On macOS, this function is always a no-op. + fn suggest_fallback_scale_factor(&self, scale_factor: f64) -> Result<(), Box>; + + /// Closes and destroys the window. + /// + /// This releases all resources the window uses. + /// + /// It is guaranteed that no other objects (e.g. the parent window) are used by this window after + /// this call. + /// + /// Calling this method is more explicit, but otherwise identical to just dropping this [`Window`]. + fn close(self) + where + Self: Sized, + { + drop(self) + } + + /// Returns `true` if the window is still open, and returns `false` + /// if the window was closed/dropped. + fn is_open(&self) -> bool; + + /// Returns `true` if the window can be resized by the user, `false` otherwise. + /// + /// This is set by the [`WindowSettings::resizable`] field. + fn is_resizable(&self) -> bool; + + /// Returns the minimum size of the window, if it has one. + /// + /// This is set by the [`WindowSettings::min_size`] field. + fn min_size(&self) -> Option; + + /// Returns the minimum size of the window, if it has one. + /// + /// This is set by the [`WindowSettings::max_size`] field. + fn max_size(&self) -> Option; + + /// Performs the work the window thread had scheduled for the main thread. + /// + /// This must be called back on the main thread, as a response to [`HostMainThreadCaller::call_main_thread`](host::HostMainThreadCaller::call_main_thread). + /// + /// # Platform compatibility notes + /// + /// Only the X11 platform has a separate window thread, so this is only needed to run host callbacks on X11. + /// + /// On Windows and macOS, this is always a no-op. + fn host_main_thread_callback(&self); + + /// Reparents this window using the given `parent`. + /// + /// # Panics + /// + /// This function can panic if the window did not have a parent, but was already created as a floating window. + /// + /// It can also panic if the given `parent` is invalid for the current platform. + fn set_parent(&self, parent: &dyn HasWindowHandle) -> Result<(), Box>; + + /// Shows the window to the screen. + fn show(&self) -> Result<(), Box>; + + /// Hides the window from the screen. + /// + /// The window will still exist, and it might still receive some events, but rendering will be + /// paused and the user will not be able to see or interact with it. + fn hide(&self) -> Result<(), Box>; + + /// Adjusts the given size to the window's size constraints. + fn adjust_size(&self, size: NativeSize) -> NativeSize; + + fn request_poll(&self) -> Result<(), Box>; +} diff --git a/src/platform/x11/mod.rs b/src/platform/x11/mod.rs index edeea9d7..b54f9785 100644 --- a/src/platform/x11/mod.rs +++ b/src/platform/x11/mod.rs @@ -100,7 +100,7 @@ pub struct ParentWindowHandle { impl ParentWindowHandle { pub fn extract( - window: &impl HasWindowHandle, + window: &(impl HasWindowHandle + ?Sized), ) -> core::result::Result { let window_id = match window.window_handle()?.as_raw() { RawWindowHandle::Xlib(h) => { diff --git a/src/settings.rs b/src/settings.rs index 491f5ae3..f3cc635e 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -170,7 +170,7 @@ const _: () = { impl ParentWindowHandle { /// Grabs a handle to the given `parent_window`, to later create a child window in it. - pub fn from_window(parent_window: &impl HasWindowHandle) -> Self { + pub fn from_window(parent_window: &(impl HasWindowHandle + ?Sized)) -> Self { let inner = match platform::ParentWindowHandle::extract(parent_window) { Ok(parent) => parent, Err(e) => { @@ -182,7 +182,7 @@ impl ParentWindowHandle { } } -impl From<&W> for ParentWindowHandle { +impl From<&W> for ParentWindowHandle { fn from(window: &W) -> Self { Self::from_window(window) } diff --git a/src/window.rs b/src/window.rs index ce10c2a7..97b0a5bf 100644 --- a/src/window.rs +++ b/src/window.rs @@ -4,6 +4,7 @@ use crate::host::Host; use crate::platform; use crate::waker::WindowWaker; use crate::*; +use raw_window_handle::HasWindowHandle; use std::marker::PhantomData; /// A handle to a Window created by baseview. @@ -247,3 +248,88 @@ pub(crate) struct WindowInitializer { } pub use baseview_host::dpi::WindowSize; +use baseview_host::window::HostedWindow; + +impl HostedWindow for Window { + #[inline] + fn run_until_closed(self) -> Result<(), Box> + where + Self: Sized, + { + self.run_until_closed()?; + Ok(()) + } + + #[inline] + fn size(&self) -> WindowSize { + self.size() + } + + #[inline] + fn resize(&self, size: Size) -> Result<(), Box> { + self.resize(size)?; + Ok(()) + } + + #[inline] + fn suggest_fallback_scale_factor( + &self, scale_factor: f64, + ) -> Result<(), Box> { + self.suggest_fallback_scale_factor(scale_factor)?; + Ok(()) + } + + #[inline] + fn is_open(&self) -> bool { + self.is_open() + } + + #[inline] + fn is_resizable(&self) -> bool { + self.is_resizable() + } + + #[inline] + fn min_size(&self) -> Option { + self.min_size() + } + + #[inline] + fn max_size(&self) -> Option { + self.max_size() + } + + #[inline] + fn host_main_thread_callback(&self) { + self.host_main_thread_callback() + } + + #[inline] + fn set_parent(&self, parent: &dyn HasWindowHandle) -> Result<(), Box> { + self.set_parent(parent)?; + Ok(()) + } + + #[inline] + fn show(&self) -> Result<(), Box> { + self.show()?; + Ok(()) + } + + #[inline] + fn hide(&self) -> Result<(), Box> { + self.hide()?; + Ok(()) + } + + #[inline] + fn adjust_size(&self, size: NativeSize) -> NativeSize { + self.adjust_size(size) + } + + #[inline] + fn request_poll(&self) -> Result<(), Box> { + self.request_poll()?; + Ok(()) + } +} From 1a59db854d65aec3247b536ad2887e995f85c820 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Mon, 5 Oct 2026 23:26:32 +0200 Subject: [PATCH 3/7] Move host stuff --- examples/plugin_clack/src/gui.rs | 3 ++- examples/plugin_clack_femtovg/src/gui.rs | 3 ++- {src => host/src}/host.rs | 30 ++++++++++-------------- host/src/lib.rs | 1 + src/lib.rs | 4 +++- src/platform/x11/window_thread.rs | 6 ++--- 6 files changed, 24 insertions(+), 23 deletions(-) rename {src => host/src}/host.rs (79%) diff --git a/examples/plugin_clack/src/gui.rs b/examples/plugin_clack/src/gui.rs index 215195b1..1c179568 100644 --- a/examples/plugin_clack/src/gui.rs +++ b/examples/plugin_clack/src/gui.rs @@ -9,6 +9,7 @@ use clack_extensions::gui::{ }; use clack_plugin::plugin::PluginError; use clack_plugin::prelude::{HostMainThreadHandle, HostSharedHandle}; +use std::error::Error; pub struct ExamplePluginGui { pub handle: Window, @@ -168,7 +169,7 @@ struct HostGuiCallbacks { } impl HostCallbacks for HostGuiCallbacks { - fn request_resize(&mut self, new_size: WindowSize) -> Result<(), HandlerError> { + fn request_resize(&mut self, new_size: WindowSize) -> Result<(), Box> { let new_size = new_size.to_native_size(); self.ext.request_resize(&self.host, new_size.width, new_size.height)?; Ok(()) diff --git a/examples/plugin_clack_femtovg/src/gui.rs b/examples/plugin_clack_femtovg/src/gui.rs index 41ab05a1..77aeae64 100644 --- a/examples/plugin_clack_femtovg/src/gui.rs +++ b/examples/plugin_clack_femtovg/src/gui.rs @@ -10,6 +10,7 @@ use clack_extensions::gui::{ }; use clack_plugin::plugin::PluginError; use clack_plugin::prelude::{HostMainThreadHandle, HostSharedHandle}; +use std::error::Error; pub struct ExamplePluginGui { pub handle: Window, @@ -168,7 +169,7 @@ struct HostGuiCallbacks { } impl HostCallbacks for HostGuiCallbacks { - fn request_resize(&mut self, new_size: WindowSize) -> Result<(), HandlerError> { + fn request_resize(&mut self, new_size: WindowSize) -> Result<(), Box> { let new_size = new_size.to_native_size(); self.ext.request_resize(&self.host, new_size.width, new_size.height)?; Ok(()) diff --git a/src/host.rs b/host/src/host.rs similarity index 79% rename from src/host.rs rename to host/src/host.rs index 6c0ee03d..49b1f2a2 100644 --- a/src/host.rs +++ b/host/src/host.rs @@ -1,5 +1,5 @@ -use crate::{HandlerError, WindowSize}; -use std::cell::RefCell; +use crate::dpi::WindowSize; +use std::error::Error; /// A special handler for the Window thread to wake up and call methods on the main thread. /// @@ -35,7 +35,7 @@ pub trait HostCallbacks: 'static { /// This can return any type of error, indicating the host either failed or denied to handle the /// resize request. /// If it does, the error is logged and the resize operation is canceled or reverted. - fn request_resize(&mut self, new_size: WindowSize) -> Result<(), HandlerError>; + fn request_resize(&mut self, new_size: WindowSize) -> Result<(), Box>; /// Notifies the host that the child window has been destroyed for a reason outside the host's /// control. /// @@ -59,9 +59,9 @@ pub trait HostCallbacks: 'static { /// (or after this [`Host`] object is dropped, if it never made it to a /// [`Window::create_with_host`](crate::Window::create_with_host) call). pub struct Host { + callbacks: Option>, #[cfg(target_os = "linux")] - pub(crate) main_thread: Option>, - pub(crate) callbacks: Option>>, + main_thread: Option>, } impl Default for Host { @@ -90,7 +90,7 @@ impl Host { /// /// # Platform Compatibility notes /// - /// This is only useful on X11. On Window and macOS, this is a no-op. + /// This is only useful on X11. On Windows and macOS, this is a no-op. #[inline] pub fn with_main_thread(self, main_thread: impl HostMainThreadCaller) -> Self { #[cfg(target_os = "linux")] @@ -111,21 +111,17 @@ impl Host { /// If another callback handler was already set, it is replaced. #[inline] pub fn with_callbacks(mut self, callbacks: impl HostCallbacks) -> Self { - self.callbacks = Some(RefCell::new(Box::new(callbacks))); + self.callbacks = Some(Box::new(callbacks)); self } - #[cfg(any(target_os = "macos", target_os = "windows"))] - pub(crate) fn notify_destroyed(&self) { - let Some(callbacks) = &self.callbacks else { return }; - let Ok(mut callbacks) = callbacks.try_borrow_mut() else { return }; - callbacks.destroyed(); + #[inline] + pub fn take_callbacks(&mut self) -> Option> { + self.callbacks.take() } - #[cfg(any(target_os = "macos", target_os = "windows"))] - pub(crate) fn request_resize(&self, new_size: WindowSize) -> Result<(), HandlerError> { - let Some(callbacks) = &self.callbacks else { return Ok(()) }; - let Ok(mut callbacks) = callbacks.try_borrow_mut() else { return Ok(()) }; - callbacks.request_resize(new_size) + #[inline] + pub fn take_main_thread(&mut self) -> Option> { + self.main_thread.take() } } diff --git a/host/src/lib.rs b/host/src/lib.rs index a1430388..c325d0a8 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -1,2 +1,3 @@ pub mod dpi; +pub mod host; pub mod window; diff --git a/src/lib.rs b/src/lib.rs index f1097725..0a8f69f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,9 @@ mod damage; mod error; mod event; mod handler; -pub mod host; +pub mod host { + pub use baseview_host::host::*; +} mod keyboard; mod mouse_cursor; mod settings; diff --git a/src/platform/x11/window_thread.rs b/src/platform/x11/window_thread.rs index a5e6e545..48f7b823 100644 --- a/src/platform/x11/window_thread.rs +++ b/src/platform/x11/window_thread.rs @@ -113,13 +113,13 @@ pub struct WindowThreadHandle { } impl WindowThreadHandle { - pub fn create_window(init: WindowInitializer) -> PlatformResult { + pub fn create_window(mut init: WindowInitializer) -> PlatformResult { let (tx, rx) = result_channel(); let shared = Arc::new(WindowThreadShared::new()); let (request_sender, request_receiver) = calloop::channel::sync_channel(1); let (response_sender, response_receiver) = mpsc::channel(); let (main_thread_caller, main_thread_receiver) = - MainThreadCaller::new(init.host.main_thread); + MainThreadCaller::new(init.host.take_main_thread()); let join_handle = { let shared = Arc::clone(&shared); @@ -155,7 +155,7 @@ impl WindowThreadHandle { loop_signal, request_sender, response_receiver, - host_callbacks: init.host.callbacks.map(|c| c.into_inner().into()), + host_callbacks: init.host.take_callbacks().map(|c| c.into()), callback_receiver: main_thread_receiver, }) } From 198a4a376682a59f7c3d66ea34f462478710617c Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:45:56 +0200 Subject: [PATCH 4/7] fixes --- host/src/host.rs | 9 ++++++++- src/platform/macos/mod.rs | 2 +- src/platform/macos/view.rs | 25 +++++++++++++++++++------ src/platform/win/mod.rs | 4 ++-- src/platform/win/window.rs | 29 ++++++++++++++++++----------- src/wrappers/win32.rs | 2 +- src/wrappers/win32/dpi.rs | 2 +- 7 files changed, 50 insertions(+), 23 deletions(-) diff --git a/host/src/host.rs b/host/src/host.rs index 49b1f2a2..1f60db29 100644 --- a/host/src/host.rs +++ b/host/src/host.rs @@ -122,6 +122,13 @@ impl Host { #[inline] pub fn take_main_thread(&mut self) -> Option> { - self.main_thread.take() + #[cfg(target_os = "linux")] + { + self.main_thread.take() + } + #[cfg(not(target_os = "linux"))] + { + None + } } } diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index 6f20e192..64a5db0f 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -83,7 +83,7 @@ pub struct ParentWindowHandle { impl ParentWindowHandle { pub fn extract( - window: &impl HasWindowHandle, + window: &(impl HasWindowHandle + ?Sized), ) -> core::result::Result { let view = extract_raw_window_handle(window.window_handle()?)?; diff --git a/src/platform/macos/view.rs b/src/platform/macos/view.rs index 07cd39c6..1efa142b 100644 --- a/src/platform/macos/view.rs +++ b/src/platform/macos/view.rs @@ -3,7 +3,6 @@ use super::keyboard::{make_modifiers, KeyboardState}; use super::window::WindowSharedState; use crate::dpi::{LogicalPosition, LogicalSize}; -use crate::host::Host; use crate::platform::macos::cursor::CursorManager; use crate::platform::macos::timer::TimerManager; use crate::platform::*; @@ -16,6 +15,7 @@ use crate::{ DamageArea, DropData, DropEffect, Event, EventStatus, HandlerError, MouseButton, MouseEvent, ScrollDelta, WindowEvent, WindowHandler, WindowSize, }; +use baseview_host::host::HostCallbacks; use objc2::__framework_prelude::Retained; use objc2::rc::Weak; use objc2::runtime::{NSObjectProtocol, ProtocolObject}; @@ -78,7 +78,7 @@ pub(crate) struct BaseviewView { display_link: OnceCell>, display_link_started: Cell, - host: Host, + host: Option>>, pub(crate) cursor_manager: CursorManager, timers: TimerManager, @@ -89,7 +89,7 @@ pub(crate) struct BaseviewView { impl BaseviewView { pub fn new( - init: WindowInitializer, parenting: ViewParentingType, final_size: LogicalSize, + mut init: WindowInitializer, parenting: ViewParentingType, final_size: LogicalSize, mtm: MainThreadMarker, ) -> Result<(Retained>, Rc)> { let view_rect = @@ -111,7 +111,7 @@ impl BaseviewView { window_handler: WindowHandlerContainer::new(), notification_center_observer: None.into(), parenting: ViewParentingType::Uninitialized.into(), - host: init.host, + host: init.host.take_callbacks().map(|c| c.into()), lifetime_tied_to_app: None.into(), cursor_manager: CursorManager::new(), @@ -226,7 +226,7 @@ impl BaseviewView { } if !from_host { - this.host.notify_destroyed(); + this.host_notify_destroyed(); } } @@ -326,6 +326,19 @@ impl BaseviewView { window.setContentMaxSize(NSSize::new(max_size.width, max_size.height)); } } + + fn host_notify_destroyed(&self) { + let Some(host) = &self.host else { return }; + let Ok(mut host) = host.try_borrow_mut() else { return }; + host.destroyed(); + } + + fn host_request_resize(&self, new_size: WindowSize) -> core::result::Result<(), HandlerError> { + let Some(host) = &self.host else { return Ok(()) }; + let Ok(mut host) = host.try_borrow_mut() else { return Ok(()) }; + host.request_resize(new_size).map_err(HandlerError::from_boxed)?; + Ok(()) + } } impl Drop for BaseviewView { @@ -396,7 +409,7 @@ impl ViewImpl for BaseviewView { } if notify_host { - if let Err(e) = this.host.request_resize(new_size) { + if let Err(e) = this.host_request_resize(new_size) { warn!("Host failed to resize parent view: {}", e); Self::resize(this, previous, false, false); diff --git a/src/platform/win/mod.rs b/src/platform/win/mod.rs index 312436dc..4263984f 100644 --- a/src/platform/win/mod.rs +++ b/src/platform/win/mod.rs @@ -7,10 +7,10 @@ mod waker; mod window; mod window_state; -pub(crate) use crate::dpi::DpiScalingStrategy; use crate::wrappers::win32::h_instance::HInstance; use crate::wrappers::win32::window::HWnd; use crate::wrappers::win32::{Rect, TimerId}; +pub(crate) use dpi::DpiScalingStrategy; pub use error::{PlatformError, Result}; use raw_window_handle::{ DisplayHandle, HandleError, HasWindowHandle, RawWindowHandle, Win32WindowHandle, @@ -69,7 +69,7 @@ unsafe impl Sync for ParentWindowHandle {} impl ParentWindowHandle { pub fn extract( - parent: &impl HasWindowHandle, + parent: &(impl HasWindowHandle + ?Sized), ) -> core::result::Result { let parent = match parent.window_handle()?.as_raw() { RawWindowHandle::Win32(h) => h.hwnd, diff --git a/src/platform/win/window.rs b/src/platform/win/window.rs index 99353128..da4c8719 100644 --- a/src/platform/win/window.rs +++ b/src/platform/win/window.rs @@ -4,14 +4,9 @@ use windows_sys::Win32::{ UI::{Controls::WM_MOUSELEAVE, WindowsAndMessaging::*}, }; -use crate::dpi::{PhysicalPosition, PhysicalSize, Size}; -use crate::{warn, DamageArea, EventStatus, HandlerError, WindowHandler}; -use std::cell::{Cell, OnceCell}; -use std::num::NonZeroU32; -use windows_sys::Win32::Foundation::POINT; - use super::drop_target::DropTarget; use super::*; +use crate::dpi::{PhysicalPosition, PhysicalSize, Size}; use crate::handler::WindowHandlerBuilder; use crate::host::Host; use crate::platform::win::window_state::{WindowSharedState, WindowState}; @@ -24,7 +19,12 @@ use crate::wrappers::win32::{ ole_initialize, run_thread_message_loop_until, Dpi, DpiAwarenessGuard, LibraryModule, Rect, TimerId, WindowStyle, }; +use crate::{warn, DamageArea, EventStatus, HandlerError, WindowHandler}; use crate::{Event, MouseButton, MouseEvent, ScrollDelta, WindowEvent, WindowSize}; +use baseview_host::host::HostCallbacks; +use std::cell::{Cell, OnceCell, RefCell}; +use std::num::NonZeroU32; +use windows_sys::Win32::Foundation::POINT; fn hi_word(wparam: WPARAM) -> u16 { ((wparam >> 16) & 0xffff) as u16 @@ -233,7 +233,7 @@ pub struct BaseviewWindow { handler_builder: Cell>, handler: OnceCell>, - host: Host, + host: Option>>, // Workaround some VST3 hosts (e.g. Bitwig) not allowing request_resize before show() occurs pub host_needs_new_size_notified_on_show: Cell>>, @@ -247,7 +247,9 @@ pub struct BaseviewWindow { } impl BaseviewWindow { - pub fn create(shared_state: Rc, init: WindowInitializer) -> Result { + pub fn create( + shared_state: Rc, mut init: WindowInitializer, + ) -> Result { shared_state.init(&init); let style = WindowStyle::from_settings(&init.settings); @@ -276,7 +278,7 @@ impl BaseviewWindow { handler_builder: Cell::new(Some(init.builder)), handler: OnceCell::new(), shared_state, - host: init.host, + host: init.host.take_callbacks().map(|cb| cb.into()), host_needs_new_size_notified_on_show: None.into(), _drop_target: None.into(), @@ -300,7 +302,9 @@ impl BaseviewWindow { return; }; - self.host.notify_destroyed() + let Some(host) = &self.host else { return }; + let Ok(mut host) = host.try_borrow_mut() else { return }; + host.destroyed(); } fn request_host_resize(&self, new_size: WindowSize) -> core::result::Result<(), HandlerError> { @@ -308,7 +312,10 @@ impl BaseviewWindow { return Ok(()); }; - self.host.request_resize(new_size) + let Some(host) = &self.host else { return Ok(()) }; + let Ok(mut host) = host.try_borrow_mut() else { return Ok(()) }; + host.request_resize(new_size).map_err(HandlerError::from_boxed)?; + Ok(()) } fn adapt_host_window_to_size( diff --git a/src/wrappers/win32.rs b/src/wrappers/win32.rs index 4e5b3d3c..80f15105 100644 --- a/src/wrappers/win32.rs +++ b/src/wrappers/win32.rs @@ -10,7 +10,7 @@ mod user32; pub mod uuid; pub mod window; -pub use crate::dpi::*; +pub use dpi::*; pub use library::*; pub use rect::Rect; pub use shcore::*; diff --git a/src/wrappers/win32/dpi.rs b/src/wrappers/win32/dpi.rs index 079974d3..33b9a90e 100644 --- a/src/wrappers/win32/dpi.rs +++ b/src/wrappers/win32/dpi.rs @@ -1,7 +1,6 @@ use super::*; use crate::platform::DpiScalingStrategy; use crate::wrappers::win32::user32::ExtendedUser32; -use crate::wrappers::win32::DpiAwarenessContextType::*; use std::ffi::c_void; use std::fmt::{Debug, Formatter}; use std::num::NonZeroU32; @@ -11,6 +10,7 @@ use windows_sys::Win32::Foundation::{FALSE, RECT, TRUE}; use windows_sys::Win32::Graphics::Gdi::{GetDC, GetDeviceCaps, ReleaseDC, LOGPIXELSX}; use windows_sys::Win32::UI::HiDpi::*; use windows_sys::Win32::UI::WindowsAndMessaging::{AdjustWindowRectEx, USER_DEFAULT_SCREEN_DPI}; +use DpiAwarenessContextType::*; #[derive(Copy, Clone, Eq, PartialEq)] pub struct Dpi(pub NonZeroU32); From 39dc10ae9ef7d2a3f699eb86d4ffbbae0a390f37 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Tue, 6 Oct 2026 09:05:47 +0200 Subject: [PATCH 5/7] fixes --- host/src/host.rs | 12 ++++-------- host/src/lib.rs | 4 +++- host/src/window.rs | 2 +- src/platform/win/window.rs | 1 - src/window.rs | 2 +- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/host/src/host.rs b/host/src/host.rs index 1f60db29..97a7f1a8 100644 --- a/host/src/host.rs +++ b/host/src/host.rs @@ -3,7 +3,7 @@ use std::error::Error; /// A special handler for the Window thread to wake up and call methods on the main thread. /// -/// [`WindowHandle::host_main_thread_callback`](crate::Window::host_main_thread_callback) +/// [`HostedWindow::host_main_thread_callback`](crate::HostedWindow::host_main_thread_callback) /// should be called as a response to this. /// /// # Platform compatibility notes @@ -12,7 +12,7 @@ use std::error::Error; pub trait HostMainThreadCaller: Send + 'static { /// Schedules a callback on the main thread. /// - /// [`WindowHandle::host_main_thread_callback`](crate::Window::host_main_thread_callback) + /// [`HostedWindow::host_main_thread_callback`](crate::HostedWindow::host_main_thread_callback) /// should be called as a response to this. /// /// # Platform compatibility notes @@ -55,9 +55,8 @@ pub trait HostCallbacks: 'static { /// It also brings the additional safety guarantee that all handlers given to this type will be /// destroyed alongside with the window. /// -/// This guarantees callbacks cannot be fired after the [`Window`](crate::Window) is dropped. -/// (or after this [`Host`] object is dropped, if it never made it to a -/// [`Window::create_with_host`](crate::Window::create_with_host) call). +/// This guarantees callbacks cannot be fired after the window is dropped. +/// (or after this [`Host`] object is dropped, if it never made it to a window creation call). pub struct Host { callbacks: Option>, #[cfg(target_os = "linux")] @@ -72,9 +71,6 @@ impl Default for Host { impl Host { /// Creates a new, empty host with no callbacks. - /// - /// Calling [`Window::create_with_host`](crate::Window::create_with_host) with this is equivalent - /// to just calling [`Window::create`](crate::Window::create). #[inline] pub fn new() -> Self { Self { diff --git a/host/src/lib.rs b/host/src/lib.rs index c325d0a8..d158d20a 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -1,3 +1,5 @@ pub mod dpi; pub mod host; -pub mod window; +mod window; + +pub use window::HostedWindow; diff --git a/host/src/window.rs b/host/src/window.rs index b0ce820e..4e3d5741 100644 --- a/host/src/window.rs +++ b/host/src/window.rs @@ -103,7 +103,7 @@ pub trait HostedWindow { /// Performs the work the window thread had scheduled for the main thread. /// - /// This must be called back on the main thread, as a response to [`HostMainThreadCaller::call_main_thread`](host::HostMainThreadCaller::call_main_thread). + /// This must be called back on the main thread, as a response to [`HostMainThreadCaller::call_main_thread`](crate::host::HostMainThreadCaller::call_main_thread). /// /// # Platform compatibility notes /// diff --git a/src/platform/win/window.rs b/src/platform/win/window.rs index da4c8719..3bd90b31 100644 --- a/src/platform/win/window.rs +++ b/src/platform/win/window.rs @@ -8,7 +8,6 @@ use super::drop_target::DropTarget; use super::*; use crate::dpi::{PhysicalPosition, PhysicalSize, Size}; use crate::handler::WindowHandlerBuilder; -use crate::host::Host; use crate::platform::win::window_state::{WindowSharedState, WindowState}; use crate::platform::PlatformError; use crate::utils::SizingStrategy; diff --git a/src/window.rs b/src/window.rs index 97b0a5bf..e40477cc 100644 --- a/src/window.rs +++ b/src/window.rs @@ -248,7 +248,7 @@ pub(crate) struct WindowInitializer { } pub use baseview_host::dpi::WindowSize; -use baseview_host::window::HostedWindow; +use baseview_host::HostedWindow; impl HostedWindow for Window { #[inline] From 59911e9898376e7246e03fac033467d5e15c688d Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Tue, 6 Oct 2026 12:02:26 +0200 Subject: [PATCH 6/7] wip --- examples/plugin_clack/src/gui.rs | 2 +- examples/plugin_clack_femtovg/src/gui.rs | 2 +- host/src/window.rs | 2 ++ src/platform/x11/mouse.rs | 3 +-- src/platform/x11/present.rs | 1 - src/platform/x11/sizing.rs | 1 - src/platform/x11/window_shared.rs | 1 - src/window.rs | 6 ++++++ 8 files changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/plugin_clack/src/gui.rs b/examples/plugin_clack/src/gui.rs index 1c179568..ccc0ed93 100644 --- a/examples/plugin_clack/src/gui.rs +++ b/examples/plugin_clack/src/gui.rs @@ -2,7 +2,7 @@ use crate::window_handler::OpenWindowExample; use crate::ExamplePluginMainThread; use baseview::dpi::*; use baseview::host::{Host, HostCallbacks, HostMainThreadCaller}; -use baseview::{HandlerError, Window, WindowSettings, WindowSize}; +use baseview::{Window, WindowSettings, WindowSize}; use clack_extensions::gui::{ AspectRatioStrategy, GuiApiType, GuiConfiguration, GuiResizeHints, GuiSize, HostGui, PluginGuiImpl, Window as ClapWindow, diff --git a/examples/plugin_clack_femtovg/src/gui.rs b/examples/plugin_clack_femtovg/src/gui.rs index 77aeae64..8da7cbe2 100644 --- a/examples/plugin_clack_femtovg/src/gui.rs +++ b/examples/plugin_clack_femtovg/src/gui.rs @@ -3,7 +3,7 @@ use crate::ExamplePluginMainThread; use baseview::dpi::*; use baseview::gl::GlConfig; use baseview::host::{Host, HostCallbacks, HostMainThreadCaller}; -use baseview::{HandlerError, Window, WindowSettings, WindowSize}; +use baseview::{Window, WindowSettings, WindowSize}; use clack_extensions::gui::{ AspectRatioStrategy, GuiApiType, GuiConfiguration, GuiResizeHints, GuiSize, HostGui, PluginGuiImpl, Window as ClapWindow, diff --git a/host/src/window.rs b/host/src/window.rs index 4e3d5741..f74c05d6 100644 --- a/host/src/window.rs +++ b/host/src/window.rs @@ -41,6 +41,8 @@ pub trait HostedWindow { where Self: Sized; + fn run_until_closed_dyn(self: Box) -> Result<(), Box>; + /// The current size of the window. fn size(&self) -> WindowSize; diff --git a/src/platform/x11/mouse.rs b/src/platform/x11/mouse.rs index 5ba1b1f9..6b88ce03 100644 --- a/src/platform/x11/mouse.rs +++ b/src/platform/x11/mouse.rs @@ -18,10 +18,9 @@ // the keyboard modifier keys at the time of the event. // http://rtbo.github.io/rust-xcb/src/xcb/ffi/xproto.rs.html#445 -use crate::platform::prelude::Handler; +use crate::platform::prelude::*; use crate::platform::x11::keyboard::key_mods; use crate::{Event, MouseButton, MouseEvent, ScrollDelta}; -use dpi::PhysicalPosition; use x11rb::protocol::xproto::{ ButtonPressEvent, ButtonReleaseEvent, EnterNotifyEvent, LeaveNotifyEvent, MotionNotifyEvent, }; diff --git a/src/platform/x11/present.rs b/src/platform/x11/present.rs index b73a0aa0..cc226700 100644 --- a/src/platform/x11/present.rs +++ b/src/platform/x11/present.rs @@ -6,7 +6,6 @@ use crate::platform::x11::window_thread::RedrawRequested; use crate::DamageArea; use calloop::timer::{TimeoutAction, Timer}; use calloop::LoopHandle; -use dpi::{PhysicalPosition, PhysicalSize}; use std::cell::Cell; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Mutex; diff --git a/src/platform/x11/sizing.rs b/src/platform/x11/sizing.rs index 0c08e221..adbd6b31 100644 --- a/src/platform/x11/sizing.rs +++ b/src/platform/x11/sizing.rs @@ -1,7 +1,6 @@ use super::prelude::*; use crate::utils::SizingStrategy; use crate::{WindowSettings, WindowSize}; -use dpi::{PhysicalSize, Size}; use std::cell::Cell; use std::num::{NonZero, NonZeroU32}; use std::sync::atomic::{AtomicU32, AtomicU64, Ordering}; diff --git a/src/platform/x11/window_shared.rs b/src/platform/x11/window_shared.rs index a44a5ad7..b2273f06 100644 --- a/src/platform/x11/window_shared.rs +++ b/src/platform/x11/window_shared.rs @@ -1,6 +1,5 @@ use super::prelude::*; use calloop::{LoopHandle, LoopSignal}; -use dpi::Size; use raw_window_handle::{DisplayHandle, XlibWindowHandle}; use std::time::Duration; use x11rb::protocol::xproto; diff --git a/src/window.rs b/src/window.rs index e40477cc..0b62b5a8 100644 --- a/src/window.rs +++ b/src/window.rs @@ -260,6 +260,12 @@ impl HostedWindow for Window { Ok(()) } + #[inline] + fn run_until_closed_dyn(self: Box) -> Result<(), Box> { + self.run_until_closed()?; + Ok(()) + } + #[inline] fn size(&self) -> WindowSize { self.size() From af15f77d39bef2c5b72ccd46a35d3a44f1893e7b Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Fri, 9 Oct 2026 13:19:05 +0200 Subject: [PATCH 7/7] wip --- host/src/host.rs | 4 ---- host/src/window.rs | 10 +++++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/host/src/host.rs b/host/src/host.rs index 97a7f1a8..db5602b1 100644 --- a/host/src/host.rs +++ b/host/src/host.rs @@ -26,10 +26,6 @@ pub trait HostCallbacks: 'static { /// Requests the parent window to be resized to accommodate the child window with the given new /// size. /// - /// Note that this method may be called *during* window initialization, i.e. in the middle of - /// [`Window::create_with_host`](crate::Window::create_with_host). Implementations should still - /// properly handle requests to the host in this case. - /// /// # Errors /// /// This can return any type of error, indicating the host either failed or denied to handle the diff --git a/host/src/window.rs b/host/src/window.rs index f74c05d6..9fd9a480 100644 --- a/host/src/window.rs +++ b/host/src/window.rs @@ -50,7 +50,7 @@ pub trait HostedWindow { /// /// The `size` can be provided in either physical or logical pixels. /// - /// Using this method does *not* trigger the [`HostCallbacks::request_resize`](host::HostCallbacks) callback. + /// Using this method does *not* trigger the [`HostCallbacks::request_resize`](super::host::HostCallbacks::request_resize) callback. fn resize(&self, size: Size) -> Result<(), Box>; /// Suggests a fallback scale factor, if Baseview couldn't get one from the platform. @@ -76,7 +76,7 @@ pub trait HostedWindow { /// It is guaranteed that no other objects (e.g. the parent window) are used by this window after /// this call. /// - /// Calling this method is more explicit, but otherwise identical to just dropping this [`Window`]. + /// Calling this method is more explicit, but otherwise identical to just dropping this [`HostedWindow`]. fn close(self) where Self: Sized, @@ -90,17 +90,17 @@ pub trait HostedWindow { /// Returns `true` if the window can be resized by the user, `false` otherwise. /// - /// This is set by the [`WindowSettings::resizable`] field. + // This is set by the [`WindowSettings::resizable`] field. TODO: move some windowSettings to baseview-host fn is_resizable(&self) -> bool; /// Returns the minimum size of the window, if it has one. /// - /// This is set by the [`WindowSettings::min_size`] field. + // This is set by the [`WindowSettings::min_size`] field. fn min_size(&self) -> Option; /// Returns the minimum size of the window, if it has one. /// - /// This is set by the [`WindowSettings::max_size`] field. + // This is set by the [`WindowSettings::max_size`] field. fn max_size(&self) -> Option; /// Performs the work the window thread had scheduled for the main thread.