Skip to content
Merged
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
24 changes: 8 additions & 16 deletions examples/plugin_clack/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ impl PluginGuiImpl for ExamplePluginMainThread<'_> {
}

fn create(&mut self, _configuration: GuiConfiguration) -> Result<(), PluginError> {
let options =
WindowSettings::new().wait_for_parent().with_size(PhysicalSize::new(400, 200));
let options = WindowSettings::new()
.wait_for_parent()
.with_size(PhysicalSize::new(400, 200))
.with_min_size(LogicalSize::new(200.0, 100.0))
.with_max_size(LogicalSize::new(600.0, 400.0));

let mut host = Host::new().with_main_thread(unsafe {
MainThreadHandler { host: self.host.shared().with_arbitrary_lifetime() }
Expand Down Expand Up @@ -90,23 +93,12 @@ impl PluginGuiImpl for ExamplePluginMainThread<'_> {
})
}

fn adjust_size(&mut self, mut size: GuiSize) -> Option<GuiSize> {
fn adjust_size(&mut self, size: GuiSize) -> Option<GuiSize> {
let Some(gui) = &self.gui else { return None };
let scale_factor = gui.handle.size().scale_factor;

if let Some(max_size) = gui.handle.max_size() {
let max_size = NativeSize::from_size(max_size, scale_factor);
size.width = size.width.min(max_size.width);
size.height = size.height.min(max_size.height);
}

if let Some(min_size) = gui.handle.min_size() {
let min_size = NativeSize::from_size(min_size, scale_factor);
size.width = size.width.max(min_size.width);
size.height = size.height.max(min_size.height);
}
let size = gui.handle.adjust_size(NativeSize::new(size.width, size.height));

Some(size)
Some(GuiSize { width: size.width, height: size.height })
}

fn set_size(&mut self, size: GuiSize) -> Result<(), PluginError> {
Expand Down
10 changes: 10 additions & 0 deletions src/dpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,21 @@ pub struct NativeSize<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<P> NativeSize<P> {
#[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<P: Pixel> NativeSize<P> {
Expand Down
9 changes: 6 additions & 3 deletions src/platform/macos/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,15 @@ impl WindowContext {
}

pub fn resize(&self, size: Size) -> Result<()> {
let Some(view) = self.view.load() else { return Ok(()) };
let Some(view) = view.inner_ref() else { return Ok(()) };
if view.inner.state.closed.get() {
if self.state.closed.get() {
return Ok(());
}

let Some(view) = self.view.load() else { return Ok(()) };
let Some(view) = view.inner_ref() else { return Ok(()) };

let size = self.state.sizing_strategy.adjust_size(size, self.size()).logical;

BaseviewView::resize(view, size, true, false);

Ok(())
Expand Down
17 changes: 11 additions & 6 deletions src/platform/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::keyboard::{make_modifiers, KeyboardState};
use super::window::WindowSharedState;
use crate::dpi::{LogicalPosition, LogicalSize, Size};
use crate::dpi::{LogicalPosition, LogicalSize};
use crate::host::Host;
use crate::platform::macos::cursor::CursorManager;
use crate::platform::*;
Expand Down Expand Up @@ -215,8 +215,13 @@ impl BaseviewView {
this.parenting.replace(parenting);
}

pub fn resize(this: ViewRef<Self>, size: Size, notify_host: bool, from_window: bool) {
let size = size.to_logical::<f64>(this.view.backing_scale_factor());
pub fn resize(
this: ViewRef<Self>, size: LogicalSize<f64>, notify_host: bool, from_window: bool,
) {
if size == this.inner.state.size.get() {
return;
}

// NOTE: macOS gives you a personal rave if you pass in fractional pixels here. Even
// though the size is in fractional pixels.
let size = NSSize::new(size.width.round(), size.height.round());
Expand Down Expand Up @@ -311,7 +316,7 @@ impl ViewImpl for BaseviewView {
let size = window.contentRectForFrameRect(window.frame()).size;
let size = LogicalSize::new(size.width, size.height);

BaseviewView::resize(this, size.into(), true, true);
BaseviewView::resize(this, size, true, true);
}

fn view_did_change_backing_properties(this: ViewRef<Self>, notify_host: bool) {
Expand All @@ -337,15 +342,15 @@ impl ViewImpl for BaseviewView {
warn!("Window Handler failed to resize: {}", e);
this.state.size.set(previous);

Self::resize(this, previous.into(), false, false);
Self::resize(this, previous, false, false);
return;
}

if notify_host {
if let Err(e) = this.host.request_resize(new_size) {
warn!("Host failed to resize parent view: {}", e);

Self::resize(this, previous.into(), false, false);
Self::resize(this, previous, false, false);
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/platform/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl WindowHandle {
let Some(view) = self.view.load() else { return Ok(()) };
let Some(view) = view.inner_ref() else { return Ok(()) };

BaseviewView::resize(view, size, false, false);
BaseviewView::resize(view, size.to_logical(self.state.scale_factor.get()), false, false);

Ok(())
}
Expand Down Expand Up @@ -160,6 +160,10 @@ impl WindowHandle {
BaseviewView::hide(view);
Ok(())
}

pub fn sizing_strategy(&self) -> SizingStrategy {
self.state.sizing_strategy
}
}

fn create_window_with_options(
Expand Down
12 changes: 11 additions & 1 deletion src/platform/win/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::handler::WindowHandlerBuilder;
use crate::host::Host;
use crate::platform::win::window_state::{WindowSharedState, WindowState};
use crate::platform::PlatformError;
use crate::utils::SizingStrategy;
use crate::window::WindowInitializer;
use crate::wrappers::win32::cursor::SystemCursor;
use crate::wrappers::win32::window::*;
Expand Down Expand Up @@ -75,7 +76,12 @@ impl WindowHandle {
}

pub fn resize(&self, new_size: Size) -> Result<()> {
let new_size = new_size.to_physical(self.state.scale_factor());
let new_size = self.state.sizing_strategy.adjust_size(new_size, self.size()).physical;

if new_size == self.state.current_size.get() {
return Ok(());
}

let hwnd = match self.hwnd.get() {
Some(hwnd) => hwnd,
None => {
Expand All @@ -96,6 +102,10 @@ impl WindowHandle {
}
}

pub fn sizing_strategy(&self) -> SizingStrategy {
self.state.sizing_strategy
}

pub fn suggest_scale_factor(&self, scale_factor: f64) -> Result<()> {
let current_scale_factor = self.state.scale_factor();
self.state.fallback_scale_factor.set(Some(scale_factor));
Expand Down
12 changes: 8 additions & 4 deletions src/platform/x11/window_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,16 @@ impl WindowInner {
}

pub fn resize(&self, size: Size) -> Result<()> {
let new_physical_size = size.to_physical(self.scaling_factor.get());
self.xcb_window.resize(new_physical_size)?.check()?;
let new_size = self.sizing_strategy.adjust_size(size, self.size()).physical;

if new_size == self.window_size.get().cast() {
return Ok(());
}

self.xcb_window.resize(new_size)?.check()?;

if !self.sizing_strategy.is_resizable() {
let size_hints =
get_size_hints(&self.sizing_strategy, new_physical_size, self.scale_factor());
let size_hints = get_size_hints(&self.sizing_strategy, new_size, self.scale_factor());
self.xcb_window.set_size_hints(size_hints)?.check()?;
}

Expand Down
4 changes: 4 additions & 0 deletions src/platform/x11/window_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ impl WindowThreadHandle {
result.map_err(|e| RequestFailed::Response(e).into())
}

pub fn sizing_strategy(&self) -> SizingStrategy {
self.shared.sizing_strategy.get().copied().unwrap_or_default()
}

pub fn run_until_closed(&self) -> Result<()> {
if !self.shared.stopped.load(Ordering::Relaxed) {
self.request(WindowThreadRequest::Show)?;
Expand Down
46 changes: 45 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::dpi::Size;
use crate::WindowSettings;
use crate::{WindowSettings, WindowSize};
use dpi::{LogicalSize, PhysicalSize};

#[derive(Copy, Clone)]
pub(crate) enum SizingStrategy {
Expand Down Expand Up @@ -39,6 +40,49 @@ impl SizingStrategy {
Self::Resizable { max_size, .. } => *max_size,
}
}

fn adjust_size_physical(&self, mut size: PhysicalSize<u32>, scale_factor: f64) -> WindowSize {
if let Some(max_size) = self.max_size() {
let max_size = max_size.to_physical::<u32>(scale_factor);
size.width = max_size.width.min(size.width);
size.height = max_size.height.min(size.height);
}

if let Some(min_size) = self.min_size() {
let min_size = min_size.to_physical::<u32>(scale_factor);
size.width = min_size.width.max(size.width);
size.height = min_size.height.max(size.height);
}

WindowSize::from_physical(size, scale_factor)
}

fn adjust_size_logical(&self, mut size: LogicalSize<f64>, scale_factor: f64) -> WindowSize {
if let Some(max_size) = self.max_size() {
let max_size = max_size.to_logical::<f64>(scale_factor);
size.width = max_size.width.min(size.width);
size.height = max_size.height.min(size.height);
}

if let Some(min_size) = self.min_size() {
let min_size = min_size.to_logical::<f64>(scale_factor);
size.width = min_size.width.max(size.width);
size.height = min_size.height.max(size.height);
}

WindowSize::from_logical(size, scale_factor)
}

pub fn adjust_size(&self, size: Size, window_size: WindowSize) -> WindowSize {
if !self.is_resizable() {
return window_size;
}

match size {
Size::Physical(size) => self.adjust_size_physical(size, window_size.scale_factor),
Size::Logical(size) => self.adjust_size_logical(size, window_size.scale_factor),
}
}
}

impl Default for SizingStrategy {
Expand Down
13 changes: 13 additions & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ impl Window {
self.inner.hide()?;
Ok(())
}

/// Adjusts the given size to the window's size constraints.
#[inline]
pub fn adjust_size<S: From<WindowSize> + Into<Size>>(&self, size: S) -> S {
self.inner.sizing_strategy().adjust_size(size.into(), self.size()).into()
}
}

pub(crate) struct WindowInitializer {
Expand Down Expand Up @@ -282,3 +288,10 @@ impl<P: Pixel> From<WindowSize> for LogicalSize<P> {
size.logical.cast()
}
}

impl From<WindowSize> for Size {
#[inline]
fn from(value: WindowSize) -> Self {
value.to_native_size::<f64>().into()
}
}