Skip to content

Commit

Permalink
On Wayland, fix resize not propagating properly
Browse files Browse the repository at this point in the history
On Wayland window size and scaling are double buffered, so winit should
send redraw requested for a client on the next frame as well.
  • Loading branch information
kchibisov committed Feb 28, 2022
1 parent 7846e6a commit 78e5a39
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -21,6 +21,7 @@ And please only add new entries to the top of this list, right below the `# Unre
- **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods).
- **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods).
- **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods).
- On Wayland, fix resize and scale factor changes not being propagated properly.

# 0.26.1 (2022-01-05)

Expand Down
30 changes: 22 additions & 8 deletions src/platform_impl/linux/wayland/event_loop/mod.rs
Expand Up @@ -24,7 +24,7 @@ use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget
use super::env::{WindowingFeatures, WinitEnv};
use super::output::OutputManager;
use super::seat::SeatManager;
use super::window::shim::{self, WindowUpdate};
use super::window::shim::{self, WindowRequest, WindowUpdate};
use super::{DeviceId, WindowId};

mod proxy;
Expand Down Expand Up @@ -249,7 +249,8 @@ impl<T: 'static> EventLoop<T> {
}

// Process 'new' pending updates.
self.with_state(|state| {
self.with_window_target(|window_target| {
let state = window_target.state.get_mut();
window_updates.clear();
window_updates.extend(
state
Expand All @@ -261,7 +262,8 @@ impl<T: 'static> EventLoop<T> {

for (window_id, window_update) in window_updates.iter_mut() {
if let Some(scale_factor) = window_update.scale_factor.map(|f| f as f64) {
let mut physical_size = self.with_state(|state| {
let mut physical_size = self.with_window_target(|window_target| {
let state = window_target.state.get_mut();
let window_handle = state.window_map.get(window_id).unwrap();
let mut size = window_handle.size.lock().unwrap();

Expand Down Expand Up @@ -294,7 +296,8 @@ impl<T: 'static> EventLoop<T> {
}

if let Some(size) = window_update.size.take() {
let physical_size = self.with_state(|state| {
let physical_size = self.with_window_target(|window_target| {
let state = window_target.state.get_mut();
let window_handle = state.window_map.get_mut(window_id).unwrap();
let mut window_size = window_handle.size.lock().unwrap();

Expand All @@ -320,6 +323,15 @@ impl<T: 'static> EventLoop<T> {
// Mark that refresh isn't required, since we've done it right now.
window_update.refresh_frame = false;

// Queue request for redraw into the next iteration of the loop, since
// resize and scale factor changes are double buffered.
window_handle
.pending_window_requests
.lock()
.unwrap()
.push(WindowRequest::Redraw);
window_target.event_loop_awakener.ping();

physical_size
});

Expand Down Expand Up @@ -356,7 +368,8 @@ impl<T: 'static> EventLoop<T> {
// The purpose of the back buffer and that swap is to not hold borrow_mut when
// we're doing callback to the user, since we can double borrow if the user decides
// to create a window in one of those callbacks.
self.with_state(|state| {
self.with_window_target(|window_target| {
let state = window_target.state.get_mut();
std::mem::swap(
&mut event_sink_back_buffer,
&mut state.event_sink.window_events,
Expand All @@ -381,7 +394,8 @@ impl<T: 'static> EventLoop<T> {
for (window_id, window_update) in window_updates.iter() {
// Handle refresh of the frame.
if window_update.refresh_frame {
self.with_state(|state| {
self.with_window_target(|window_target| {
let state = window_target.state.get_mut();
let window_handle = state.window_map.get_mut(window_id).unwrap();
window_handle.window.refresh();
if !window_update.redraw_requested {
Expand Down Expand Up @@ -526,9 +540,9 @@ impl<T: 'static> EventLoop<T> {
&self.window_target
}

fn with_state<U, F: FnOnce(&mut WinitState) -> U>(&mut self, f: F) -> U {
fn with_window_target<U, F: FnOnce(&mut EventLoopWindowTarget<T>) -> U>(&mut self, f: F) -> U {
let state = match &mut self.window_target.p {
PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(),
PlatformEventLoopWindowTarget::Wayland(window_target) => window_target,
#[cfg(feature = "x11")]
_ => unreachable!(),
};
Expand Down

0 comments on commit 78e5a39

Please sign in to comment.