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| {
|
window_target.store.lock().unwrap().for_each(|window| {
|
||||||
let window_id =
|
let window_id =
|
||||||
crate::window::WindowId(crate::platform_impl::WindowId::Wayland(window.wid));
|
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
|
// Update decorations state
|
||||||
match window.decorations_action {
|
match window.decorations_action {
|
||||||
Some(DecorationsAction::Hide) => frame.set_decorate(false),
|
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
|
// 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,
|
// it overlaps mutter's `bounding box`, so we can't avoid this resize call,
|
||||||
// which calls `set_geometry` under the hood, for now.
|
// which calls `set_geometry` under the hood, for now.
|
||||||
|
let (w, h) = logical_size;
|
||||||
frame.resize(w, h);
|
frame.resize(w, h);
|
||||||
frame.refresh();
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Don't send resize event downstream if the new logical size and scale is identical to the
|
||||||
if let Some(dpi) = window.new_dpi {
|
// current one
|
||||||
// Update cursor scale factor
|
if logical_size != old_logical_size || window.new_scale_factor.is_some() {
|
||||||
{
|
let physical_size = LogicalSize::<f64>::from(logical_size).to_physical(
|
||||||
self.cursor_manager
|
window.new_scale_factor.unwrap_or(window.prev_scale_factor) as f64,
|
||||||
.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);
|
|
||||||
|
|
||||||
callback(Event::WindowEvent {
|
callback(Event::WindowEvent {
|
||||||
window_id,
|
window_id,
|
||||||
event: WindowEvent::ScaleFactorChanged {
|
event: WindowEvent::Resized(physical_size),
|
||||||
scale_factor: dpi,
|
|
||||||
new_inner_size: &mut new_inner_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 {
|
if window.closed {
|
||||||
callback(Event::WindowEvent {
|
callback(Event::WindowEvent {
|
||||||
window_id,
|
window_id,
|
||||||
|
|
|
@ -59,15 +59,20 @@ impl Window {
|
||||||
// Create the surface first to get initial DPI
|
// Create the surface first to get initial DPI
|
||||||
let window_store = evlp.store.clone();
|
let window_store = evlp.store.clone();
|
||||||
let cursor_manager = evlp.cursor_manager.clone();
|
let cursor_manager = evlp.cursor_manager.clone();
|
||||||
let surface = evlp.env.create_surface(move |dpi, surface| {
|
let surface = evlp.env.create_surface(move |scale_factor, surface| {
|
||||||
window_store.lock().unwrap().dpi_change(&surface, dpi);
|
window_store
|
||||||
surface.set_buffer_scale(dpi);
|
.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
|
let (width, height) = attributes
|
||||||
.inner_size
|
.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));
|
.unwrap_or((800, 600));
|
||||||
|
|
||||||
// Create the window
|
// Create the window
|
||||||
|
@ -91,7 +96,7 @@ impl Window {
|
||||||
|
|
||||||
for window in &mut store.windows {
|
for window in &mut store.windows {
|
||||||
if window.surface.as_ref().equals(&my_surface.as_ref()) {
|
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;
|
*(window.need_refresh.lock().unwrap()) = true;
|
||||||
{
|
{
|
||||||
// Get whether we're in fullscreen
|
// Get whether we're in fullscreen
|
||||||
|
@ -173,12 +178,12 @@ impl Window {
|
||||||
frame.set_min_size(
|
frame.set_min_size(
|
||||||
attributes
|
attributes
|
||||||
.min_inner_size
|
.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(
|
frame.set_max_size(
|
||||||
attributes
|
attributes
|
||||||
.max_inner_size
|
.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));
|
let kill_switch = Arc::new(Mutex::new(false));
|
||||||
|
@ -189,7 +194,7 @@ impl Window {
|
||||||
|
|
||||||
evlp.store.lock().unwrap().windows.push(InternalWindow {
|
evlp.store.lock().unwrap().windows.push(InternalWindow {
|
||||||
closed: false,
|
closed: false,
|
||||||
newsize: None,
|
new_size: None,
|
||||||
size: size.clone(),
|
size: size.clone(),
|
||||||
need_refresh: need_refresh.clone(),
|
need_refresh: need_refresh.clone(),
|
||||||
fullscreen: fullscreen.clone(),
|
fullscreen: fullscreen.clone(),
|
||||||
|
@ -198,8 +203,8 @@ impl Window {
|
||||||
surface: surface.clone(),
|
surface: surface.clone(),
|
||||||
kill_switch: kill_switch.clone(),
|
kill_switch: kill_switch.clone(),
|
||||||
frame: Arc::downgrade(&frame),
|
frame: Arc::downgrade(&frame),
|
||||||
current_dpi: 1,
|
current_scale_factor: scale_factor,
|
||||||
new_dpi: None,
|
new_scale_factor: None,
|
||||||
decorated: decorated.clone(),
|
decorated: decorated.clone(),
|
||||||
pending_decorations_action: pending_decorations_action.clone(),
|
pending_decorations_action: pending_decorations_action.clone(),
|
||||||
});
|
});
|
||||||
|
@ -250,9 +255,9 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
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());
|
let size = LogicalSize::<f64>::from(*self.size.lock().unwrap());
|
||||||
size.to_physical(dpi)
|
size.to_physical(scale_factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_redraw(&self) {
|
pub fn request_redraw(&self) {
|
||||||
|
@ -261,38 +266,38 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn outer_size(&self) -> PhysicalSize<u32> {
|
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) = self.size.lock().unwrap().clone();
|
||||||
// let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
|
// let (w, h) = super::wayland_window::add_borders(w as i32, h as i32);
|
||||||
let size = LogicalSize::<f64>::from((w, h));
|
let size = LogicalSize::<f64>::from((w, h));
|
||||||
size.to_physical(dpi)
|
size.to_physical(scale_factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
// NOTE: This will only resize the borders, the contents must be updated by the user
|
// NOTE: This will only resize the borders, the contents must be updated by the user
|
||||||
pub fn set_inner_size(&self, size: Size) {
|
pub fn set_inner_size(&self, size: Size) {
|
||||||
let dpi = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor() as f64;
|
||||||
let (w, h) = size.to_logical::<u32>(dpi).into();
|
let (w, h) = size.to_logical::<u32>(scale_factor).into();
|
||||||
self.frame.lock().unwrap().resize(w, h);
|
self.frame.lock().unwrap().resize(w, h);
|
||||||
*(self.size.lock().unwrap()) = (w, h);
|
*(self.size.lock().unwrap()) = (w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
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
|
self.frame
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.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]
|
#[inline]
|
||||||
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
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
|
self.frame
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.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]
|
#[inline]
|
||||||
|
@ -428,7 +433,7 @@ impl Drop for Window {
|
||||||
struct InternalWindow {
|
struct InternalWindow {
|
||||||
surface: wl_surface::WlSurface,
|
surface: wl_surface::WlSurface,
|
||||||
// TODO: CONVERT TO LogicalSize<u32>s
|
// TODO: CONVERT TO LogicalSize<u32>s
|
||||||
newsize: Option<(u32, u32)>,
|
new_size: Option<(u32, u32)>,
|
||||||
size: Arc<Mutex<(u32, u32)>>,
|
size: Arc<Mutex<(u32, u32)>>,
|
||||||
need_refresh: Arc<Mutex<bool>>,
|
need_refresh: Arc<Mutex<bool>>,
|
||||||
fullscreen: Arc<Mutex<bool>>,
|
fullscreen: Arc<Mutex<bool>>,
|
||||||
|
@ -437,8 +442,8 @@ struct InternalWindow {
|
||||||
closed: bool,
|
closed: bool,
|
||||||
kill_switch: Arc<Mutex<bool>>,
|
kill_switch: Arc<Mutex<bool>>,
|
||||||
frame: Weak<Mutex<SWindow<ConceptFrame>>>,
|
frame: Weak<Mutex<SWindow<ConceptFrame>>>,
|
||||||
current_dpi: i32,
|
current_scale_factor: i32,
|
||||||
new_dpi: Option<i32>,
|
new_scale_factor: Option<i32>,
|
||||||
decorated: Arc<Mutex<bool>>,
|
decorated: Arc<Mutex<bool>>,
|
||||||
pending_decorations_action: Arc<Mutex<Option<DecorationsAction>>>,
|
pending_decorations_action: Arc<Mutex<Option<DecorationsAction>>>,
|
||||||
}
|
}
|
||||||
|
@ -448,10 +453,10 @@ pub struct WindowStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WindowStoreForEach<'a> {
|
pub struct WindowStoreForEach<'a> {
|
||||||
pub newsize: Option<(u32, u32)>,
|
pub new_size: Option<(u32, u32)>,
|
||||||
pub size: &'a mut (u32, u32),
|
pub size: &'a Mutex<(u32, u32)>,
|
||||||
pub prev_dpi: i32,
|
pub prev_scale_factor: i32,
|
||||||
pub new_dpi: Option<i32>,
|
pub new_scale_factor: Option<i32>,
|
||||||
pub closed: bool,
|
pub closed: bool,
|
||||||
pub grab_cursor: Option<bool>,
|
pub grab_cursor: Option<bool>,
|
||||||
pub surface: &'a wl_surface::WlSurface,
|
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 {
|
for window in &mut self.windows {
|
||||||
if surface.as_ref().equals(&window.surface.as_ref()) {
|
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<'_>),
|
F: FnMut(WindowStoreForEach<'_>),
|
||||||
{
|
{
|
||||||
for window in &mut self.windows {
|
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 opt_arc = window.frame.upgrade();
|
||||||
let mut opt_mutex_lock = opt_arc.as_ref().map(|m| m.lock().unwrap());
|
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() };
|
let decorations_action = { window.pending_decorations_action.lock().unwrap().take() };
|
||||||
f(WindowStoreForEach {
|
f(WindowStoreForEach {
|
||||||
newsize: window.newsize.take(),
|
new_size: window.new_size.take(),
|
||||||
size: &mut size,
|
size: &window.size,
|
||||||
prev_dpi: window.current_dpi,
|
prev_scale_factor,
|
||||||
new_dpi: window.new_dpi,
|
new_scale_factor: window.new_scale_factor.take(),
|
||||||
closed: window.closed,
|
closed: window.closed,
|
||||||
grab_cursor: window.cursor_grab_changed.lock().unwrap().take(),
|
grab_cursor: window.cursor_grab_changed.lock().unwrap().take(),
|
||||||
surface: &window.surface,
|
surface: &window.surface,
|
||||||
|
@ -528,10 +537,6 @@ impl WindowStore {
|
||||||
frame: opt_mutex_lock.as_mut().map(|m| &mut **m),
|
frame: opt_mutex_lock.as_mut().map(|m| &mut **m),
|
||||||
decorations_action,
|
decorations_action,
|
||||||
});
|
});
|
||||||
*window.size.lock().unwrap() = size;
|
|
||||||
if let Some(dpi) = window.new_dpi.take() {
|
|
||||||
window.current_dpi = dpi;
|
|
||||||
}
|
|
||||||
// avoid re-spamming the event
|
// avoid re-spamming the event
|
||||||
window.closed = false;
|
window.closed = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue