mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
wayland: rework scale factor handling (#1538)
- Always send Resized events in case of scale factor change - Properly take into account the resize the user can do using the resize event.
This commit is contained in:
parent
54bc41f68b
commit
114fe9d502
|
@ -714,8 +714,43 @@ impl<T> EventLoop<T> {
|
|||
window_target.store.lock().unwrap().for_each(|window| {
|
||||
let window_id =
|
||||
crate::window::WindowId(crate::platform_impl::WindowId::Wayland(window.wid));
|
||||
if let Some(frame) = window.frame {
|
||||
if let Some((w, h)) = window.newsize {
|
||||
|
||||
// Update window logical .size field (for callbacks using .inner_size)
|
||||
let (old_logical_size, mut logical_size) = {
|
||||
let mut window_size = window.size.lock().unwrap();
|
||||
let old_logical_size = *window_size;
|
||||
*window_size = window.new_size.unwrap_or(old_logical_size);
|
||||
(old_logical_size, *window_size)
|
||||
};
|
||||
|
||||
if let Some(scale_factor) = window.new_scale_factor {
|
||||
// Update cursor scale factor
|
||||
self.cursor_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.update_scale_factor(scale_factor as u32);
|
||||
let new_logical_size = {
|
||||
let scale_factor = scale_factor as f64;
|
||||
let mut physical_size =
|
||||
LogicalSize::<f64>::from(logical_size).to_physical(scale_factor);
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
new_inner_size: &mut physical_size,
|
||||
},
|
||||
});
|
||||
physical_size.to_logical::<u32>(scale_factor).into()
|
||||
};
|
||||
// Update size if changed by callback
|
||||
if new_logical_size != logical_size {
|
||||
logical_size = new_logical_size;
|
||||
*window.size.lock().unwrap() = logical_size.into();
|
||||
}
|
||||
}
|
||||
|
||||
if window.new_size.is_some() || window.new_scale_factor.is_some() {
|
||||
if let Some(frame) = window.frame {
|
||||
// Update decorations state
|
||||
match window.decorations_action {
|
||||
Some(DecorationsAction::Hide) => frame.set_decorate(false),
|
||||
|
@ -726,51 +761,23 @@ impl<T> EventLoop<T> {
|
|||
// mutter (GNOME Wayland) relies on `set_geometry` to reposition window in case
|
||||
// it overlaps mutter's `bounding box`, so we can't avoid this resize call,
|
||||
// which calls `set_geometry` under the hood, for now.
|
||||
let (w, h) = logical_size;
|
||||
frame.resize(w, h);
|
||||
frame.refresh();
|
||||
|
||||
// Don't send resize event downstream if the new size is identical to the
|
||||
// current one.
|
||||
if (w, h) != *window.size {
|
||||
let logical_size = crate::dpi::LogicalSize::new(w as f64, h as f64);
|
||||
let physical_size = logical_size
|
||||
.to_physical(window.new_dpi.unwrap_or(window.prev_dpi) as f64);
|
||||
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Resized(physical_size),
|
||||
});
|
||||
*window.size = (w, h);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(dpi) = window.new_dpi {
|
||||
// Update cursor scale factor
|
||||
{
|
||||
self.cursor_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.update_scale_factor(dpi as u32);
|
||||
};
|
||||
let dpi = dpi as f64;
|
||||
let logical_size = LogicalSize::<f64>::from(*window.size);
|
||||
let mut new_inner_size = logical_size.to_physical(dpi);
|
||||
|
||||
// Don't send resize event downstream if the new logical size and scale is identical to the
|
||||
// current one
|
||||
if logical_size != old_logical_size || window.new_scale_factor.is_some() {
|
||||
let physical_size = LogicalSize::<f64>::from(logical_size).to_physical(
|
||||
window.new_scale_factor.unwrap_or(window.prev_scale_factor) as f64,
|
||||
);
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor: dpi,
|
||||
new_inner_size: &mut new_inner_size,
|
||||
},
|
||||
event: WindowEvent::Resized(physical_size),
|
||||
});
|
||||
|
||||
let (w, h) = new_inner_size.to_logical::<u32>(dpi).into();
|
||||
frame.resize(w, h);
|
||||
// Refresh frame to rescale decorations
|
||||
frame.refresh();
|
||||
*window.size = (w, h);
|
||||
}
|
||||
}
|
||||
|
||||
if window.closed {
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
|
|
|
@ -59,15 +59,20 @@ impl Window {
|
|||
// Create the surface first to get initial DPI
|
||||
let window_store = evlp.store.clone();
|
||||
let cursor_manager = evlp.cursor_manager.clone();
|
||||
let surface = evlp.env.create_surface(move |dpi, surface| {
|
||||
window_store.lock().unwrap().dpi_change(&surface, dpi);
|
||||
surface.set_buffer_scale(dpi);
|
||||
let surface = evlp.env.create_surface(move |scale_factor, surface| {
|
||||
window_store
|
||||
.lock()
|
||||
.unwrap()
|
||||
.scale_factor_change(&surface, scale_factor);
|
||||
surface.set_buffer_scale(scale_factor);
|
||||
});
|
||||
|
||||
let dpi = get_dpi_factor(&surface) as f64;
|
||||
// Always 1.
|
||||
let scale_factor = get_dpi_factor(&surface);
|
||||
|
||||
let (width, height) = attributes
|
||||
.inner_size
|
||||
.map(|size| size.to_logical::<f64>(dpi).into())
|
||||
.map(|size| size.to_logical::<f64>(scale_factor as f64).into())
|
||||
.unwrap_or((800, 600));
|
||||
|
||||
// Create the window
|
||||
|
@ -91,7 +96,7 @@ impl Window {
|
|||
|
||||
for window in &mut store.windows {
|
||||
if window.surface.as_ref().equals(&my_surface.as_ref()) {
|
||||
window.newsize = new_size;
|
||||
window.new_size = new_size;
|
||||
*(window.need_refresh.lock().unwrap()) = true;
|
||||
{
|
||||
// Get whether we're in fullscreen
|
||||
|
@ -173,12 +178,12 @@ impl Window {
|
|||
frame.set_min_size(
|
||||
attributes
|
||||
.min_inner_size
|
||||
.map(|size| size.to_logical::<f64>(dpi).into()),
|
||||
.map(|size| size.to_logical::<f64>(scale_factor as f64).into()),
|
||||
);
|
||||
frame.set_max_size(
|
||||
attributes
|
||||
.max_inner_size
|
||||
.map(|size| size.to_logical::<f64>(dpi).into()),
|
||||
.map(|size| size.to_logical::<f64>(scale_factor as f64).into()),
|
||||
);
|
||||
|
||||
let kill_switch = Arc::new(Mutex::new(false));
|
||||
|
@ -189,7 +194,7 @@ impl Window {
|
|||
|
||||
evlp.store.lock().unwrap().windows.push(InternalWindow {
|
||||
closed: false,
|
||||
newsize: None,
|
||||
new_size: None,
|
||||
size: size.clone(),
|
||||
need_refresh: need_refresh.clone(),
|
||||
fullscreen: fullscreen.clone(),
|
||||
|
@ -198,8 +203,8 @@ impl Window {
|
|||
surface: surface.clone(),
|
||||
kill_switch: kill_switch.clone(),
|
||||
frame: Arc::downgrade(&frame),
|
||||
current_dpi: 1,
|
||||
new_dpi: None,
|
||||
current_scale_factor: scale_factor,
|
||||
new_scale_factor: None,
|
||||
decorated: decorated.clone(),
|
||||
pending_decorations_action: pending_decorations_action.clone(),
|
||||
});
|
||||
|
@ -250,9 +255,9 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
||||
let dpi = self.scale_factor() as f64;
|
||||
let scale_factor = self.scale_factor() as f64;
|
||||
let size = LogicalSize::<f64>::from(*self.size.lock().unwrap());
|
||||
size.to_physical(dpi)
|
||||
size.to_physical(scale_factor)
|
||||
}
|
||||
|
||||
pub fn request_redraw(&self) {
|
||||
|
@ -261,38 +266,38 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn outer_size(&self) -> PhysicalSize<u32> {
|
||||
let dpi = self.scale_factor() as f64;
|
||||
let scale_factor = self.scale_factor() as f64;
|
||||
let (w, h) = self.size.lock().unwrap().clone();
|
||||
// let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
|
||||
let size = LogicalSize::<f64>::from((w, h));
|
||||
size.to_physical(dpi)
|
||||
size.to_physical(scale_factor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
// NOTE: This will only resize the borders, the contents must be updated by the user
|
||||
pub fn set_inner_size(&self, size: Size) {
|
||||
let dpi = self.scale_factor() as f64;
|
||||
let (w, h) = size.to_logical::<u32>(dpi).into();
|
||||
let scale_factor = self.scale_factor() as f64;
|
||||
let (w, h) = size.to_logical::<u32>(scale_factor).into();
|
||||
self.frame.lock().unwrap().resize(w, h);
|
||||
*(self.size.lock().unwrap()) = (w, h);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
||||
let dpi = self.scale_factor() as f64;
|
||||
let scale_factor = self.scale_factor() as f64;
|
||||
self.frame
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_min_size(dimensions.map(|dim| dim.to_logical::<f64>(dpi).into()));
|
||||
.set_min_size(dimensions.map(|dim| dim.to_logical::<f64>(scale_factor).into()));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
||||
let dpi = self.scale_factor() as f64;
|
||||
let scale_factor = self.scale_factor() as f64;
|
||||
self.frame
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_max_size(dimensions.map(|dim| dim.to_logical::<f64>(dpi).into()));
|
||||
.set_max_size(dimensions.map(|dim| dim.to_logical::<f64>(scale_factor).into()));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -428,7 +433,7 @@ impl Drop for Window {
|
|||
struct InternalWindow {
|
||||
surface: wl_surface::WlSurface,
|
||||
// TODO: CONVERT TO LogicalSize<u32>s
|
||||
newsize: Option<(u32, u32)>,
|
||||
new_size: Option<(u32, u32)>,
|
||||
size: Arc<Mutex<(u32, u32)>>,
|
||||
need_refresh: Arc<Mutex<bool>>,
|
||||
fullscreen: Arc<Mutex<bool>>,
|
||||
|
@ -437,8 +442,8 @@ struct InternalWindow {
|
|||
closed: bool,
|
||||
kill_switch: Arc<Mutex<bool>>,
|
||||
frame: Weak<Mutex<SWindow<ConceptFrame>>>,
|
||||
current_dpi: i32,
|
||||
new_dpi: Option<i32>,
|
||||
current_scale_factor: i32,
|
||||
new_scale_factor: Option<i32>,
|
||||
decorated: Arc<Mutex<bool>>,
|
||||
pending_decorations_action: Arc<Mutex<Option<DecorationsAction>>>,
|
||||
}
|
||||
|
@ -448,10 +453,10 @@ pub struct WindowStore {
|
|||
}
|
||||
|
||||
pub struct WindowStoreForEach<'a> {
|
||||
pub newsize: Option<(u32, u32)>,
|
||||
pub size: &'a mut (u32, u32),
|
||||
pub prev_dpi: i32,
|
||||
pub new_dpi: Option<i32>,
|
||||
pub new_size: Option<(u32, u32)>,
|
||||
pub size: &'a Mutex<(u32, u32)>,
|
||||
pub prev_scale_factor: i32,
|
||||
pub new_scale_factor: Option<i32>,
|
||||
pub closed: bool,
|
||||
pub grab_cursor: Option<bool>,
|
||||
pub surface: &'a wl_surface::WlSurface,
|
||||
|
@ -499,10 +504,11 @@ impl WindowStore {
|
|||
}
|
||||
}
|
||||
|
||||
fn dpi_change(&mut self, surface: &wl_surface::WlSurface, new: i32) {
|
||||
fn scale_factor_change(&mut self, surface: &wl_surface::WlSurface, new: i32) {
|
||||
for window in &mut self.windows {
|
||||
if surface.as_ref().equals(&window.surface.as_ref()) {
|
||||
window.new_dpi = Some(new);
|
||||
window.new_scale_factor = Some(new);
|
||||
*(window.need_refresh.lock().unwrap()) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -512,15 +518,18 @@ impl WindowStore {
|
|||
F: FnMut(WindowStoreForEach<'_>),
|
||||
{
|
||||
for window in &mut self.windows {
|
||||
let prev_scale_factor = window.current_scale_factor;
|
||||
if let Some(scale_factor) = window.new_scale_factor {
|
||||
window.current_scale_factor = scale_factor;
|
||||
}
|
||||
let opt_arc = window.frame.upgrade();
|
||||
let mut opt_mutex_lock = opt_arc.as_ref().map(|m| m.lock().unwrap());
|
||||
let mut size = { *window.size.lock().unwrap() };
|
||||
let decorations_action = { window.pending_decorations_action.lock().unwrap().take() };
|
||||
f(WindowStoreForEach {
|
||||
newsize: window.newsize.take(),
|
||||
size: &mut size,
|
||||
prev_dpi: window.current_dpi,
|
||||
new_dpi: window.new_dpi,
|
||||
new_size: window.new_size.take(),
|
||||
size: &window.size,
|
||||
prev_scale_factor,
|
||||
new_scale_factor: window.new_scale_factor.take(),
|
||||
closed: window.closed,
|
||||
grab_cursor: window.cursor_grab_changed.lock().unwrap().take(),
|
||||
surface: &window.surface,
|
||||
|
@ -528,10 +537,6 @@ impl WindowStore {
|
|||
frame: opt_mutex_lock.as_mut().map(|m| &mut **m),
|
||||
decorations_action,
|
||||
});
|
||||
*window.size.lock().unwrap() = size;
|
||||
if let Some(dpi) = window.new_dpi.take() {
|
||||
window.current_dpi = dpi;
|
||||
}
|
||||
// avoid re-spamming the event
|
||||
window.closed = false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue