Skip to content

Commit

Permalink
feat(wm): adapt to scaling and resolution changes
Browse files Browse the repository at this point in the history
This commit expands the reconcile_monitors fn to also update resolution
and work area sizes if they are different from what is stored in the
window manager state.

Another WindowManagerEvent has been added as a polling mechanism for
monitor-related changes (scaling, dpi, resolution etc.), and this will
now also trigger the reconcile_monitors fn in the existing event
pre-processing block.

resolve #36
  • Loading branch information
LGUG2Z committed Sep 16, 2021
1 parent b8a27a9 commit 5b923a1
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 10 deletions.
9 changes: 5 additions & 4 deletions komorebi/src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ use crate::workspace::Workspace;
pub struct Monitor {
#[getset(get_copy = "pub", set = "pub")]
id: isize,
monitor_size: Rect,
#[getset(get = "pub")]
#[getset(get = "pub", set = "pub")]
size: Rect,
#[getset(get = "pub", set = "pub")]
work_area_size: Rect,
workspaces: Ring<Workspace>,
#[serde(skip_serializing)]
Expand All @@ -30,13 +31,13 @@ pub struct Monitor {

impl_ring_elements!(Monitor, Workspace);

pub fn new(id: isize, monitor_size: Rect, work_area_size: Rect) -> Monitor {
pub fn new(id: isize, size: Rect, work_area_size: Rect) -> Monitor {
let mut workspaces = Ring::default();
workspaces.elements_mut().push_back(Workspace::default());

Monitor {
id,
monitor_size,
size,
work_area_size,
workspaces,
workspace_names: HashMap::default(),
Expand Down
5 changes: 3 additions & 2 deletions komorebi/src/process_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ impl WindowManager {

// Make sure we have the most recently focused monitor from any event
match event {
WindowManagerEvent::FocusChange(_, window)
WindowManagerEvent::MonitorPoll(_, window)
| WindowManagerEvent::FocusChange(_, window)
| WindowManagerEvent::Show(_, window)
| WindowManagerEvent::MoveResizeEnd(_, window) => {
self.reconcile_monitors()?;
Expand Down Expand Up @@ -284,7 +285,7 @@ impl WindowManager {
self.update_focused_workspace(false)?;
}
}
WindowManagerEvent::MouseCapture(..) => {}
WindowManagerEvent::MonitorPoll(..) | WindowManagerEvent::MouseCapture(..) => {}
};

// If we unmanaged a window, it shouldn't be immediately hidden behind managed windows
Expand Down
4 changes: 4 additions & 0 deletions komorebi/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ impl Window {

#[tracing::instrument(fields(exe, title))]
pub fn should_manage(self, event: Option<WindowManagerEvent>) -> Result<bool> {
if let Some(WindowManagerEvent::MonitorPoll(_, _)) = event {
return Ok(true);
}

if self.title().is_err() {
return Ok(false);
}
Expand Down
33 changes: 33 additions & 0 deletions komorebi/src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,39 @@ impl WindowManager {
// Remove any invalid monitors from our state
self.monitors_mut().retain(|m| !invalid.contains(&m.id()));

let invisible_borders = self.invisible_borders;

for monitor in self.monitors_mut() {
let mut should_update = false;
let reference = WindowsApi::monitor(monitor.id())?;
// TODO: If this is different, force a redraw

if reference.work_area_size() != monitor.work_area_size() {
monitor.set_work_area_size(Rect {
left: reference.work_area_size().left,
top: reference.work_area_size().top,
right: reference.work_area_size().right,
bottom: reference.work_area_size().bottom,
});

should_update = true;
}
if reference.size() != monitor.size() {
monitor.set_size(Rect {
left: reference.size().left,
top: reference.size().top,
right: reference.size().right,
bottom: reference.size().bottom,
});

should_update = true;
}

if should_update {
monitor.update_focused_workspace(&invisible_borders)?;
}
}

// Check for and add any new monitors that may have been plugged in
WindowsApi::load_monitor_information(&mut self.monitors)?;

Expand Down
20 changes: 20 additions & 0 deletions komorebi/src/window_manager_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum WindowManagerEvent {
Manage(Window),
Unmanage(Window),
Raise(Window),
MonitorPoll(WinEvent, Window),
}

impl Display for WindowManagerEvent {
Expand Down Expand Up @@ -64,6 +65,13 @@ impl Display for WindowManagerEvent {
WindowManagerEvent::Raise(window) => {
write!(f, "Raise (Window: {})", window)
}
WindowManagerEvent::MonitorPoll(winevent, window) => {
write!(
f,
"MonitorPoll (WinEvent: {}, Window: {})",
winevent, window
)
}
}
}
}
Expand All @@ -78,6 +86,7 @@ impl WindowManagerEvent {
| WindowManagerEvent::Show(_, window)
| WindowManagerEvent::MoveResizeEnd(_, window)
| WindowManagerEvent::MouseCapture(_, window)
| WindowManagerEvent::MonitorPoll(_, window)
| WindowManagerEvent::Raise(window)
| WindowManagerEvent::Manage(window)
| WindowManagerEvent::Unmanage(window) => window,
Expand Down Expand Up @@ -121,6 +130,17 @@ impl WindowManagerEvent {
None
}
}
WinEvent::ObjectCreate => {
if let Ok(title) = window.title() {
// Hidden COM support mechanism window that fires this event on both DPI/scaling
// changes and resolution changes, a good candidate for polling
if title == "OLEChannelWnd" {
return Option::from(Self::MonitorPoll(winevent, window));
}
}

None
}
_ => None,
}
}
Expand Down
6 changes: 3 additions & 3 deletions komorebi/src/windows_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,11 +560,11 @@ impl WindowsApi {
Ok(monitor_info)
}

pub fn monitor(hmonitor: HMONITOR) -> Result<Monitor> {
let monitor_info = Self::monitor_info_w(hmonitor)?;
pub fn monitor(hmonitor: isize) -> Result<Monitor> {
let monitor_info = Self::monitor_info_w(HMONITOR(hmonitor))?;

Ok(monitor::new(
hmonitor.0,
hmonitor,
monitor_info.rcMonitor.into(),
monitor_info.rcWork.into(),
))
Expand Down
2 changes: 1 addition & 1 deletion komorebi/src/windows_callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub extern "system" fn enum_display_monitor(
}
}

if let Ok(m) = WindowsApi::monitor(hmonitor) {
if let Ok(m) = WindowsApi::monitor(hmonitor.0) {
monitors.elements_mut().push_back(m);
}

Expand Down

0 comments on commit 5b923a1

Please sign in to comment.