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

fn can_resize(&mut self) -> bool {
true // Non-resizeable windows not supported yet
let Some(gui) = &self.gui else { return false };

gui.handle.is_resizable()
}

fn get_resize_hints(&mut self) -> Option<GuiResizeHints> {
let can_resize = self.can_resize();

Some(GuiResizeHints {
strategy: AspectRatioStrategy::Disregard, // Not supported

// Non-resizeable windows not supported yet
can_resize_vertically: true,
can_resize_horizontally: true,
can_resize_vertically: can_resize,
can_resize_horizontally: can_resize,
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/platform/macos/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl WindowContext {
return Ok(());
}

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

Ok(())
}
Expand Down
27 changes: 19 additions & 8 deletions src/platform/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl BaseviewView {
let view_rect =
NSRect::new(NSPoint::ZERO, NSSize::new(final_size.width, final_size.height));

let state = Rc::new(WindowSharedState::new(final_size, 1.0));
let state = Rc::new(WindowSharedState::new(final_size, 1.0, init.settings.resizable));

let inner = BaseviewView {
mtm,
Expand Down Expand Up @@ -205,7 +205,7 @@ impl BaseviewView {
this.parenting.replace(parenting);
}

pub fn resize(this: ViewRef<Self>, size: Size, notify_host: bool) {
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());
// NOTE: macOS gives you a personal rave if you pass in fractional pixels here. Even
// though the size is in fractional pixels.
Expand All @@ -221,10 +221,12 @@ impl BaseviewView {
gl_context.resize(size);
}

// If this is a standalone window then we'll also need to resize the window itself
if let ViewParentingType::Windowed { owned_window } = &*this.parenting.borrow() {
if let Some(owned_window) = owned_window.load() {
owned_window.setContentSize(size);
if !from_window {
// If this is a standalone window then we'll also need to resize the window itself
if let ViewParentingType::Windowed { owned_window } = &*this.parenting.borrow() {
if let Some(owned_window) = owned_window.load() {
owned_window.setContentSize(size);
}
}
}

Expand Down Expand Up @@ -275,6 +277,15 @@ impl ViewImpl for BaseviewView {
true
}

fn window_did_resize(this: ViewRef<Self>) {
let Some(window) = this.view.window() else { return };

let size = window.contentRectForFrameRect(window.frame()).size;
let size = LogicalSize::new(size.width, size.height);

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

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

Self::resize(this, previous.into(), false);
Self::resize(this, previous.into(), 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);
Self::resize(this, previous.into(), false, false);
}
}
}
Expand Down
26 changes: 18 additions & 8 deletions src/platform/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ impl WindowHandle {
self.state.closed.get()
}

pub fn is_resizable(&self) -> bool {
self.state.resizable
}

#[inline]
pub fn handle_main_thread_callback(&self) {
// No-op
Expand All @@ -108,7 +112,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);
BaseviewView::resize(view, size, false, false);

Ok(())
}
Expand Down Expand Up @@ -145,18 +149,18 @@ impl WindowHandle {
}

fn create_window_with_options(
options: &WindowSettings, mtm: MainThreadMarker,
settings: &WindowSettings, mtm: MainThreadMarker,
) -> Retained<NSWindow> {
let initial_size = options.size.to_logical(1.0);
let window = create_window(initial_size, mtm);
let initial_size = settings.size.to_logical(1.0);
let window = create_window(initial_size, settings, mtm);
window.center();

let final_size = options.size.to_logical(window.backingScaleFactor());
let final_size = settings.size.to_logical(window.backingScaleFactor());
if final_size != initial_size {
window.setContentSize(NSSize::new(final_size.width, final_size.height));
}

let title = NSString::from_str(&options.title);
let title = NSString::from_str(&settings.title);
window.setTitle(&title);

window
Expand All @@ -166,11 +170,17 @@ pub(crate) struct WindowSharedState {
pub closed: Cell<bool>,
pub size: Cell<LogicalSize<f64>>,
pub scale_factor: Cell<f64>,
pub resizable: bool,
}

impl WindowSharedState {
pub fn new(size: LogicalSize<f64>, scale_factor: f64) -> Self {
Self { closed: false.into(), size: size.into(), scale_factor: scale_factor.into() }
pub fn new(size: LogicalSize<f64>, scale_factor: f64, resizable: bool) -> Self {
Self {
closed: false.into(),
size: size.into(),
scale_factor: scale_factor.into(),
resizable,
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/platform/win/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ impl WindowHandle {
self.state.is_alive.get()
}

pub fn is_resizable(&self) -> bool {
self.state.resizable
}

pub fn size(&self) -> WindowSize {
self.state.size()
}
Expand Down Expand Up @@ -211,11 +215,7 @@ impl BaseviewWindow {
pub fn create(shared_state: Rc<WindowSharedState>, init: WindowInitializer) -> Result<HWnd> {
let dpi_ctx = DpiAwarenessContext::new(&shared_state.user32)?;

let style = if init.settings.parent.is_some() {
WindowStyle::parented()
} else {
WindowStyle::embedded()
};
let style = WindowStyle::from_settings(&init.settings);

let window_size = shared_state.current_size.get();

Expand Down
2 changes: 2 additions & 0 deletions src/platform/win/window_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ pub struct WindowSharedState {
pub destroy_host_originated: Cell<bool>,

pub user32: ExtendedUser32,
pub resizable: bool,
}

impl WindowSharedState {
Expand All @@ -163,6 +164,7 @@ impl WindowSharedState {
fallback_scale_factor: settings.fallback_scale_factor.into(),
resize_host_originated: false.into(),
destroy_host_originated: false.into(),
resizable: settings.resizable,
user32,
}
.into()
Expand Down
16 changes: 16 additions & 0 deletions src/platform/x11/window_shared.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::platform::x11::event_loop::EventLoop;
use crate::platform::x11::visual_info::WindowVisualConfig;
use crate::platform::x11::window_thread::WindowThreadShared;
use crate::platform::x11::xcb_connection::{get_size_hints, WmSizeHintsExt};
use crate::platform::x11::xcb_window::XcbWindow;
use crate::platform::*;
use crate::{warn, MouseCursor, WindowHandler, WindowSettings, WindowSize};
Expand All @@ -10,6 +11,7 @@ use raw_window_handle::{DisplayHandle, XlibWindowHandle};
use std::cell::Cell;
use std::rc::Rc;
use std::sync::Arc;
use x11rb::properties::WmSizeHints;
use x11rb::protocol::xproto::{ChangeWindowAttributesAux, ConnectionExt, InputFocus, Visualid};
use x11rb::CURRENT_TIME;

Expand Down Expand Up @@ -49,6 +51,7 @@ pub(crate) struct WindowInner {
pub(crate) scaling_factor: ScalingFactor,

window_size: Cell<PhysicalSize<u16>>,
pub(crate) is_resizable: bool,
mouse_cursor: Cell<MouseCursor>,
pub(crate) visual_id: Visualid,

Expand All @@ -73,6 +76,8 @@ impl WindowInner {

let physical_size = options.size.to_physical(initial_scale_factor);

let size_hints = get_size_hints(&options, initial_scale_factor);

#[cfg(feature = "opengl")]
let visual_info =
WindowVisualConfig::find_best_visual_config_for_gl(&xcb_connection, options.gl_config)?;
Expand All @@ -93,6 +98,7 @@ impl WindowInner {
xcb_window.set_title(&options.title)?,
xcb_window.enable_wm_protocols()?,
xcb_window.enable_dnd_protocols()?,
xcb_window.set_size_hints(size_hints)?,
];

for cookie in cookies {
Expand Down Expand Up @@ -121,6 +127,7 @@ impl WindowInner {
system: scaling.into(),
suggested: options.fallback_scale_factor.into(),
},
is_resizable: options.resizable,
mouse_cursor: MouseCursor::default().into(),
loop_signal: ev_loop.get_signal(),

Expand Down Expand Up @@ -186,6 +193,11 @@ impl WindowInner {
let new_physical_size = size.to_physical(self.scaling_factor.get());
self.xcb_window.resize(new_physical_size)?.check()?;

if !self.is_resizable {
let size_hints = WmSizeHints::new().with_fixed_size(new_physical_size.cast());
self.xcb_window.set_size_hints(size_hints)?.check()?;
}

// This will trigger a `ConfigureNotify` event which will in turn change `self.window_info`
// and notify the window handler about it

Expand All @@ -210,6 +222,10 @@ impl WindowInner {
}

self.xcb_window.resize(new_size.cast())?.check()?; // Will not call handler, as size is the same as above.
if !self.is_resizable {
let size_hints = WmSizeHints::new().with_fixed_size(new_size.cast());
self.xcb_window.set_size_hints(size_hints)?.check()?;
}

// These come from the Host, no need to notify it about the new size

Expand Down
15 changes: 15 additions & 0 deletions src/platform/x11/window_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub(crate) struct WindowThreadShared {
size: AtomicU32,
final_error: Mutex<Option<String>>,
stopped_requested_from_host: AtomicBool,
is_resizable: AtomicBool,
}

impl WindowThreadShared {
Expand All @@ -32,12 +33,14 @@ impl WindowThreadShared {
size: 0.into(),
scaling_factor: 0.into(),
stopped_requested_from_host: false.into(),
is_resizable: true.into(),
}
}

fn init(&self, window: &WindowInner) {
self.set_size(window.get_size());
self.set_scaling_factor(window.scale_factor());
self.set_resizable(window.is_resizable);
}

pub fn get_size(&self) -> PhysicalSize<u16> {
Expand All @@ -53,6 +56,14 @@ impl WindowThreadShared {
self.size.store(bytes, Ordering::Relaxed);
}

pub fn set_resizable(&self, resizable: bool) {
self.is_resizable.store(resizable, Ordering::Relaxed);
}

pub fn is_resizable(&self) -> bool {
self.is_resizable.load(Ordering::Relaxed)
}

pub fn get_scaling_factor(&self) -> f64 {
f64::from_be_bytes(self.scaling_factor.load(Ordering::Relaxed).to_ne_bytes())
}
Expand Down Expand Up @@ -201,6 +212,10 @@ impl WindowThreadHandle {
!self.shared.stopped.load(Ordering::Relaxed)
}

pub fn is_resizable(&self) -> bool {
self.shared.is_resizable()
}

pub fn handle_main_thread_callback(&mut self) {
loop {
let Some(receiver) = self.callback_receiver.as_mut() else { return };
Expand Down
2 changes: 2 additions & 0 deletions src/platform/x11/xcb_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use crate::MouseCursor;

mod get_property;
pub use get_property::GetPropertyError;
mod size_hints;
pub use size_hints::{get_size_hints, WmSizeHintsExt};

x11rb::atom_manager! {
pub Atoms: AtomsCookie {
Expand Down
24 changes: 24 additions & 0 deletions src/platform/x11/xcb_connection/size_hints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::WindowSettings;
use dpi::PhysicalSize;
use x11rb::properties::WmSizeHints;

pub fn get_size_hints(settings: &WindowSettings, scale_factor: f64) -> WmSizeHints {
let mut size_hints = WmSizeHints::default();

if !settings.resizable {
size_hints = size_hints.with_fixed_size(settings.size.to_physical(scale_factor));
}

size_hints
}

pub trait WmSizeHintsExt: Sized {
fn with_fixed_size(self, size: PhysicalSize<i32>) -> Self;
}

impl WmSizeHintsExt for WmSizeHints {
fn with_fixed_size(mut self, size: PhysicalSize<i32>) -> Self {
self.max_size = Some((size.width, size.height));
self
}
}
8 changes: 8 additions & 0 deletions src/platform/x11/xcb_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::rc::Rc;
use x11rb::connection::Connection;
use x11rb::cookie::VoidCookie;
use x11rb::errors::{ConnectionError, ReplyOrIdError};
use x11rb::properties::WmSizeHints;
use x11rb::protocol::xproto::{
AtomEnum, ConfigureWindowAux, ConnectionExt as _, CreateWindowAux, EventMask, PropMode,
WindowClass,
Expand Down Expand Up @@ -119,6 +120,13 @@ impl XcbWindow {
)?)
}

pub fn set_size_hints(
&self, size_hints: WmSizeHints,
) -> Result<VoidCookie<'_, XCBConnection>, ReplyOrIdError> {
Ok(size_hints
.set_normal_hints(&self.connection.conn as &XCBConnection, self.window_id.get())?)
}

#[inline]
pub fn id(&self) -> NonZeroU32 {
self.window_id
Expand Down
Loading