Skip to content

Commit bb46eb3

Browse files
committed
wip
1 parent a18c31b commit bb46eb3

7 files changed

Lines changed: 112 additions & 45 deletions

File tree

examples/open_parented/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use baseview::{
55
};
66
use std::cell::{Cell, RefCell};
77
use std::num::NonZeroU32;
8+
use std::thread;
9+
use std::time::Duration;
810

911
struct ParentWindowHandler {
1012
surface: RefCell<softbuffer::Surface<WindowContext, WindowContext>>,
@@ -56,6 +58,7 @@ impl WindowHandler for ParentWindowHandler {
5658

5759
let child_size =
5860
PhysicalSize::new(new_size.physical.width / 2, new_size.physical.height / 2);
61+
self.child_window.suggest_scale_factor(new_size.scale_factor)?;
5962
self.child_window.resize(child_size.into())?;
6063
Ok(())
6164
}

examples/plugin_clack/src/gui.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::window_handler::OpenWindowExample;
22
use crate::ExamplePluginMainThread;
3-
use baseview::dpi::{LogicalSize, PhysicalSize, Size};
3+
use baseview::dpi::{PhysicalSize, Size};
44
use baseview::gl::GlConfig;
55
use baseview::{WindowHandle, WindowOpenOptions, WindowSize};
66
use clack_extensions::gui::{

src/platform/win/window.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub(crate) const BV_WINDOW_MUST_CLOSE: u32 = WM_USER + 1;
2323
use super::drop_target::DropTarget;
2424
use super::*;
2525
use crate::handler::WindowHandlerBuilder;
26-
use crate::platform::win::window_state::WindowState;
26+
use crate::platform::win::window_state::{WindowSharedState, WindowState};
2727
use crate::platform::Error;
2828
use crate::wrappers::win32::cursor::SystemCursor;
2929
use crate::wrappers::win32::window::*;
@@ -53,7 +53,7 @@ const WIN_FRAME_TIMER: NonZeroUsize = match NonZeroUsize::new(4242) {
5353

5454
pub struct WindowHandle {
5555
hwnd: Cell<Option<HWnd>>,
56-
is_open: Rc<Cell<bool>>,
56+
state: Rc<WindowSharedState>,
5757
}
5858

5959
impl WindowHandle {
@@ -63,7 +63,7 @@ impl WindowHandle {
6363
}
6464

6565
pub fn is_open(&self) -> bool {
66-
self.is_open.get()
66+
self.state.is_alive.get()
6767
}
6868
}
6969

@@ -75,31 +75,27 @@ impl Drop for WindowHandle {
7575
}
7676
}
7777

78-
struct ParentHandle {
79-
is_open: Rc<Cell<bool>>,
80-
}
81-
82-
impl Drop for ParentHandle {
83-
fn drop(&mut self) {
84-
self.is_open.set(false);
85-
}
86-
}
87-
8878
pub struct BaseviewWindow {
8979
window_state: Rc<WindowState>,
80+
shared_state: Rc<WindowSharedState>,
9081
initial_size: Size,
9182

9283
handler_builder: Cell<Option<WindowHandlerBuilder>>,
9384

9485
// Things not directly used, but kept so their Drop impl runs when the window is destroyed
95-
_parent_handle: ParentHandle,
9686
_keyboard_hook: Cell<Option<hook::KeyboardHookHandle>>,
9787
_drop_target: Cell<Option<ComObject<DropTarget>>>,
9888

9989
#[cfg(feature = "opengl")]
10090
pub gl_config: Option<crate::gl::GlConfig>,
10191
}
10292

93+
impl Drop for BaseviewWindow {
94+
fn drop(&mut self) {
95+
self.shared_state.is_alive.set(false);
96+
}
97+
}
98+
10399
impl WindowImpl for BaseviewWindow {
104100
fn after_create(&self, window: HWnd) -> core::result::Result<(), Error> {
105101
let hwnd = window.as_raw();
@@ -442,10 +438,7 @@ impl WindowHandle {
442438

443439
let rect = dpi_ctx.client_area_to_nc_area(window_size.into(), style, Dpi::default())?;
444440

445-
let is_open = Rc::new(Cell::new(true));
446-
447441
let initializer = {
448-
let parent_handle = ParentHandle { is_open: is_open.clone() };
449442
let extended_user_32 = extended_user_32.clone();
450443

451444
move |hwnd: HWnd| {
@@ -457,7 +450,6 @@ impl WindowHandle {
457450
initial_size: options.size,
458451
handler_builder: Cell::new(Some(build)),
459452

460-
_parent_handle: parent_handle,
461453
_drop_target: None.into(),
462454
_keyboard_hook: None.into(),
463455

src/platform/win/window_state.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ use dpi::{PhysicalSize, Size};
1010
use raw_window_handle::{DisplayHandle, Win32WindowHandle};
1111
use std::cell::{Cell, OnceCell, Ref, RefCell};
1212
use std::num::NonZeroIsize;
13+
use std::rc::Rc;
1314
use windows_sys::Win32::UI::WindowsAndMessaging::PostMessageW;
1415

1516
/// All data associated with the window.
1617
pub(crate) struct WindowState {
1718
/// The HWND belonging to this window.
1819
pub hwnd: HWnd,
19-
pub current_size: Cell<PhysicalSize<u32>>,
20-
pub current_dpi: Cell<Dpi>, // None if in non-system scale policy
2120
pub keyboard_state: RefCell<KeyboardState>,
2221
pub mouse_button_counter: Cell<usize>,
2322
pub mouse_was_outside_window: Cell<bool>,
@@ -39,8 +38,6 @@ impl WindowState {
3938
) -> Self {
4039
Self {
4140
hwnd,
42-
current_dpi: Dpi::default().into(),
43-
current_size: current_size.into(),
4441
keyboard_state: RefCell::new(KeyboardState::new()),
4542
mouse_button_counter: Cell::new(0),
4643
mouse_was_outside_window: true.into(),
@@ -127,7 +124,6 @@ impl WindowState {
127124

128125
#[cfg(feature = "opengl")]
129126
pub fn gl_context(&self) -> Option<crate::gl::GlContext> {
130-
use std::rc::Rc;
131127
Some(crate::gl::GlContext::new(Rc::clone(self.gl_context.get()?)))
132128
}
133129

@@ -148,3 +144,20 @@ impl WindowState {
148144
PlatformHandle { hwnd }
149145
}
150146
}
147+
148+
pub struct WindowSharedState {
149+
pub is_alive: Cell<bool>,
150+
pub current_size: Cell<PhysicalSize<u32>>,
151+
pub current_dpi: Cell<Dpi>, // None if in non-system scale policy
152+
}
153+
154+
impl WindowSharedState {
155+
pub fn new(current_size: PhysicalSize<u32>) -> Rc<Self> {
156+
Self {
157+
is_alive: true.into(),
158+
current_dpi: Dpi::default().into(),
159+
current_size: current_size.into(),
160+
}
161+
.into()
162+
}
163+
}

src/platform/x11/event_loop.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,21 +137,23 @@ impl EventLoop {
137137
let scale_factor = self.window.scaling_factor.get();
138138
let new_size = new_size.to_physical(scale_factor);
139139

140-
// Handle everything directly, so we can return a handler error immediately.
141-
let previous = self.window.store_size(new_size);
142-
self.window.xcb_window.resize(new_size.cast())?; // Will not call handler, as size is the same as above.
143-
144-
if let Err(e) =
145-
self.handler.resized(WindowSize::from_physical(new_size.cast(), scale_factor))
146-
{
147-
warn!("Window Handler failed to resize: {}. Reverting to previous size", &e);
148-
self.window.store_size(previous);
149-
return Err(e.into());
150-
}
140+
self.window.resize_immediately(new_size, &*self.handler)?;
141+
142+
Ok(())
143+
}
144+
WindowThreadRequest::SuggestScaleFactor(scale) => {
145+
// If the scaling factor is already provided by the system, do nothing
146+
if !self.window.scaling_factor.suggest(scale) {
147+
return Ok(());
148+
};
149+
150+
let current_logical_size = self.window.get_size().to_logical::<f64>(1.0);
151+
let new_physical_size = current_logical_size.to_physical(scale);
152+
153+
self.window.resize_immediately(new_physical_size, &*self.handler)?;
151154

152155
Ok(())
153156
}
154-
_ => todo!(),
155157
}
156158
}
157159

src/platform/x11/window_shared.rs

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::platform::x11::visual_info::WindowVisualConfig;
33
use crate::platform::x11::window_thread::WindowThreadShared;
44
use crate::platform::x11::xcb_window::XcbWindow;
55
use crate::platform::*;
6-
use crate::{MouseCursor, WindowOpenOptions, WindowScalePolicy, WindowSize};
6+
use crate::{warn, MouseCursor, WindowHandler, WindowOpenOptions, WindowScalePolicy, WindowSize};
77
use calloop::LoopSignal;
88
use dpi::{PhysicalSize, Size};
99
use raw_window_handle::{DisplayHandle, XlibWindowHandle};
@@ -13,14 +13,48 @@ use std::sync::Arc;
1313
use x11rb::protocol::xproto::{ChangeWindowAttributesAux, ConnectionExt, InputFocus, Visualid};
1414
use x11rb::CURRENT_TIME;
1515

16+
pub struct ScalingFactor {
17+
system: Cell<Option<f64>>,
18+
suggested: Cell<Option<f64>>,
19+
}
20+
21+
impl ScalingFactor {
22+
pub fn get(&self) -> f64 {
23+
if let Some(factor) = self.system.get() {
24+
return factor;
25+
};
26+
27+
if let Some(factor) = self.suggested.get() {
28+
return factor;
29+
}
30+
31+
1.0
32+
}
33+
34+
pub fn suggest(&self, value: f64) -> bool {
35+
self.suggested.set(Some(value));
36+
37+
self.system.get().is_none()
38+
}
39+
}
40+
41+
impl From<Option<f64>> for ScalingFactor {
42+
fn from(value: Option<f64>) -> Self {
43+
// FIXME
44+
Self { system: None.into(), suggested: None.into() }
45+
}
46+
}
47+
1648
pub(crate) struct WindowInner {
1749
// GlContext should be dropped **before** XcbConnection is dropped
1850
#[cfg(feature = "opengl")]
1951
gl_context: Option<super::gl::GlContext>,
2052

2153
pub(crate) xcb_window: XcbWindow,
2254
pub(crate) connection: Rc<X11Connection>,
23-
pub(crate) scaling_factor: Cell<f64>,
55+
56+
pub(crate) scaling_factor: ScalingFactor,
57+
2458
window_size: Cell<PhysicalSize<u16>>,
2559
mouse_cursor: Cell<MouseCursor>,
2660
pub(crate) visual_id: Visualid,
@@ -41,11 +75,13 @@ impl WindowInner {
4175

4276
let scaling = match options.scale {
4377
WindowScalePolicy::SystemScaleFactor => xcb_connection.get_scaling(),
44-
WindowScalePolicy::ScaleFactor(scale) => scale,
78+
WindowScalePolicy::ScaleFactor(scale) => Some(scale),
4579
};
4680

47-
shared.set_scaling_factor(scaling);
48-
let physical_size = options.size.to_physical(scaling);
81+
let initial_scale_factor = scaling.unwrap_or(1.0);
82+
shared.set_scaling_factor(initial_scale_factor);
83+
84+
let physical_size = options.size.to_physical(initial_scale_factor);
4985

5086
#[cfg(feature = "opengl")]
5187
let visual_info =
@@ -164,6 +200,28 @@ impl WindowInner {
164200
Ok(())
165201
}
166202

203+
pub fn resize_immediately(
204+
&self, new_size: PhysicalSize<u16>, handler: &dyn WindowHandler,
205+
) -> Result<()> {
206+
let previous = self.store_size(new_size);
207+
208+
if previous == new_size {
209+
return Ok(());
210+
};
211+
212+
self.xcb_window.resize(new_size.cast())?; // Will not call handler, as size is the same as above.
213+
214+
if let Err(e) =
215+
handler.resized(WindowSize::from_physical(new_size.cast(), self.scaling_factor.get()))
216+
{
217+
warn!("Window Handler failed to resize: {}. Reverting to previous size", &e);
218+
self.store_size(previous);
219+
return Err(e.into());
220+
}
221+
222+
Ok(())
223+
}
224+
167225
pub fn window_handle(&self) -> Option<raw_window_handle::WindowHandle<'_>> {
168226
let mut handle = XlibWindowHandle::new(self.xcb_window.id().get() as _);
169227
handle.visual_id = self.visual_id.into();

src/platform/x11/xcb_connection.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@ impl X11Connection {
6969
})
7070
}
7171

72-
pub fn get_scaling(&self) -> f64 {
73-
// If the WM didn't set any display scaling, assume a scaling factor of 1.0 (i.e. don't do any scaling)
72+
pub fn get_scaling(&self) -> Option<f64> {
7473
if let Ok(Some(dpi)) = self.resources.get_value::<u32>("Xft.dpi", "") {
75-
dpi as f64 / 96.0
74+
Some(dpi as f64 / 96.0)
7675
} else {
77-
1.0
76+
None
7877
}
7978
}
8079

0 commit comments

Comments
 (0)