On X11, reload DPI on PropertyChange
Signed-off-by: John Nunley <dev@notgull.net> Fixes #1228.
This commit is contained in:
parent
81a1d9c396
commit
b3c87caa7c
3 changed files with 97 additions and 67 deletions
|
|
@ -570,6 +570,14 @@ impl<T: 'static> EventProcessor<T> {
|
|||
event: WindowEvent::Destroyed,
|
||||
});
|
||||
}
|
||||
ffi::PropertyNotify => {
|
||||
let xev: &ffi::XPropertyEvent = xev.as_ref();
|
||||
let atom = xev.atom as xproto::Atom;
|
||||
|
||||
if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER) {
|
||||
self.process_dpi_change(&mut callback);
|
||||
}
|
||||
}
|
||||
|
||||
ffi::VisibilityNotify => {
|
||||
let xev: &ffi::XVisibilityEvent = xev.as_ref();
|
||||
|
|
@ -1306,72 +1314,7 @@ impl<T: 'static> EventProcessor<T> {
|
|||
}
|
||||
}
|
||||
if event_type == self.randr_event_offset as c_int {
|
||||
// In the future, it would be quite easy to emit monitor hotplug events.
|
||||
let prev_list = wt.xconn.invalidate_cached_monitor_list();
|
||||
if let Some(prev_list) = prev_list {
|
||||
let new_list = wt
|
||||
.xconn
|
||||
.available_monitors()
|
||||
.expect("Failed to get monitor list");
|
||||
for new_monitor in new_list {
|
||||
// Previous list may be empty, in case of disconnecting and
|
||||
// reconnecting the only one monitor. We still need to emit events in
|
||||
// this case.
|
||||
let maybe_prev_scale_factor = prev_list
|
||||
.iter()
|
||||
.find(|prev_monitor| prev_monitor.name == new_monitor.name)
|
||||
.map(|prev_monitor| prev_monitor.scale_factor);
|
||||
if Some(new_monitor.scale_factor) != maybe_prev_scale_factor {
|
||||
for (window_id, window) in wt.windows.borrow().iter() {
|
||||
if let Some(window) = window.upgrade() {
|
||||
// Check if the window is on this monitor
|
||||
let monitor =
|
||||
window.shared_state_lock().last_monitor.clone();
|
||||
if monitor.name == new_monitor.name {
|
||||
let (width, height) = window.inner_size_physical();
|
||||
let (new_width, new_height) = window.adjust_for_dpi(
|
||||
// If we couldn't determine the previous scale
|
||||
// factor (e.g., because all monitors were closed
|
||||
// before), just pick whatever the current monitor
|
||||
// has set as a baseline.
|
||||
maybe_prev_scale_factor
|
||||
.unwrap_or(monitor.scale_factor),
|
||||
new_monitor.scale_factor,
|
||||
width,
|
||||
height,
|
||||
&window.shared_state_lock(),
|
||||
);
|
||||
|
||||
let window_id = crate::window::WindowId(*window_id);
|
||||
let old_inner_size = PhysicalSize::new(width, height);
|
||||
let inner_size = Arc::new(Mutex::new(
|
||||
PhysicalSize::new(new_width, new_height),
|
||||
));
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor: new_monitor.scale_factor,
|
||||
inner_size_writer: InnerSizeWriter::new(
|
||||
Arc::downgrade(&inner_size),
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
let new_inner_size = *inner_size.lock().unwrap();
|
||||
drop(inner_size);
|
||||
|
||||
if new_inner_size != old_inner_size {
|
||||
let (new_width, new_height) = new_inner_size.into();
|
||||
window.request_inner_size_physical(
|
||||
new_width, new_height,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.process_dpi_change(&mut callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1464,6 +1407,45 @@ impl<T: 'static> EventProcessor<T> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn process_dpi_change<F>(&self, callback: &mut F)
|
||||
where
|
||||
F: FnMut(Event<T>),
|
||||
{
|
||||
let wt = get_xtarget(&self.target);
|
||||
|
||||
// In the future, it would be quite easy to emit monitor hotplug events.
|
||||
let prev_list = {
|
||||
let prev_list = wt.xconn.invalidate_cached_monitor_list();
|
||||
match prev_list {
|
||||
Some(prev_list) => prev_list,
|
||||
None => return,
|
||||
}
|
||||
};
|
||||
|
||||
let new_list = wt
|
||||
.xconn
|
||||
.available_monitors()
|
||||
.expect("Failed to get monitor list");
|
||||
for new_monitor in new_list {
|
||||
// Previous list may be empty, in case of disconnecting and
|
||||
// reconnecting the only one monitor. We still need to emit events in
|
||||
// this case.
|
||||
let maybe_prev_scale_factor = prev_list
|
||||
.iter()
|
||||
.find(|prev_monitor| prev_monitor.name == new_monitor.name)
|
||||
.map(|prev_monitor| prev_monitor.scale_factor);
|
||||
if Some(new_monitor.scale_factor) != maybe_prev_scale_factor {
|
||||
for window in wt.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
|
||||
window.refresh_dpi_for_monitor(
|
||||
&new_monitor,
|
||||
maybe_prev_scale_factor,
|
||||
&mut *callback,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_first_touch(first: &mut Option<u64>, num: &mut u32, id: u64, phase: TouchPhase) -> bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue