Skip to content

Commit

Permalink
fix(linux): fire resized & moved events on min/maximize, closes #219 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir authored Jan 4, 2022
1 parent a75716d commit 98321ae
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 35 deletions.
5 changes: 5 additions & 0 deletions .changes/linx-moved-resized-on-min-maximized.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

Fire `WindowEvent::Resized` and `WindowEvent::Moved` when window is min/maximized on Linux to align with Windows behavior.
82 changes: 64 additions & 18 deletions src/platform_impl/linux/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use gtk::{prelude::*, AboutDialog, ApplicationWindow, Inhibit};

use crate::{
accelerator::AcceleratorId,
dpi::{PhysicalPosition, PhysicalSize},
dpi::{LogicalPosition, LogicalSize},
event::{ElementState, Event, MouseButton, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
keyboard::ModifiersState,
Expand Down Expand Up @@ -294,6 +294,7 @@ impl<T: 'static> EventLoop<T> {
| EventMask::BUTTON1_MOTION_MASK
| EventMask::BUTTON_PRESS_MASK
| EventMask::TOUCH_MASK
| EventMask::STRUCTURE_MASK
| EventMask::FOCUS_CHANGE_MASK,
);

Expand Down Expand Up @@ -382,19 +383,25 @@ impl<T: 'static> EventLoop<T> {
});

let tx_clone = event_tx.clone();
window.connect_configure_event(move |_, event| {
window.connect_configure_event(move |window, event| {
let scale_factor = window.scale_factor();

let (x, y) = event.position();
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::Moved(PhysicalPosition::new(x, y)),
event: WindowEvent::Moved(
LogicalPosition::new(x, y).to_physical(scale_factor as f64),
),
}) {
log::warn!("Failed to send window moved event to event channel: {}", e);
}

let (w, h) = event.size();
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::Resized(PhysicalSize::new(w, h)),
event: WindowEvent::Resized(
LogicalSize::new(w, h).to_physical(scale_factor as f64),
),
}) {
log::warn!(
"Failed to send window resized event to event channel: {}",
Expand All @@ -405,7 +412,7 @@ impl<T: 'static> EventLoop<T> {
});

let tx_clone = event_tx.clone();
window.connect_focus_in_event(move |_window, _| {
window.connect_focus_in_event(move |_, _| {
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::Focused(true),
Expand All @@ -419,7 +426,7 @@ impl<T: 'static> EventLoop<T> {
});

let tx_clone = event_tx.clone();
window.connect_focus_out_event(move |_window, _| {
window.connect_focus_out_event(move |_, _| {
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::Focused(false),
Expand Down Expand Up @@ -463,18 +470,25 @@ impl<T: 'static> EventLoop<T> {
});

let tx_clone = event_tx.clone();
window.connect_motion_notify_event(move |_window, event| {
let (x, y) = event.position();
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
position: PhysicalPosition::new(x, y),
device_id: DEVICE_ID,
// this field is depracted so it is fine to pass empty state
modifiers: ModifiersState::empty(),
},
}) {
log::warn!("Failed to send cursor moved event to event channel: {}", e);
window.connect_motion_notify_event(move |window, _| {
let display = window.display();
if let Some(cursor) = display
.default_seat()
.and_then(|device_manager| device_manager.pointer())
{
let scale_factor = window.scale_factor();
let (_, x, y) = cursor.position();
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
position: LogicalPosition::new(x, y).to_physical(scale_factor as f64),
device_id: DEVICE_ID,
// this field is depracted so it is fine to pass empty state
modifiers: ModifiersState::empty(),
},
}) {
log::warn!("Failed to send cursor moved event to event channel: {}", e);
}
}
Inhibit(false)
});
Expand Down Expand Up @@ -617,6 +631,38 @@ impl<T: 'static> EventLoop<T> {
handler(event_key.to_owned(), ElementState::Released);
Inhibit(false)
});

let tx_clone = event_tx.clone();
window.connect_window_state_event(move |window, event| {
let state = event.changed_mask();
if state.contains(WindowState::ICONIFIED) || state.contains(WindowState::MAXIMIZED) {
let scale_factor = window.scale_factor();

let (x, y) = window.position();
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::Moved(
LogicalPosition::new(x, y).to_physical(scale_factor as f64),
),
}) {
log::warn!("Failed to send window moved event to event channel: {}", e);
}

let (w, h) = window.size();
if let Err(e) = tx_clone.send(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::Resized(
LogicalSize::new(w, h).to_physical(scale_factor as f64),
),
}) {
log::warn!(
"Failed to send window resized event to event channel: {}",
e
);
}
}
Inhibit(false)
});
}
WindowRequest::Redraw => {
if let Err(e) = draw_tx.send(id) {
Expand Down
8 changes: 5 additions & 3 deletions src/platform_impl/linux/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
dpi::{PhysicalPosition, PhysicalSize},
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize},
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
};

Expand All @@ -29,19 +29,21 @@ impl MonitorHandle {
#[inline]
pub fn size(&self) -> PhysicalSize<u32> {
let rect = self.monitor.geometry();
PhysicalSize {
LogicalSize {
width: rect.width as u32,
height: rect.height as u32,
}
.to_physical(self.scale_factor())
}

#[inline]
pub fn position(&self) -> PhysicalPosition<i32> {
let rect = self.monitor.geometry();
PhysicalPosition {
LogicalPosition {
x: rect.x,
y: rect.y,
}
.to_physical(self.scale_factor())
}

#[inline]
Expand Down
30 changes: 16 additions & 14 deletions src/platform_impl/linux/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use gdk_pixbuf::{Colorspace, Pixbuf};
use gtk::{prelude::*, AccelGroup, ApplicationWindow, Orientation};

use crate::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError as RootOsError},
icon::{BadIcon, Icon},
menu::{MenuId, MenuItem},
Expand Down Expand Up @@ -163,7 +163,7 @@ impl Window {

// Set Position
if let Some(position) = attributes.position {
let (x, y): (i32, i32) = position.to_physical::<i32>(win_scale_factor as f64).into();
let (x, y): (i32, i32) = position.to_logical::<i32>(win_scale_factor as f64).into();
window.move_(x, y);
}

Expand Down Expand Up @@ -246,7 +246,7 @@ impl Window {
let minimized = Rc::new(AtomicBool::new(false));
let min_clone = minimized.clone();

window.connect_window_state_event(move |_window, event| {
window.connect_window_state_event(move |_, event| {
let state = event.new_window_state();
max_clone.store(state.contains(WindowState::MAXIMIZED), Ordering::Release);
min_clone.store(state.contains(WindowState::ICONIFIED), Ordering::Release);
Expand Down Expand Up @@ -305,24 +305,24 @@ impl Window {

pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
let (x, y) = &*self.position;
Ok(PhysicalPosition::new(
x.load(Ordering::Acquire),
y.load(Ordering::Acquire),
))
Ok(
LogicalPosition::new(x.load(Ordering::Acquire), y.load(Ordering::Acquire))
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64),
)
}

pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
let (x, y) = &*self.position;
Ok(PhysicalPosition::new(
x.load(Ordering::Acquire),
y.load(Ordering::Acquire),
))
Ok(
LogicalPosition::new(x.load(Ordering::Acquire), y.load(Ordering::Acquire))
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64),
)
}

pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
let (x, y): (i32, i32) = position
.into()
.to_physical::<i32>(self.scale_factor())
.to_logical::<i32>(self.scale_factor())
.into();

if let Err(e) = self
Expand All @@ -336,10 +336,11 @@ impl Window {
pub fn inner_size(&self) -> PhysicalSize<u32> {
let (width, height) = &*self.size;

PhysicalSize::new(
LogicalSize::new(
width.load(Ordering::Acquire) as u32,
height.load(Ordering::Acquire) as u32,
)
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64)
}

pub fn set_inner_size<S: Into<Size>>(&self, size: S) {
Expand All @@ -356,10 +357,11 @@ impl Window {
pub fn outer_size(&self) -> PhysicalSize<u32> {
let (width, height) = &*self.size;

PhysicalSize::new(
LogicalSize::new(
width.load(Ordering::Acquire) as u32,
height.load(Ordering::Acquire) as u32,
)
.to_physical(self.scale_factor.load(Ordering::Acquire) as f64)
}

pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
Expand Down

0 comments on commit 98321ae

Please sign in to comment.