Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wayland: rework scale factor handling #1538

Merged
merged 7 commits into from
Apr 22, 2020
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
85 changes: 46 additions & 39 deletions src/platform_impl/linux/wayland/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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,
Expand Down
83 changes: 44 additions & 39 deletions src/platform_impl/linux/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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));
Expand All @@ -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(),
Expand All @@ -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(),
});
Expand Down Expand Up @@ -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) {
Expand All @@ -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]
Expand Down Expand Up @@ -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>>,
Expand All @@ -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>>>,
}
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
}
}
Expand All @@ -512,26 +518,25 @@ 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,
wid: make_wid(&window.surface),
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;
}
Expand Down