mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-14 21:04:04 +01:00
refactor(kde): the Backend names windows and monitors with the shared ids
KDE's Backend took and returned bare u32 ids and answered
window_workspace and current_workspaces without a Result. The operations
that the shared trait has now use komorebi_backend's WindowId and
MonitorId, window_workspace and current_workspaces return its Result, and
the look/drag/wallpaper methods that only KDE has take the same id types.
So the Shared wrapper no longer converts ids or results: it is down to
the window info mapping.
The window manager core keeps its u32 ids (Window { id: u32 }); the
conversion is at the backend call (Window::window_id, From<WindowId> for
Window, WindowId::from_u32 / to_u32 at the remaining call sites). KWin's
table stays keyed by u32; an id too wide for a u32 is a window it never
had (WindowGone, or None for a query). Test call sites got .into() on the
ids and unwrap on the two results. No behaviour change.
Verified: KDE cargo test --workspace --no-fail-fast (unit, integration,
doc) 881 passed, 0 failed, native with FakeBackend. Not run: KDE VM
suites.
This commit is contained in:
1 parent
06ce5adfe8
commit
c08ee2cfae
17 files changed
+459
-306
No files matched your search
@@ -18,7 +18,7 @@
|
||||
//! fake.open_window(1, "foot", "foot", "a terminal");
|
||||
//!
|
||||
//! let tile = Rect { left: 0, top: 0, right: 960, bottom: 1050 };
|
||||
//! fake.set_rect(1, &tile)?;
|
||||
//! fake.set_rect(1.into(), &tile)?;
|
||||
//!
|
||||
//! assert_eq!(fake.rect_of(1), Some(tile));
|
||||
//! assert_eq!(fake.commands(), [Command::SetRect(1, tile)]);
|
||||
@@ -406,12 +406,12 @@ impl Backend for FakeBackend {
|
||||
self.inner.windows().into_iter().map(window_info).collect()
|
||||
}
|
||||
|
||||
fn window(&self, id: u32) -> Option<WindowInfo> {
|
||||
self.inner.window(wid(id)).map(window_info)
|
||||
fn window(&self, id: WindowId) -> Option<WindowInfo> {
|
||||
self.inner.window(id).map(window_info)
|
||||
}
|
||||
|
||||
fn foreground_window(&self) -> Option<u32> {
|
||||
self.inner.foreground_window().map(raw)
|
||||
fn foreground_window(&self) -> Option<WindowId> {
|
||||
self.inner.foreground_window()
|
||||
}
|
||||
|
||||
fn monitors(&self) -> shared::Result<Vec<MonitorInfo>> {
|
||||
@@ -433,41 +433,40 @@ impl Backend for FakeBackend {
|
||||
self.inner.cursor_pos()
|
||||
}
|
||||
|
||||
fn drag_end(&self, id: u32) -> Option<Rect> {
|
||||
self.kde.lock().drag_ends.get(&id).copied()
|
||||
fn drag_end(&self, id: WindowId) -> Option<Rect> {
|
||||
self.kde.lock().drag_ends.get(&raw(id)).copied()
|
||||
}
|
||||
|
||||
fn set_rect(&self, id: u32, rect: &Rect) -> shared::Result<()> {
|
||||
self.inner.set_rect(wid(id), rect)
|
||||
fn set_rect(&self, id: WindowId, rect: &Rect) -> shared::Result<()> {
|
||||
self.inner.set_rect(id, rect)
|
||||
}
|
||||
|
||||
fn focus(&self, id: u32, mouse_follows_focus: bool) -> shared::Result<()> {
|
||||
self.inner
|
||||
.focus(wid(id), mouse_follows_focus)
|
||||
fn focus(&self, id: WindowId, mouse_follows_focus: bool) -> shared::Result<()> {
|
||||
self.inner.focus(id, mouse_follows_focus)
|
||||
}
|
||||
|
||||
fn raise(&self, id: u32) -> shared::Result<()> {
|
||||
self.inner.raise(wid(id))
|
||||
fn raise(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.inner.raise(id)
|
||||
}
|
||||
|
||||
fn hide(&self, id: u32) -> shared::Result<()> {
|
||||
self.inner.hide(wid(id))
|
||||
fn hide(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.inner.hide(id)
|
||||
}
|
||||
|
||||
fn restore(&self, id: u32) -> shared::Result<()> {
|
||||
self.inner.restore(wid(id))
|
||||
fn restore(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.inner.restore(id)
|
||||
}
|
||||
|
||||
fn minimize(&self, id: u32) -> shared::Result<()> {
|
||||
self.inner.minimize(wid(id))
|
||||
fn minimize(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.inner.minimize(id)
|
||||
}
|
||||
|
||||
fn unminimize(&self, id: u32) -> shared::Result<()> {
|
||||
self.inner.unminimize(wid(id))
|
||||
fn unminimize(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.inner.unminimize(id)
|
||||
}
|
||||
|
||||
fn close(&self, id: u32) -> shared::Result<()> {
|
||||
self.inner.close(wid(id))
|
||||
fn close(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.inner.close(id)
|
||||
}
|
||||
|
||||
fn center_cursor_in(&self, rect: &Rect) -> shared::Result<()> {
|
||||
@@ -478,31 +477,24 @@ impl Backend for FakeBackend {
|
||||
self.inner.ensure_workspaces(names)
|
||||
}
|
||||
|
||||
fn switch_workspace(&self, monitor_id: u32, idx: usize) -> shared::Result<()> {
|
||||
self.inner
|
||||
.switch_workspace(MonitorId::from_u32(monitor_id), idx)
|
||||
fn switch_workspace(&self, monitor_id: MonitorId, idx: usize) -> shared::Result<()> {
|
||||
self.inner.switch_workspace(monitor_id, idx)
|
||||
}
|
||||
|
||||
fn set_window_workspace(&self, id: u32, idx: usize) -> shared::Result<()> {
|
||||
self.inner
|
||||
.set_window_workspace(wid(id), idx)
|
||||
fn set_window_workspace(&self, id: WindowId, idx: usize) -> shared::Result<()> {
|
||||
self.inner.set_window_workspace(id, idx)
|
||||
}
|
||||
|
||||
fn window_workspace(&self, id: u32) -> Option<usize> {
|
||||
self.inner.window_workspace(wid(id)).ok().flatten()
|
||||
fn window_workspace(&self, id: WindowId) -> komorebi_backend::Result<Option<usize>> {
|
||||
self.inner.window_workspace(id)
|
||||
}
|
||||
|
||||
fn current_workspaces(&self) -> Vec<(u32, usize)> {
|
||||
self.inner
|
||||
.current_workspaces()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|(monitor, idx)| (raw_monitor(monitor), idx))
|
||||
.collect()
|
||||
fn current_workspaces(&self) -> shared::Result<Vec<(MonitorId, usize)>> {
|
||||
self.inner.current_workspaces()
|
||||
}
|
||||
|
||||
fn maximize(&self, id: u32, maximize: bool) -> shared::Result<()> {
|
||||
self.inner.maximize(wid(id), maximize)
|
||||
fn maximize(&self, id: WindowId, maximize: bool) -> shared::Result<()> {
|
||||
self.inner.maximize(id, maximize)
|
||||
}
|
||||
|
||||
fn apply_look(&self, look: &Look) -> eyre::Result<bool> {
|
||||
@@ -519,18 +511,20 @@ impl Backend for FakeBackend {
|
||||
self.inner.set_focus_follows_mouse(enable)
|
||||
}
|
||||
|
||||
fn set_wallpaper(&self, monitor_id: u32, path: &Path) -> eyre::Result<()> {
|
||||
fn set_wallpaper(&self, monitor_id: MonitorId, path: &Path) -> eyre::Result<()> {
|
||||
self.kde
|
||||
.lock()
|
||||
.wallpapers
|
||||
.insert(monitor_id, path.to_path_buf());
|
||||
self.inner
|
||||
.record_ext(KdeCommand::SetWallpaper(monitor_id, path.to_path_buf()));
|
||||
.insert(raw_monitor(monitor_id), path.to_path_buf());
|
||||
self.inner.record_ext(KdeCommand::SetWallpaper(
|
||||
raw_monitor(monitor_id),
|
||||
path.to_path_buf(),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_opacity(&self, id: u32, alpha: u8) -> shared::Result<()> {
|
||||
self.inner.set_opacity(wid(id), alpha)
|
||||
fn set_opacity(&self, id: WindowId, alpha: u8) -> shared::Result<()> {
|
||||
self.inner.set_opacity(id, alpha)
|
||||
}
|
||||
|
||||
fn set_border_colours(&self, colours: &[(u32, u32)]) -> eyre::Result<bool> {
|
||||
@@ -571,7 +565,7 @@ mod tests {
|
||||
fn a_window_asked_to_move_is_where_it_was_asked() -> eyre::Result<()> {
|
||||
let fake = fake_with(&[1]);
|
||||
|
||||
fake.set_rect(1, &tile(10, 500))?;
|
||||
fake.set_rect(1.into(), &tile(10, 500))?;
|
||||
|
||||
assert_eq!(fake.rect_of(1), Some(tile(10, 500)));
|
||||
Ok(())
|
||||
@@ -582,7 +576,7 @@ mod tests {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.set_min_size(1, 600, 400);
|
||||
|
||||
fake.set_rect(1, &tile(0, 300))?;
|
||||
fake.set_rect(1.into(), &tile(0, 300))?;
|
||||
|
||||
let rect = fake.rect_of(1).expect("window 1 was opened");
|
||||
assert_eq!((rect.right, rect.bottom), (600, 1050));
|
||||
@@ -593,11 +587,11 @@ mod tests {
|
||||
fn every_command_is_recorded_in_order() -> eyre::Result<()> {
|
||||
let fake = fake_with(&[1, 2]);
|
||||
|
||||
fake.focus(1, false)?;
|
||||
fake.raise(2)?;
|
||||
fake.minimize(1)?;
|
||||
fake.unminimize(1)?;
|
||||
fake.close(2)?;
|
||||
fake.focus(1.into(), false)?;
|
||||
fake.raise(2.into())?;
|
||||
fake.minimize(1.into())?;
|
||||
fake.unminimize(1.into())?;
|
||||
fake.close(2.into())?;
|
||||
|
||||
assert_eq!(
|
||||
fake.commands(),
|
||||
@@ -617,16 +611,16 @@ mod tests {
|
||||
#[test]
|
||||
fn a_maximized_window_has_the_work_area_and_gets_its_frame_back() -> eyre::Result<()> {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.set_rect(1, &tile(100, 200))?;
|
||||
fake.set_rect(1.into(), &tile(100, 200))?;
|
||||
|
||||
fake.maximize(1, true)?;
|
||||
fake.maximize(1.into(), true)?;
|
||||
// a second maximize does not make the maximized frame the one to give back
|
||||
fake.maximize(1, true)?;
|
||||
fake.maximize(1.into(), true)?;
|
||||
|
||||
assert!(fake.is_maximized(1));
|
||||
assert_eq!(fake.rect_of(1), Some(tile(0, 1920)));
|
||||
|
||||
fake.maximize(1, false)?;
|
||||
fake.maximize(1.into(), false)?;
|
||||
|
||||
assert!(!fake.is_maximized(1));
|
||||
assert_eq!(fake.rect_of(1), Some(tile(100, 200)));
|
||||
@@ -645,32 +639,45 @@ mod tests {
|
||||
#[test]
|
||||
fn a_window_the_user_maximizes_is_maximized_and_no_command_is_recorded() {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.set_rect(1, &tile(100, 200)).unwrap();
|
||||
fake.set_rect(1.into(), &tile(100, 200)).unwrap();
|
||||
fake.clear_commands();
|
||||
|
||||
fake.user_maximize(1, true);
|
||||
|
||||
assert!(fake.is_maximized(1));
|
||||
assert!(fake.window(1).expect("window 1 was opened").maximized);
|
||||
assert!(
|
||||
fake.window(1.into())
|
||||
.expect("window 1 was opened")
|
||||
.maximized
|
||||
);
|
||||
assert!(fake.windows()[0].maximized);
|
||||
assert_eq!(fake.rect_of(1), Some(tile(0, 1920)));
|
||||
assert!(fake.commands().is_empty());
|
||||
|
||||
fake.user_maximize(1, false);
|
||||
|
||||
assert!(!fake.window(1).expect("window 1 was opened").maximized);
|
||||
assert!(
|
||||
!fake
|
||||
.window(1.into())
|
||||
.expect("window 1 was opened")
|
||||
.maximized
|
||||
);
|
||||
assert_eq!(fake.rect_of(1), Some(tile(100, 200)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_fullscreen_window_covers_its_monitor_and_gets_its_frame_back() {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.set_rect(1, &tile(100, 200)).unwrap();
|
||||
fake.set_rect(1.into(), &tile(100, 200)).unwrap();
|
||||
fake.clear_commands();
|
||||
|
||||
fake.set_fullscreen(1, true);
|
||||
|
||||
assert!(fake.window(1).expect("window 1 was opened").fullscreen);
|
||||
assert!(
|
||||
fake.window(1.into())
|
||||
.expect("window 1 was opened")
|
||||
.fullscreen
|
||||
);
|
||||
assert!(fake.windows()[0].fullscreen);
|
||||
assert_eq!(
|
||||
fake.rect_of(1),
|
||||
@@ -686,7 +693,12 @@ mod tests {
|
||||
|
||||
fake.set_fullscreen(1, false);
|
||||
|
||||
assert!(!fake.window(1).expect("window 1 was opened").fullscreen);
|
||||
assert!(
|
||||
!fake
|
||||
.window(1.into())
|
||||
.expect("window 1 was opened")
|
||||
.fullscreen
|
||||
);
|
||||
assert_eq!(fake.rect_of(1), Some(tile(100, 200)));
|
||||
}
|
||||
|
||||
@@ -694,7 +706,9 @@ mod tests {
|
||||
fn a_command_about_a_window_nobody_opened_is_an_error() {
|
||||
let fake = fake_with(&[1]);
|
||||
|
||||
let error = fake.focus(9, false).expect_err("window 9 does not exist");
|
||||
let error = fake
|
||||
.focus(9.into(), false)
|
||||
.expect_err("window 9 does not exist");
|
||||
|
||||
assert_eq!(error.to_string(), "no such window: 9");
|
||||
}
|
||||
@@ -704,17 +718,20 @@ mod tests {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.close_window_now(1);
|
||||
|
||||
assert!(fake.raise(1).is_err());
|
||||
assert!(fake.raise(1.into()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_permissive_fake_creates_the_windows_it_is_asked_about() -> eyre::Result<()> {
|
||||
let fake = FakeBackend::permissive();
|
||||
|
||||
fake.focus(77, false)?;
|
||||
fake.focus(77.into(), false)?;
|
||||
|
||||
assert!(fake.is_window(77));
|
||||
assert_eq!(fake.foreground_window(), Some(77));
|
||||
assert!(fake.is_window(77.into()));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(77)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -722,9 +739,9 @@ mod tests {
|
||||
fn focusing_with_the_mouse_following_puts_the_pointer_in_the_middle_of_the_window()
|
||||
-> eyre::Result<()> {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.set_rect(1, &tile(100, 200))?;
|
||||
fake.set_rect(1.into(), &tile(100, 200))?;
|
||||
|
||||
fake.focus(1, true)?;
|
||||
fake.focus(1.into(), true)?;
|
||||
|
||||
assert_eq!(fake.cursor_pos(), Some((200, 525)));
|
||||
Ok(())
|
||||
@@ -735,7 +752,7 @@ mod tests {
|
||||
let fake = fake_with(&[1]);
|
||||
fake.set_cursor(5, 5);
|
||||
|
||||
fake.focus(1, false)?;
|
||||
fake.focus(1.into(), false)?;
|
||||
|
||||
assert_eq!(fake.cursor_pos(), Some((5, 5)));
|
||||
Ok(())
|
||||
@@ -761,7 +778,7 @@ mod tests {
|
||||
|
||||
assert!(fake.commands().is_empty());
|
||||
assert_eq!(fake.rect_of(1), Some(tile(300, 300)));
|
||||
let window = fake.window(1).expect("window 1 was opened");
|
||||
let window = fake.window(1.into()).expect("window 1 was opened");
|
||||
assert_eq!(window.title, "renamed");
|
||||
assert!(!window.normal);
|
||||
}
|
||||
@@ -784,22 +801,25 @@ mod tests {
|
||||
fake.open_window(1, "foot", "foot", "window 1");
|
||||
|
||||
assert_eq!(fake.workspace_of(1), Some(2));
|
||||
assert_eq!(fake.window_workspace(1), Some(2));
|
||||
assert_eq!(fake.window_workspace(1.into()).unwrap(), Some(2));
|
||||
assert!(fake.on_screen(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_monitor_shows_the_windows_of_its_workspace_and_no_others() -> eyre::Result<()> {
|
||||
let fake = fake_with(&[1, 2]);
|
||||
fake.set_window_workspace(2, 1)?;
|
||||
fake.set_window_workspace(2.into(), 1)?;
|
||||
|
||||
assert!(fake.on_screen(1) && !fake.on_screen(2));
|
||||
|
||||
fake.switch_workspace(1, 1)?;
|
||||
fake.switch_workspace(1.into(), 1)?;
|
||||
|
||||
assert!(!fake.on_screen(1) && fake.on_screen(2));
|
||||
assert_eq!(fake.shown_workspace(1), 1);
|
||||
assert_eq!(fake.current_workspaces(), [(1, 1)]);
|
||||
assert_eq!(
|
||||
fake.current_workspaces().unwrap(),
|
||||
[(MonitorId::from_u32(1), 1)]
|
||||
);
|
||||
assert_eq!(
|
||||
fake.commands(),
|
||||
[
|
||||
@@ -816,7 +836,10 @@ mod tests {
|
||||
|
||||
fake.show_workspace_by_user(1, 3);
|
||||
|
||||
assert_eq!(fake.current_workspaces(), [(1, 3)]);
|
||||
assert_eq!(
|
||||
fake.current_workspaces().unwrap(),
|
||||
[(MonitorId::from_u32(1), 3)]
|
||||
);
|
||||
assert!(fake.commands().is_empty());
|
||||
}
|
||||
|
||||
@@ -824,7 +847,7 @@ mod tests {
|
||||
fn a_minimized_window_or_one_that_closed_is_not_on_screen() -> eyre::Result<()> {
|
||||
let fake = fake_with(&[1, 2]);
|
||||
|
||||
fake.minimize(1)?;
|
||||
fake.minimize(1.into())?;
|
||||
fake.close_window_now(2);
|
||||
|
||||
assert!(!fake.on_screen(1) && !fake.on_screen(2));
|
||||
@@ -835,14 +858,17 @@ mod tests {
|
||||
fn a_hidden_window_is_out_of_sight_on_its_workspace_until_it_is_restored() -> eyre::Result<()> {
|
||||
let fake = fake_with(&[1]);
|
||||
|
||||
fake.hide(1)?;
|
||||
fake.hide(1)?;
|
||||
fake.hide(1.into())?;
|
||||
fake.hide(1.into())?;
|
||||
|
||||
assert!(fake.is_hidden(1) && !fake.on_screen(1));
|
||||
assert_eq!(fake.window_workspace(1), Some(0));
|
||||
assert!(fake.window(1).is_some_and(|w| w.alive && !w.minimized));
|
||||
assert_eq!(fake.window_workspace(1.into()).unwrap(), Some(0));
|
||||
assert!(
|
||||
fake.window(1.into())
|
||||
.is_some_and(|w| w.alive && !w.minimized)
|
||||
);
|
||||
|
||||
fake.restore(1)?;
|
||||
fake.restore(1.into())?;
|
||||
|
||||
assert!(!fake.is_hidden(1) && fake.on_screen(1));
|
||||
assert_eq!(
|
||||
@@ -856,15 +882,15 @@ mod tests {
|
||||
fn hiding_or_restoring_a_window_nobody_opened_is_an_error() {
|
||||
let fake = fake_with(&[1]);
|
||||
|
||||
assert!(fake.hide(9).is_err());
|
||||
assert!(fake.restore(9).is_err());
|
||||
assert!(fake.hide(9.into()).is_err());
|
||||
assert!(fake.restore(9.into()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn putting_a_window_nobody_opened_on_a_workspace_is_an_error() {
|
||||
let fake = fake_with(&[1]);
|
||||
|
||||
assert!(fake.set_window_workspace(9, 1).is_err());
|
||||
assert!(fake.set_window_workspace(9.into(), 1).is_err());
|
||||
assert_eq!(fake.workspace_of(9), None);
|
||||
}
|
||||
|
||||
@@ -926,11 +952,11 @@ mod tests {
|
||||
let fake = fake_with(&[1]);
|
||||
assert_eq!(fake.opacity_of(1), 255);
|
||||
|
||||
fake.set_opacity(1, 100)?;
|
||||
fake.set_opacity(1.into(), 100)?;
|
||||
|
||||
assert_eq!(fake.opacity_of(1), 100);
|
||||
assert_eq!(fake.commands(), [Command::SetOpacity(1, 100)]);
|
||||
assert!(fake.set_opacity(9, 100).is_err());
|
||||
assert!(fake.set_opacity(9.into(), 100).is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -939,7 +965,7 @@ mod tests {
|
||||
let fake = fake_with(&[1]);
|
||||
|
||||
fake.apply_look(&Look::default())?;
|
||||
fake.focus(1, false)?;
|
||||
fake.focus(1.into(), false)?;
|
||||
fake.set_border_colours(&[(1, 0xFF0000)])?;
|
||||
|
||||
assert_eq!(fake.commands().len(), 3);
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
|
||||
use crate::core::Rect;
|
||||
use color_eyre::eyre;
|
||||
use komorebi_backend::MonitorId;
|
||||
use komorebi_backend::WindowId;
|
||||
use parking_lot::RwLock;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
@@ -212,28 +214,29 @@ pub struct BorderLook {
|
||||
/// # use color_eyre::eyre;
|
||||
/// # use komorebi::backend::{Backend, MonitorInfo, WindowInfo};
|
||||
/// # use komorebi::core::Rect;
|
||||
/// # use komorebi_backend::{MonitorId, WindowId};
|
||||
/// struct NotShareable(Rc<u8>);
|
||||
///
|
||||
/// # impl Backend for NotShareable {
|
||||
/// # fn windows(&self) -> Vec<WindowInfo> { vec![] }
|
||||
/// # fn window(&self, _: u32) -> Option<WindowInfo> { None }
|
||||
/// # fn foreground_window(&self) -> Option<u32> { None }
|
||||
/// # fn window(&self, _: WindowId) -> Option<WindowInfo> { None }
|
||||
/// # fn foreground_window(&self) -> Option<WindowId> { None }
|
||||
/// # fn monitors(&self) -> komorebi_backend::Result<Vec<MonitorInfo>> { Ok(vec![]) }
|
||||
/// # fn cursor_pos(&self) -> Option<(i32, i32)> { None }
|
||||
/// # fn set_rect(&self, _: u32, _: &Rect) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn focus(&self, _: u32, _: bool) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn raise(&self, _: u32) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn hide(&self, _: u32) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn restore(&self, _: u32) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn minimize(&self, _: u32) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn unminimize(&self, _: u32) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn close(&self, _: u32) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn set_rect(&self, _: WindowId, _: &Rect) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn focus(&self, _: WindowId, _: bool) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn raise(&self, _: WindowId) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn hide(&self, _: WindowId) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn restore(&self, _: WindowId) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn minimize(&self, _: WindowId) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn unminimize(&self, _: WindowId) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn close(&self, _: WindowId) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn center_cursor_in(&self, _: &Rect) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn ensure_workspaces(&self, _: &[String]) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn switch_workspace(&self, _: u32, _: usize) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn set_window_workspace(&self, _: u32, _: usize) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn window_workspace(&self, _: u32) -> Option<usize> { None }
|
||||
/// # fn current_workspaces(&self) -> Vec<(u32, usize)> { vec![] }
|
||||
/// # fn switch_workspace(&self, _: MonitorId, _: usize) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn set_window_workspace(&self, _: WindowId, _: usize) -> komorebi_backend::Result<()> { Ok(()) }
|
||||
/// # fn window_workspace(&self, _: WindowId) -> komorebi_backend::Result<Option<usize>> { Ok(None) }
|
||||
/// # fn current_workspaces(&self) -> komorebi_backend::Result<Vec<(MonitorId, usize)>> { Ok(vec![]) }
|
||||
/// # }
|
||||
/// ```
|
||||
pub trait Backend: Send + Sync + 'static {
|
||||
@@ -243,10 +246,10 @@ pub trait Backend: Send + Sync + 'static {
|
||||
fn windows(&self) -> Vec<WindowInfo>;
|
||||
|
||||
/// Returns what is known about the window, or `None` if the compositor has never heard of it.
|
||||
fn window(&self, id: u32) -> Option<WindowInfo>;
|
||||
fn window(&self, id: WindowId) -> Option<WindowInfo>;
|
||||
|
||||
/// Returns the id of the window that has the focus, if any window does.
|
||||
fn foreground_window(&self) -> Option<u32>;
|
||||
fn foreground_window(&self) -> Option<WindowId>;
|
||||
|
||||
/// Returns every connected monitor.
|
||||
///
|
||||
@@ -276,9 +279,9 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// let fake = FakeBackend::with_one_monitor();
|
||||
/// fake.open_window(1, "foot", "foot", "a terminal");
|
||||
///
|
||||
/// assert_eq!(fake.drag_origin(1), None);
|
||||
/// assert_eq!(fake.drag_origin(1.into()), None);
|
||||
/// ```
|
||||
fn drag_origin(&self, _id: u32) -> Option<Rect> {
|
||||
fn drag_origin(&self, _id: WindowId) -> Option<Rect> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -303,13 +306,13 @@ pub trait Backend: Send + Sync + 'static {
|
||||
///
|
||||
/// let fake = FakeBackend::with_one_monitor();
|
||||
/// fake.open_window(1, "foot", "foot", "a terminal");
|
||||
/// assert_eq!(fake.drag_end(1), None);
|
||||
/// assert_eq!(fake.drag_end(1.into()), None);
|
||||
///
|
||||
/// let asked = Rect { left: 0, top: 0, right: 672, bottom: 704 };
|
||||
/// fake.set_drag_end(1, asked);
|
||||
/// assert_eq!(fake.drag_end(1), Some(asked));
|
||||
/// assert_eq!(fake.drag_end(1.into()), Some(asked));
|
||||
/// ```
|
||||
fn drag_end(&self, _id: u32) -> Option<Rect> {
|
||||
fn drag_end(&self, _id: WindowId) -> Option<Rect> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -323,21 +326,21 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn set_rect(&self, id: u32, rect: &Rect) -> komorebi_backend::Result<()>;
|
||||
fn set_rect(&self, id: WindowId, rect: &Rect) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Gives the window the focus, and, if `mouse_follows_focus`, puts the pointer in its middle.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn focus(&self, id: u32, mouse_follows_focus: bool) -> komorebi_backend::Result<()>;
|
||||
fn focus(&self, id: WindowId, mouse_follows_focus: bool) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Raises the window above the others.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn raise(&self, id: u32) -> komorebi_backend::Result<()>;
|
||||
fn raise(&self, id: WindowId) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Takes the window out of sight without closing or minimizing it, which is how the window
|
||||
/// manager keeps the back of a stack out of the way. On KWin it goes to a virtual desktop that
|
||||
@@ -351,7 +354,7 @@ pub trait Backend: Send + Sync + 'static {
|
||||
///
|
||||
/// When the window does not exist or is no longer alive, or the compositor cannot make the
|
||||
/// place the window is hidden in.
|
||||
fn hide(&self, id: u32) -> komorebi_backend::Result<()>;
|
||||
fn hide(&self, id: WindowId) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Brings a hidden window back, to the workspace it is on. A window that is not hidden is left
|
||||
/// as it is.
|
||||
@@ -359,28 +362,28 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn restore(&self, id: u32) -> komorebi_backend::Result<()>;
|
||||
fn restore(&self, id: WindowId) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Minimizes the window.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn minimize(&self, id: u32) -> komorebi_backend::Result<()>;
|
||||
fn minimize(&self, id: WindowId) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Brings a minimized window back.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn unminimize(&self, id: u32) -> komorebi_backend::Result<()>;
|
||||
fn unminimize(&self, id: WindowId) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Asks the window to close.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn close(&self, id: u32) -> komorebi_backend::Result<()>;
|
||||
fn close(&self, id: WindowId) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Puts the pointer in the middle of `rect`.
|
||||
///
|
||||
@@ -416,21 +419,21 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// # Errors
|
||||
///
|
||||
/// When there is no desktop for `idx` and one cannot be made.
|
||||
fn switch_workspace(&self, monitor_id: u32, idx: usize) -> komorebi_backend::Result<()>;
|
||||
fn switch_workspace(&self, monitor_id: MonitorId, idx: usize) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Puts a window on workspace `idx`. It is visible at once to [`Backend::window_workspace`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist, or there is no desktop for `idx` and one cannot be made.
|
||||
fn set_window_workspace(&self, id: u32, idx: usize) -> komorebi_backend::Result<()>;
|
||||
fn set_window_workspace(&self, id: WindowId, idx: usize) -> komorebi_backend::Result<()>;
|
||||
|
||||
/// Returns the workspace a window is on, or `None` for a window the compositor does not know or
|
||||
/// that is on every workspace.
|
||||
fn window_workspace(&self, id: u32) -> Option<usize>;
|
||||
fn window_workspace(&self, id: WindowId) -> komorebi_backend::Result<Option<usize>>;
|
||||
|
||||
/// Returns the workspace each monitor shows, as `(monitor id, workspace index)`.
|
||||
fn current_workspaces(&self) -> Vec<(u32, usize)>;
|
||||
fn current_workspaces(&self) -> komorebi_backend::Result<Vec<(MonitorId, usize)>>;
|
||||
|
||||
// ---- look, which a backend that draws nothing need not say anything about --------------------
|
||||
|
||||
@@ -523,11 +526,11 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// fake.open_window(7, "foot", "foot", "a terminal");
|
||||
/// assert_eq!(fake.opacity_of(7), 255);
|
||||
///
|
||||
/// fake.set_opacity(7, 150)?;
|
||||
/// fake.set_opacity(7.into(), 150)?;
|
||||
/// assert_eq!(fake.opacity_of(7), 150);
|
||||
/// # Ok::<(), color_eyre::eyre::Report>(())
|
||||
/// ```
|
||||
fn set_opacity(&self, _id: u32, _alpha: u8) -> komorebi_backend::Result<()> {
|
||||
fn set_opacity(&self, _id: WindowId, _alpha: u8) -> komorebi_backend::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -576,7 +579,7 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// let fake = FakeBackend::with_one_monitor();
|
||||
/// assert_eq!(fake.wallpaper_of(1), None);
|
||||
///
|
||||
/// fake.set_wallpaper(1, Path::new("/pictures/dunes.png"))?;
|
||||
/// fake.set_wallpaper(1.into(), Path::new("/pictures/dunes.png"))?;
|
||||
/// assert_eq!(fake.wallpaper_of(1), Some("/pictures/dunes.png".into()));
|
||||
/// assert_eq!(
|
||||
/// fake.commands(),
|
||||
@@ -584,7 +587,7 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// );
|
||||
/// # Ok::<(), color_eyre::eyre::Report>(())
|
||||
/// ```
|
||||
fn set_wallpaper(&self, _monitor_id: u32, _path: &Path) -> eyre::Result<()> {
|
||||
fn set_wallpaper(&self, _monitor_id: MonitorId, _path: &Path) -> eyre::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -605,26 +608,26 @@ pub trait Backend: Send + Sync + 'static {
|
||||
/// # Errors
|
||||
///
|
||||
/// When the window does not exist or is no longer alive.
|
||||
fn maximize(&self, _id: u32, _maximize: bool) -> komorebi_backend::Result<()> {
|
||||
fn maximize(&self, _id: WindowId, _maximize: bool) -> komorebi_backend::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns true if and only if the compositor has a live window with this id.
|
||||
fn is_window(&self, id: u32) -> bool {
|
||||
fn is_window(&self, id: WindowId) -> bool {
|
||||
self.window(id).is_some_and(|w| w.alive)
|
||||
}
|
||||
|
||||
/// Returns the window's frame, if the compositor knows the window.
|
||||
fn window_rect(&self, id: u32) -> Option<Rect> {
|
||||
fn window_rect(&self, id: WindowId) -> Option<Rect> {
|
||||
self.window(id).map(|w| w.rect)
|
||||
}
|
||||
|
||||
/// Returns the id of the monitor whose bounds contain the point.
|
||||
fn monitor_from_point(&self, x: i32, y: i32) -> Option<u32> {
|
||||
fn monitor_from_point(&self, x: i32, y: i32) -> Option<MonitorId> {
|
||||
self.monitors().ok()?.into_iter().find_map(|m| {
|
||||
let (l, t) = (m.size.left, m.size.top);
|
||||
let (r, b) = (l + m.size.right, t + m.size.bottom);
|
||||
(x >= l && x < r && y >= t && y < b).then_some(m.id)
|
||||
(x >= l && x < r && y >= t && y < b).then_some(MonitorId::from_u32(m.id))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -716,7 +719,7 @@ mod tests {
|
||||
fn a_thread_that_installs_nothing_gets_a_permissive_fake_in_unit_tests() {
|
||||
let id = 41;
|
||||
|
||||
assert!(backend().window(id).is_some());
|
||||
assert!(backend().window(id.into()).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -728,12 +731,12 @@ mod tests {
|
||||
|
||||
with_backend(outer, || {
|
||||
with_backend(inner, || {
|
||||
assert!(backend().is_window(2));
|
||||
assert!(!backend().is_window(1));
|
||||
assert!(backend().is_window(2.into()));
|
||||
assert!(!backend().is_window(1.into()));
|
||||
});
|
||||
|
||||
assert!(backend().is_window(1));
|
||||
assert!(!backend().is_window(2));
|
||||
assert!(backend().is_window(1.into()));
|
||||
assert!(!backend().is_window(2.into()));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -749,7 +752,7 @@ mod tests {
|
||||
}));
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(backend().is_window(1));
|
||||
assert!(backend().is_window(1.into()));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -758,10 +761,10 @@ mod tests {
|
||||
let fake = FakeBackend::with_one_monitor();
|
||||
fake.open_window(5, "foot", "foot", "a terminal");
|
||||
|
||||
assert!(fake.is_window(5));
|
||||
assert!(!fake.is_window(6));
|
||||
assert_eq!(fake.window_rect(5), fake.rect_of(5));
|
||||
assert_eq!(fake.monitor_from_point(10, 10), Some(1));
|
||||
assert!(fake.is_window(5.into()));
|
||||
assert!(!fake.is_window(6.into()));
|
||||
assert_eq!(fake.window_rect(5.into()), fake.rect_of(5));
|
||||
assert_eq!(fake.monitor_from_point(10, 10), Some(1.into()));
|
||||
assert_eq!(fake.monitor_from_point(5000, 10), None);
|
||||
}
|
||||
|
||||
@@ -772,8 +775,8 @@ mod tests {
|
||||
|
||||
fake.close_window_now(5);
|
||||
|
||||
assert!(!fake.is_window(5));
|
||||
assert!(fake.window(5).is_some_and(|w| !w.alive));
|
||||
assert!(!fake.is_window(5.into()));
|
||||
assert!(fake.window(5.into()).is_some_and(|w| !w.alive));
|
||||
assert!(fake.windows().is_empty());
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
use super::Backend;
|
||||
use komorebi_backend as shared;
|
||||
use komorebi_backend::Capability;
|
||||
use komorebi_backend::Error;
|
||||
use komorebi_backend::MonitorId;
|
||||
use komorebi_backend::Rect;
|
||||
use komorebi_backend::WindowId;
|
||||
@@ -34,18 +33,6 @@ impl<B: Backend + ?Sized> Shared<B> {
|
||||
pub fn kde(&self) -> &B {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Runs a window command through KDE's trait; an id too wide for KDE is a window it never had.
|
||||
fn window_command(
|
||||
&self,
|
||||
id: WindowId,
|
||||
command: impl FnOnce(&B, u32) -> shared::Result<()>,
|
||||
) -> shared::Result<()> {
|
||||
let Some(raw) = id.to_u32() else {
|
||||
return Err(Error::WindowGone(id));
|
||||
};
|
||||
command(&self.0, raw)
|
||||
}
|
||||
}
|
||||
|
||||
fn window_info(info: super::WindowInfo) -> shared::WindowInfo {
|
||||
@@ -71,11 +58,11 @@ impl<B: Backend + ?Sized> shared::Backend for Shared<B> {
|
||||
}
|
||||
|
||||
fn window(&self, id: WindowId) -> Option<shared::WindowInfo> {
|
||||
self.0.window(id.to_u32()?).map(window_info)
|
||||
self.0.window(id).map(window_info)
|
||||
}
|
||||
|
||||
fn foreground_window(&self) -> Option<WindowId> {
|
||||
self.0.foreground_window().map(WindowId::from_u32)
|
||||
self.0.foreground_window()
|
||||
}
|
||||
|
||||
fn monitors(&self) -> shared::Result<Vec<shared::MonitorInfo>> {
|
||||
@@ -98,35 +85,35 @@ impl<B: Backend + ?Sized> shared::Backend for Shared<B> {
|
||||
}
|
||||
|
||||
fn set_rect(&self, id: WindowId, rect: &Rect) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.set_rect(raw, rect))
|
||||
self.0.set_rect(id, rect)
|
||||
}
|
||||
|
||||
fn focus(&self, id: WindowId, mouse_follows_focus: bool) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.focus(raw, mouse_follows_focus))
|
||||
self.0.focus(id, mouse_follows_focus)
|
||||
}
|
||||
|
||||
fn raise(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.raise(raw))
|
||||
self.0.raise(id)
|
||||
}
|
||||
|
||||
fn hide(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.hide(raw))
|
||||
self.0.hide(id)
|
||||
}
|
||||
|
||||
fn restore(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.restore(raw))
|
||||
self.0.restore(id)
|
||||
}
|
||||
|
||||
fn minimize(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.minimize(raw))
|
||||
self.0.minimize(id)
|
||||
}
|
||||
|
||||
fn unminimize(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.unminimize(raw))
|
||||
self.0.unminimize(id)
|
||||
}
|
||||
|
||||
fn close(&self, id: WindowId) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.close(raw))
|
||||
self.0.close(id)
|
||||
}
|
||||
|
||||
fn center_cursor_in(&self, rect: &Rect) -> shared::Result<()> {
|
||||
@@ -138,11 +125,11 @@ impl<B: Backend + ?Sized> shared::Backend for Shared<B> {
|
||||
}
|
||||
|
||||
fn maximize(&self, id: WindowId, maximize: bool) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.maximize(raw, maximize))
|
||||
self.0.maximize(id, maximize)
|
||||
}
|
||||
|
||||
fn set_opacity(&self, id: WindowId, alpha: u8) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.set_opacity(raw, alpha))
|
||||
self.0.set_opacity(id, alpha)
|
||||
}
|
||||
|
||||
fn set_focus_follows_mouse(&self, enable: bool) -> shared::Result<()> {
|
||||
@@ -154,25 +141,19 @@ impl<B: Backend + ?Sized> shared::Backend for Shared<B> {
|
||||
}
|
||||
|
||||
fn switch_workspace(&self, monitor: MonitorId, idx: usize) -> shared::Result<()> {
|
||||
let id = monitor.to_u32().unwrap_or(u32::MAX);
|
||||
self.0.switch_workspace(id, idx)
|
||||
self.0.switch_workspace(monitor, idx)
|
||||
}
|
||||
|
||||
fn set_window_workspace(&self, id: WindowId, idx: usize) -> shared::Result<()> {
|
||||
self.window_command(id, |b, raw| b.set_window_workspace(raw, idx))
|
||||
self.0.set_window_workspace(id, idx)
|
||||
}
|
||||
|
||||
fn window_workspace(&self, id: WindowId) -> shared::Result<Option<usize>> {
|
||||
Ok(id.to_u32().and_then(|raw| self.0.window_workspace(raw)))
|
||||
self.0.window_workspace(id)
|
||||
}
|
||||
|
||||
fn current_workspaces(&self) -> shared::Result<Vec<(MonitorId, usize)>> {
|
||||
Ok(self
|
||||
.0
|
||||
.current_workspaces()
|
||||
.into_iter()
|
||||
.map(|(monitor, idx)| (MonitorId::from_u32(monitor), idx))
|
||||
.collect())
|
||||
self.0.current_workspaces()
|
||||
}
|
||||
|
||||
// `is_window`, `window_rect` and `monitor_from_point` are the provided ones, over `window` and
|
||||
@@ -185,6 +166,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::backend::fake::FakeBackend;
|
||||
use komorebi_backend::Backend as _;
|
||||
use komorebi_backend::Error;
|
||||
use komorebi_backend::contract::Harness;
|
||||
use komorebi_backend::contract::check_all;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ use crate::core::animation::AnimationStyle;
|
||||
use crate::core::animation::QtCurve;
|
||||
use crate::window_manager::WindowManager;
|
||||
use color_eyre::eyre;
|
||||
use komorebi_backend::WindowId;
|
||||
use komorebi_themes::colour::Colour;
|
||||
use komorebi_themes::colour::Rgb;
|
||||
use lazy_static::lazy_static;
|
||||
@@ -113,7 +114,7 @@ fn kind_colour(kind: WindowKind) -> u32 {
|
||||
pub fn window_kinds(wm: &WindowManager) -> Vec<(u32, WindowKind)> {
|
||||
let mut out = vec![];
|
||||
let focused_monitor_idx = wm.focused_monitor_idx();
|
||||
let foreground = backend().foreground_window();
|
||||
let foreground = backend().foreground_window().and_then(WindowId::to_u32);
|
||||
|
||||
let floating = |workspace: &crate::workspace::Workspace, out: &mut Vec<(u32, WindowKind)>| {
|
||||
for window in workspace.floating_windows() {
|
||||
|
||||
@@ -45,6 +45,8 @@ use crate::window::RuleDebug;
|
||||
use crate::window::Window;
|
||||
use crate::window_manager::WindowManager;
|
||||
use color_eyre::eyre;
|
||||
use komorebi_backend::MonitorId;
|
||||
use komorebi_backend::WindowId;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn contains_point(area: &Rect, x: i32, y: i32) -> bool {
|
||||
@@ -339,8 +341,12 @@ pub fn load_workspace_information(wm: &mut WindowManager) -> eyre::Result<()> {
|
||||
let mut valid_window_count = 0;
|
||||
|
||||
// each monitor starts out showing the workspace the compositor is showing on it
|
||||
for (monitor_id, idx) in backend().current_workspaces() {
|
||||
if let Some(monitor) = wm.monitors_mut().iter_mut().find(|m| m.id == monitor_id) {
|
||||
for (monitor_id, idx) in backend().current_workspaces().unwrap_or_default() {
|
||||
if let Some(monitor) = wm
|
||||
.monitors_mut()
|
||||
.iter_mut()
|
||||
.find(|m| MonitorId::from_u32(m.id) == monitor_id)
|
||||
{
|
||||
monitor.focus_workspace(idx)?;
|
||||
}
|
||||
}
|
||||
@@ -374,7 +380,9 @@ pub fn load_workspace_information(wm: &mut WindowManager) -> eyre::Result<()> {
|
||||
continue;
|
||||
};
|
||||
let workspace_idx = backend()
|
||||
.window_workspace(info.id)
|
||||
.window_workspace(WindowId::from_u32(info.id))
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or_else(|| monitor.focused_workspace_idx());
|
||||
monitor.ensure_workspace_count(workspace_idx + 1);
|
||||
|
||||
|
||||
@@ -101,6 +101,8 @@ use crate::window_manager_event_listener;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::OptionExt;
|
||||
use futures_util::StreamExt;
|
||||
use komorebi_backend::MonitorId;
|
||||
use komorebi_backend::WindowId;
|
||||
use parking_lot::Condvar;
|
||||
use parking_lot::Mutex;
|
||||
use serde_json::Value;
|
||||
@@ -788,6 +790,11 @@ fn platform(report: eyre::Report) -> komorebi_backend::Error {
|
||||
komorebi_backend::Error::Platform(report.into())
|
||||
}
|
||||
|
||||
/// The compositor's number for a window id, which is always one that was made from a `u32`
|
||||
fn raw(id: komorebi_backend::WindowId) -> komorebi_backend::Result<u32> {
|
||||
id.to_u32().ok_or(komorebi_backend::Error::WindowGone(id))
|
||||
}
|
||||
|
||||
fn command_rect(uuid: &str, rect: &Rect) -> Value {
|
||||
json!({ "op": "geo", "id": uuid, "x": rect.left, "y": rect.top, "w": rect.right, "h": rect.bottom })
|
||||
}
|
||||
@@ -810,11 +817,7 @@ impl KWinBackend {
|
||||
))
|
||||
}
|
||||
|
||||
fn command(
|
||||
&self,
|
||||
id: u32,
|
||||
build: impl FnOnce(&str) -> Value,
|
||||
) -> komorebi_backend::Result<()> {
|
||||
fn command(&self, id: u32, build: impl FnOnce(&str) -> Value) -> komorebi_backend::Result<()> {
|
||||
let uuid = self.uuid_of(id)?;
|
||||
self.shared.push(build(&uuid));
|
||||
Ok(())
|
||||
@@ -826,19 +829,26 @@ impl Backend for KWinBackend {
|
||||
self.shared.table.lock().windows()
|
||||
}
|
||||
|
||||
fn window(&self, id: u32) -> Option<WindowInfo> {
|
||||
fn window(&self, id: WindowId) -> Option<WindowInfo> {
|
||||
let id = id.to_u32()?;
|
||||
self.shared.table.lock().window(id)
|
||||
}
|
||||
|
||||
fn foreground_window(&self) -> Option<u32> {
|
||||
self.shared.table.lock().foreground()
|
||||
fn foreground_window(&self) -> Option<WindowId> {
|
||||
self.shared
|
||||
.table
|
||||
.lock()
|
||||
.foreground()
|
||||
.map(WindowId::from_u32)
|
||||
}
|
||||
|
||||
fn drag_origin(&self, id: u32) -> Option<Rect> {
|
||||
fn drag_origin(&self, id: WindowId) -> Option<Rect> {
|
||||
let id = id.to_u32()?;
|
||||
self.shared.table.lock().drag_origin(id)
|
||||
}
|
||||
|
||||
fn drag_end(&self, id: u32) -> Option<Rect> {
|
||||
fn drag_end(&self, id: WindowId) -> Option<Rect> {
|
||||
let id = id.to_u32()?;
|
||||
self.shared.table.lock().drag_end(id)
|
||||
}
|
||||
|
||||
@@ -864,14 +874,16 @@ impl Backend for KWinBackend {
|
||||
answer.or_else(|| self.shared.table.lock().cursor())
|
||||
}
|
||||
|
||||
fn set_rect(&self, id: u32, rect: &Rect) -> komorebi_backend::Result<()> {
|
||||
fn set_rect(&self, id: WindowId, rect: &Rect) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
tracing::debug!("asking for window {id} to be at {rect:?}");
|
||||
self.command(id, |uuid| command_rect(uuid, rect))?;
|
||||
self.shared.table.lock().note_requested_rect(id, *rect);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn focus(&self, id: u32, mouse_follows_focus: bool) -> komorebi_backend::Result<()> {
|
||||
fn focus(&self, id: WindowId, mouse_follows_focus: bool) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(id, |uuid| json!({ "op": "activate", "id": uuid }))?;
|
||||
|
||||
if mouse_follows_focus {
|
||||
@@ -894,11 +906,13 @@ impl Backend for KWinBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn raise(&self, id: u32) -> komorebi_backend::Result<()> {
|
||||
fn raise(&self, id: WindowId) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(id, |uuid| json!({ "op": "raise", "id": uuid }))
|
||||
}
|
||||
|
||||
fn hide(&self, id: u32) -> komorebi_backend::Result<()> {
|
||||
fn hide(&self, id: WindowId) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.uuid_of(id)?;
|
||||
|
||||
let commands = loop {
|
||||
@@ -923,7 +937,8 @@ impl Backend for KWinBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn restore(&self, id: u32) -> komorebi_backend::Result<()> {
|
||||
fn restore(&self, id: WindowId) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.uuid_of(id)?;
|
||||
|
||||
let commands = self.shared.table.lock().restore_commands(id);
|
||||
@@ -942,9 +957,13 @@ impl Backend for KWinBackend {
|
||||
.map_err(platform)
|
||||
}
|
||||
|
||||
fn switch_workspace(&self, monitor_id: u32, idx: usize) -> komorebi_backend::Result<()> {
|
||||
fn switch_workspace(&self, monitor_id: MonitorId, idx: usize) -> komorebi_backend::Result<()> {
|
||||
let commands = loop {
|
||||
let attempt = self.shared.table.lock().switch_commands(monitor_id, idx);
|
||||
let attempt = self
|
||||
.shared
|
||||
.table
|
||||
.lock()
|
||||
.switch_commands(monitor_id.to_u32().unwrap_or(u32::MAX), idx);
|
||||
match attempt {
|
||||
Ok(commands) => break commands,
|
||||
Err(NeedsDesktops(count)) => self.make_desktops(count)?,
|
||||
@@ -957,7 +976,8 @@ impl Backend for KWinBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_window_workspace(&self, id: u32, idx: usize) -> komorebi_backend::Result<()> {
|
||||
fn set_window_workspace(&self, id: WindowId, idx: usize) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
let commands = loop {
|
||||
let attempt = self.shared.table.lock().window_workspace_commands(id, idx);
|
||||
match attempt {
|
||||
@@ -972,27 +992,41 @@ impl Backend for KWinBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn window_workspace(&self, id: u32) -> Option<usize> {
|
||||
self.shared.table.lock().window_workspace(id)
|
||||
fn window_workspace(&self, id: WindowId) -> komorebi_backend::Result<Option<usize>> {
|
||||
let Some(id) = id.to_u32() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(self.shared.table.lock().window_workspace(id))
|
||||
}
|
||||
|
||||
fn current_workspaces(&self) -> Vec<(u32, usize)> {
|
||||
self.shared.table.lock().current_workspaces()
|
||||
fn current_workspaces(&self) -> komorebi_backend::Result<Vec<(MonitorId, usize)>> {
|
||||
Ok(self
|
||||
.shared
|
||||
.table
|
||||
.lock()
|
||||
.current_workspaces()
|
||||
.into_iter()
|
||||
.map(|(monitor, idx)| (MonitorId::from_u32(monitor), idx))
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn minimize(&self, id: u32) -> komorebi_backend::Result<()> {
|
||||
fn minimize(&self, id: WindowId) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(id, |uuid| json!({ "op": "min", "id": uuid, "v": true }))
|
||||
}
|
||||
|
||||
fn unminimize(&self, id: u32) -> komorebi_backend::Result<()> {
|
||||
fn unminimize(&self, id: WindowId) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(id, |uuid| json!({ "op": "min", "id": uuid, "v": false }))
|
||||
}
|
||||
|
||||
fn close(&self, id: u32) -> komorebi_backend::Result<()> {
|
||||
fn close(&self, id: WindowId) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(id, |uuid| json!({ "op": "close", "id": uuid }))
|
||||
}
|
||||
|
||||
fn maximize(&self, id: u32, maximize: bool) -> komorebi_backend::Result<()> {
|
||||
fn maximize(&self, id: WindowId, maximize: bool) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(
|
||||
id,
|
||||
|uuid| json!({ "op": "maximize", "id": uuid, "v": maximize }),
|
||||
@@ -1025,7 +1059,8 @@ impl Backend for KWinBackend {
|
||||
})?
|
||||
}
|
||||
|
||||
fn set_opacity(&self, id: u32, alpha: u8) -> komorebi_backend::Result<()> {
|
||||
fn set_opacity(&self, id: WindowId, alpha: u8) -> komorebi_backend::Result<()> {
|
||||
let id = raw(id)?;
|
||||
self.command(
|
||||
id,
|
||||
|uuid| json!({ "op": "opacity", "id": uuid, "v": f64::from(alpha) / 255.0 }),
|
||||
@@ -1037,31 +1072,31 @@ impl Backend for KWinBackend {
|
||||
|
||||
self.shared
|
||||
.block_on(async move {
|
||||
let Some(kwinrc) = &shared.kwinrc else {
|
||||
eyre::bail!("there is no configuration directory to find kwinrc in");
|
||||
};
|
||||
let Some(kwinrc) = &shared.kwinrc else {
|
||||
eyre::bail!("there is no configuration directory to find kwinrc in");
|
||||
};
|
||||
|
||||
if enable {
|
||||
kwinrc.set(
|
||||
"Windows",
|
||||
&[
|
||||
("FocusPolicy", "1".to_string()),
|
||||
("DelayFocusInterval", "0".to_string()),
|
||||
],
|
||||
)?;
|
||||
} else {
|
||||
kwinrc.restore_keys("Windows", &["FocusPolicy", "DelayFocusInterval"])?;
|
||||
}
|
||||
if enable {
|
||||
kwinrc.set(
|
||||
"Windows",
|
||||
&[
|
||||
("FocusPolicy", "1".to_string()),
|
||||
("DelayFocusInterval", "0".to_string()),
|
||||
],
|
||||
)?;
|
||||
} else {
|
||||
kwinrc.restore_keys("Windows", &["FocusPolicy", "DelayFocusInterval"])?;
|
||||
}
|
||||
|
||||
let connection = shared.connection().await?;
|
||||
kwin_reconfigure(&connection).await;
|
||||
Ok(())
|
||||
})
|
||||
let connection = shared.connection().await?;
|
||||
kwin_reconfigure(&connection).await;
|
||||
Ok(())
|
||||
})
|
||||
.map_err(platform)?
|
||||
.map_err(platform)
|
||||
}
|
||||
|
||||
fn set_wallpaper(&self, monitor_id: u32, path: &std::path::Path) -> eyre::Result<()> {
|
||||
fn set_wallpaper(&self, monitor_id: MonitorId, path: &std::path::Path) -> eyre::Result<()> {
|
||||
if !self.shared.alive.load(Ordering::SeqCst) {
|
||||
eyre::bail!("KWin is gone");
|
||||
}
|
||||
@@ -1072,7 +1107,7 @@ impl Backend for KWinBackend {
|
||||
.lock()
|
||||
.monitors()
|
||||
.into_iter()
|
||||
.find(|m| m.id == monitor_id)
|
||||
.find(|m| MonitorId::from_u32(m.id) == monitor_id)
|
||||
.map(|m| m.name)
|
||||
.ok_or_eyre("there is no such monitor")?;
|
||||
|
||||
@@ -1251,28 +1286,28 @@ mod tests {
|
||||
bottom: 1050,
|
||||
};
|
||||
// the editor is 1, the terminal 2 and the dialog 3
|
||||
backend.set_rect(1, &left(0)).unwrap();
|
||||
backend.focus(1, false).unwrap();
|
||||
backend.raise(1).unwrap();
|
||||
backend.minimize(1).unwrap();
|
||||
backend.unminimize(1).unwrap();
|
||||
backend.maximize(1, true).unwrap();
|
||||
backend.maximize(1, false).unwrap();
|
||||
backend.close(3).unwrap();
|
||||
backend.set_rect(1.into(), &left(0)).unwrap();
|
||||
backend.focus(1.into(), false).unwrap();
|
||||
backend.raise(1.into()).unwrap();
|
||||
backend.minimize(1.into()).unwrap();
|
||||
backend.unminimize(1.into()).unwrap();
|
||||
backend.maximize(1.into(), true).unwrap();
|
||||
backend.maximize(1.into(), false).unwrap();
|
||||
backend.close(3.into()).unwrap();
|
||||
// the terminal has closed, and the table still knows it: the bridge gives it back
|
||||
backend.set_rect(2, &left(960)).unwrap();
|
||||
backend.set_rect(2.into(), &left(960)).unwrap();
|
||||
},
|
||||
|backend| {
|
||||
// the editor goes to the second workspace before the monitor is switched to it
|
||||
let monitor = backend.monitors().unwrap()[0].id;
|
||||
backend.set_window_workspace(1, 1).unwrap();
|
||||
backend.switch_workspace(monitor, 1).unwrap();
|
||||
assert_eq!(backend.window_workspace(1), Some(1));
|
||||
assert_eq!(backend.current_workspaces(), [(monitor, 1)]);
|
||||
backend.set_window_workspace(1.into(), 1).unwrap();
|
||||
backend.switch_workspace(monitor.into(), 1).unwrap();
|
||||
assert_eq!(backend.window_workspace(1.into()).unwrap(), Some(1));
|
||||
assert_eq!(backend.current_workspaces().unwrap(), [(monitor.into(), 1)]);
|
||||
},
|
||||
|backend| {
|
||||
// 51 of 255 is a fifth
|
||||
backend.set_opacity(1, 51).unwrap();
|
||||
backend.set_opacity(1.into(), 51).unwrap();
|
||||
},
|
||||
];
|
||||
assert_eq!(asks.len(), commands.len());
|
||||
@@ -1362,7 +1397,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// the right tile, as the window manager put it
|
||||
let tile = backend.window_rect(2).unwrap();
|
||||
let tile = backend.window_rect(2.into()).unwrap();
|
||||
assert!(tile.left > 900, "{tile:?}");
|
||||
|
||||
let started = report(json!({
|
||||
@@ -1382,7 +1417,7 @@ mod tests {
|
||||
process(&mut wm, waiting);
|
||||
|
||||
assert_eq!(
|
||||
backend.window_rect(2).unwrap().left,
|
||||
backend.window_rect(2.into()).unwrap().left,
|
||||
tile.left - 200,
|
||||
"the tile took what the user asked for"
|
||||
);
|
||||
@@ -1393,9 +1428,9 @@ mod tests {
|
||||
fn a_command_about_a_window_the_table_does_not_know_is_an_error_and_sends_nothing() {
|
||||
let (runtime, backend) = offline();
|
||||
|
||||
assert!(backend.focus(7, false).is_err());
|
||||
assert!(backend.hide(7).is_err());
|
||||
assert!(backend.restore(7).is_err());
|
||||
assert!(backend.focus(7.into(), false).is_err());
|
||||
assert!(backend.hide(7.into()).is_err());
|
||||
assert!(backend.restore(7.into()).is_err());
|
||||
assert_eq!(next_poll(&runtime, &backend), json!([]));
|
||||
}
|
||||
|
||||
@@ -1429,20 +1464,20 @@ mod tests {
|
||||
table.set_park(String::from("p1"));
|
||||
}
|
||||
|
||||
backend.hide(1).unwrap();
|
||||
backend.hide(1.into()).unwrap();
|
||||
assert_eq!(
|
||||
next_poll(&runtime, &backend),
|
||||
json!([{ "batch": 1, "cmds": [{ "op": "desktop", "id": "{a}", "v": "p1" }] }])
|
||||
);
|
||||
|
||||
backend.restore(1).unwrap();
|
||||
backend.restore(1.into()).unwrap();
|
||||
assert_eq!(
|
||||
next_poll(&runtime, &backend),
|
||||
json!([{ "batch": 2, "cmds": [{ "op": "desktop", "id": "{a}", "v": "d1" }] }])
|
||||
);
|
||||
|
||||
// a window that is not hidden is not sent anywhere
|
||||
backend.restore(1).unwrap();
|
||||
backend.restore(1.into()).unwrap();
|
||||
assert_eq!(next_poll(&runtime, &backend), json!([]));
|
||||
}
|
||||
|
||||
@@ -1451,7 +1486,7 @@ mod tests {
|
||||
let (_runtime, backend) = offline();
|
||||
|
||||
// no snapshot yet: there is no monitor
|
||||
let nowhere = backend.set_wallpaper(1, std::path::Path::new("/nonexistent/a.png"));
|
||||
let nowhere = backend.set_wallpaper(1.into(), std::path::Path::new("/nonexistent/a.png"));
|
||||
assert!(nowhere.unwrap_err().to_string().contains("no such monitor"));
|
||||
|
||||
let events: Vec<Value> =
|
||||
@@ -1463,7 +1498,8 @@ mod tests {
|
||||
.handle(&events[0], Instant::now());
|
||||
let monitor = backend.monitors().unwrap()[0].id;
|
||||
|
||||
let missing = backend.set_wallpaper(monitor, std::path::Path::new("/nonexistent/a.png"));
|
||||
let missing =
|
||||
backend.set_wallpaper(monitor.into(), std::path::Path::new("/nonexistent/a.png"));
|
||||
assert!(missing.unwrap_err().to_string().contains("is not a file"));
|
||||
assert!(backend.shared.wallpapers.lock().is_empty());
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ use crate::workspace::WorkspaceGlobals;
|
||||
use crate::workspace::WorkspaceLayer;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::OptionExt;
|
||||
use komorebi_backend::MonitorId;
|
||||
use komorebi_backend::WindowId;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::VecDeque;
|
||||
@@ -254,7 +256,8 @@ impl Monitor {
|
||||
// was on
|
||||
self.assign_windows_to_workspaces();
|
||||
|
||||
if let Err(error) = backend().switch_workspace(monitor_id, focused_idx) {
|
||||
if let Err(error) = backend().switch_workspace(MonitorId::from_u32(monitor_id), focused_idx)
|
||||
{
|
||||
tracing::warn!("could not show workspace {focused_idx}: {error}");
|
||||
}
|
||||
|
||||
@@ -284,8 +287,13 @@ impl Monitor {
|
||||
.chain(workspace.maximized_window.iter());
|
||||
|
||||
for window in windows {
|
||||
if backend().window_workspace(window.id) != Some(idx)
|
||||
&& let Err(error) = backend().set_window_workspace(window.id, idx)
|
||||
if backend()
|
||||
.window_workspace(WindowId::from_u32(window.id))
|
||||
.ok()
|
||||
.flatten()
|
||||
!= Some(idx)
|
||||
&& let Err(error) =
|
||||
backend().set_window_workspace(WindowId::from_u32(window.id), idx)
|
||||
{
|
||||
tracing::debug!(
|
||||
"could not put window {} on workspace {idx}: {error}",
|
||||
@@ -323,6 +331,7 @@ impl Monitor {
|
||||
let foreground_hwnd = if !cfg!(test) {
|
||||
backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?
|
||||
} else {
|
||||
0
|
||||
|
||||
@@ -116,6 +116,7 @@ use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::workspace::WorkspaceLayer;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::OptionExt;
|
||||
use komorebi_backend::WindowId;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
use tracing::instrument;
|
||||
@@ -457,7 +458,10 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
// an app that remembers it was maximized opens that way
|
||||
if backend().window(window_id).is_some_and(|w| w.maximized) {
|
||||
if backend()
|
||||
.window(WindowId::from_u32(window_id))
|
||||
.is_some_and(|w| w.maximized)
|
||||
{
|
||||
self.update_known_window_ids();
|
||||
self.adopt_maximize_change(window_id, true)?;
|
||||
}
|
||||
@@ -518,7 +522,9 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
if focused {
|
||||
let refocus = should_refocus_after_destroy(backend().foreground_window());
|
||||
let refocus = should_refocus_after_destroy(
|
||||
backend().foreground_window().and_then(WindowId::to_u32),
|
||||
);
|
||||
self.update_focused_workspace(refocus, refocus)?;
|
||||
}
|
||||
}
|
||||
@@ -793,7 +799,9 @@ impl WindowManager {
|
||||
);
|
||||
|
||||
if !already_started {
|
||||
let started_from = match crate::backend::backend().drag_origin(window_id) {
|
||||
let started_from = match crate::backend::backend()
|
||||
.drag_origin(WindowId::from_u32(window_id))
|
||||
{
|
||||
Some(origin) => origin,
|
||||
None => window.rect()?,
|
||||
};
|
||||
@@ -861,10 +869,11 @@ impl WindowManager {
|
||||
// client is still drawing at the new size, and the frame events after the
|
||||
// drag can have changed that by now: the end of a resize does not wait for
|
||||
// them
|
||||
let new_position = match crate::backend::backend().drag_end(window_id) {
|
||||
Some(asked) => asked,
|
||||
None => window.rect()?,
|
||||
};
|
||||
let new_position =
|
||||
match crate::backend::backend().drag_end(WindowId::from_u32(window_id)) {
|
||||
Some(asked) => asked,
|
||||
None => window.rect()?,
|
||||
};
|
||||
let resized = self.apply_mouse_resize(window, started_from, new_position)?;
|
||||
|
||||
// put every window where the layout now says: the dragged one too when
|
||||
|
||||
@@ -17,6 +17,7 @@ use crate::backend::backend;
|
||||
use crate::window::Window;
|
||||
use crate::window::should_act;
|
||||
use crate::window_manager::WindowManager;
|
||||
use komorebi_backend::WindowId;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicU8;
|
||||
@@ -121,8 +122,8 @@ pub fn apply(wm: &mut WindowManager) {
|
||||
.copied()
|
||||
.collect();
|
||||
for id in no_longer {
|
||||
if backend().is_window(id)
|
||||
&& let Err(error) = backend().set_opacity(id, OPAQUE)
|
||||
if backend().is_window(WindowId::from_u32(id))
|
||||
&& let Err(error) = backend().set_opacity(WindowId::from_u32(id), OPAQUE)
|
||||
{
|
||||
tracing::warn!("could not make window {id} opaque: {error}");
|
||||
}
|
||||
@@ -134,7 +135,7 @@ pub fn apply(wm: &mut WindowManager) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match backend().set_opacity(id, alpha) {
|
||||
match backend().set_opacity(WindowId::from_u32(id), alpha) {
|
||||
Ok(()) => {
|
||||
wm.opacity_applied.insert(id, alpha);
|
||||
}
|
||||
@@ -146,8 +147,8 @@ pub fn apply(wm: &mut WindowManager) {
|
||||
/// Makes every window komorebi made see-through opaque again, when komorebi exits.
|
||||
pub fn restore(wm: &mut WindowManager) {
|
||||
for (id, _) in wm.opacity_applied.drain() {
|
||||
if backend().is_window(id) {
|
||||
let _ = backend().set_opacity(id, OPAQUE);
|
||||
if backend().is_window(WindowId::from_u32(id)) {
|
||||
let _ = backend().set_opacity(WindowId::from_u32(id), OPAQUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,15 @@ use crate::REGEX_IDENTIFIERS;
|
||||
use crate::backend::backend;
|
||||
use crate::core::ApplicationIdentifier;
|
||||
use crate::core::Rect;
|
||||
pub use komorebi_config::aspect_ratio::AspectRatio;
|
||||
pub use komorebi_config::aspect_ratio::PredefinedAspectRatio;
|
||||
use crate::core::config_generation::IdWithIdentifier;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::OptionExt;
|
||||
use komorebi_backend::WindowId;
|
||||
pub use komorebi_config::aspect_ratio::AspectRatio;
|
||||
pub use komorebi_config::aspect_ratio::PredefinedAspectRatio;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -91,6 +92,16 @@ impl From<u32> for Window {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for Window {
|
||||
/// An id too wide for a `u32` is not one this compositor ever gave: it becomes `u32::MAX`, which
|
||||
/// no window has.
|
||||
fn from(id: WindowId) -> Self {
|
||||
Self {
|
||||
id: id.to_u32().unwrap_or(u32::MAX),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct WindowDetails {
|
||||
@@ -174,18 +185,23 @@ impl schemars::JsonSchema for Window {
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// The id as the backend names it
|
||||
pub fn window_id(self) -> WindowId {
|
||||
WindowId::from_u32(self.id)
|
||||
}
|
||||
|
||||
/// What the compositor knows about this window, including for a few moments after it closed
|
||||
pub fn info(self) -> Option<crate::backend::WindowInfo> {
|
||||
backend().window(self.id)
|
||||
backend().window(self.window_id())
|
||||
}
|
||||
|
||||
/// Whether the window still exists
|
||||
pub fn is_valid(self) -> bool {
|
||||
backend().is_window(self.id)
|
||||
backend().is_window(self.window_id())
|
||||
}
|
||||
|
||||
pub fn is_focused(self) -> bool {
|
||||
backend().foreground_window() == Some(self.id)
|
||||
backend().foreground_window() == Some(self.window_id())
|
||||
}
|
||||
|
||||
pub fn is_minimized(self) -> bool {
|
||||
@@ -216,7 +232,7 @@ impl Window {
|
||||
/// The window's current frame geometry, as last reported by the compositor
|
||||
pub fn rect(self) -> eyre::Result<Rect> {
|
||||
backend()
|
||||
.window_rect(self.id)
|
||||
.window_rect(self.window_id())
|
||||
.ok_or_eyre("the window does not exist")
|
||||
}
|
||||
|
||||
@@ -240,21 +256,23 @@ impl Window {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
backend().set_rect(self.id, rect)
|
||||
backend().set_rect(self.window_id(), rect)
|
||||
}
|
||||
|
||||
/// Returns true if and only if the window is fullscreen
|
||||
pub fn is_fullscreen(self) -> bool {
|
||||
backend().window(self.id).is_some_and(|w| w.fullscreen)
|
||||
backend()
|
||||
.window(self.window_id())
|
||||
.is_some_and(|w| w.fullscreen)
|
||||
}
|
||||
|
||||
/// Asks the compositor to draw the window with this opacity, 255 being not see-through at all
|
||||
pub fn set_opacity(self, alpha: u8) -> komorebi_backend::Result<()> {
|
||||
backend().set_opacity(self.id, alpha)
|
||||
backend().set_opacity(self.window_id(), alpha)
|
||||
}
|
||||
|
||||
pub fn focus(self, mouse_follows_focus: bool) -> komorebi_backend::Result<()> {
|
||||
backend().focus(self.id, mouse_follows_focus)
|
||||
backend().focus(self.window_id(), mouse_follows_focus)
|
||||
}
|
||||
|
||||
/// Have the compositor maximize the window (the work area, panels respected)
|
||||
@@ -263,7 +281,7 @@ impl Window {
|
||||
///
|
||||
/// The backend does not know the window, or refuses to maximize it.
|
||||
pub fn maximize(self) -> komorebi_backend::Result<()> {
|
||||
backend().maximize(self.id, true)
|
||||
backend().maximize(self.window_id(), true)
|
||||
}
|
||||
|
||||
/// Have the compositor give the window back the frame it had before it was maximized
|
||||
@@ -272,25 +290,25 @@ impl Window {
|
||||
///
|
||||
/// The backend does not know the window, or refuses to restore it.
|
||||
pub fn unmaximize(self) -> komorebi_backend::Result<()> {
|
||||
backend().maximize(self.id, false)
|
||||
backend().maximize(self.window_id(), false)
|
||||
}
|
||||
|
||||
pub fn raise(self) -> komorebi_backend::Result<()> {
|
||||
backend().raise(self.id)
|
||||
backend().raise(self.window_id())
|
||||
}
|
||||
|
||||
pub fn close(self) -> komorebi_backend::Result<()> {
|
||||
backend().close(self.id)
|
||||
backend().close(self.window_id())
|
||||
}
|
||||
|
||||
/// Minimizes the window, as the user asking for it would. [`Window::hide`] is what komorebi
|
||||
/// does to keep the back of a stack out of the way.
|
||||
pub fn minimize(self) -> komorebi_backend::Result<()> {
|
||||
backend().minimize(self.id)
|
||||
backend().minimize(self.window_id())
|
||||
}
|
||||
|
||||
pub fn unminimize(self) -> komorebi_backend::Result<()> {
|
||||
backend().unminimize(self.id)
|
||||
backend().unminimize(self.window_id())
|
||||
}
|
||||
|
||||
/// Takes the window out of sight ([`Backend::hide`](crate::backend::Backend::hide)): the back
|
||||
@@ -302,7 +320,7 @@ impl Window {
|
||||
/// stays where it is, and stays recorded as hidden until [`Window::restore`].
|
||||
pub fn hide(self) {
|
||||
HIDDEN_WINDOWS.lock().insert(self.id);
|
||||
if let Err(error) = backend().hide(self.id) {
|
||||
if let Err(error) = backend().hide(self.window_id()) {
|
||||
tracing::warn!("failed to hide window {}: {error}", self.id);
|
||||
}
|
||||
}
|
||||
@@ -311,7 +329,7 @@ impl Window {
|
||||
/// [`struct@HIDDEN_WINDOWS`]. A failure is logged, as for [`Window::hide`].
|
||||
pub fn restore(self) {
|
||||
HIDDEN_WINDOWS.lock().remove(&self.id);
|
||||
if let Err(error) = backend().restore(self.id) {
|
||||
if let Err(error) = backend().restore(self.window_id()) {
|
||||
tracing::warn!("failed to restore window {}: {error}", self.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ use color_eyre::eyre::OptionExt;
|
||||
use color_eyre::eyre::bail;
|
||||
use crossbeam_channel::Receiver;
|
||||
use hotwatch::Hotwatch;
|
||||
use komorebi_backend::WindowId;
|
||||
use parking_lot::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
@@ -322,6 +323,7 @@ impl WindowManager {
|
||||
if len > 1 {
|
||||
let focused_window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
let focused_rect = Window::from(focused_window_id).rect()?;
|
||||
|
||||
@@ -797,6 +799,7 @@ impl WindowManager {
|
||||
|
||||
let focused_window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
for window in focused_workspace.floating_windows().iter() {
|
||||
if window.id == focused_window_id {
|
||||
@@ -1702,6 +1705,7 @@ impl WindowManager {
|
||||
pub fn toggle_float(&mut self, force_float: bool) -> eyre::Result<()> {
|
||||
let window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
@@ -1811,6 +1815,7 @@ impl WindowManager {
|
||||
let workspace = self.focused_workspace()?;
|
||||
let focused_window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
|
||||
let border_offset = 0;
|
||||
@@ -2359,7 +2364,7 @@ impl WindowManager {
|
||||
|
||||
pub fn monitor_idx_from_current_pos(&mut self) -> Option<usize> {
|
||||
let (x, y) = backend().cursor_pos()?;
|
||||
let monitor_id = backend().monitor_from_point(x, y)?;
|
||||
let monitor_id = backend().monitor_from_point(x, y)?.to_u32()?;
|
||||
|
||||
for (i, monitor) in self.monitors().iter().enumerate() {
|
||||
if monitor.id == monitor_id {
|
||||
@@ -2470,6 +2475,7 @@ impl WindowManager {
|
||||
|
||||
let foreground_window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
let floating_window_index = workspace
|
||||
.floating_windows()
|
||||
@@ -2765,6 +2771,7 @@ impl WindowManager {
|
||||
if len > 1 {
|
||||
let focused_window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
for (idx, window) in focused_workspace.floating_windows().iter().enumerate() {
|
||||
if window.id == focused_window_id {
|
||||
@@ -3268,6 +3275,7 @@ impl WindowManager {
|
||||
let workspace = self.focused_workspace()?;
|
||||
let focused_hwnd = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("there is no foreground window")?;
|
||||
if !workspace.contains_managed_window(focused_hwnd) {
|
||||
bail!("ignoring commands while active window is not managed by komorebi");
|
||||
@@ -3801,6 +3809,7 @@ impl WindowManager {
|
||||
pub fn manage_focused_window(&mut self) -> eyre::Result<()> {
|
||||
let window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("there is no foreground window")?;
|
||||
|
||||
UNMANAGED_WINDOW_IDS.lock().retain(|id| *id != window_id);
|
||||
@@ -3823,6 +3832,7 @@ impl WindowManager {
|
||||
pub fn unmanage_focused_window(&mut self) -> eyre::Result<()> {
|
||||
let window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("there is no foreground window")?;
|
||||
|
||||
window_manager_event_listener::send_notification(WindowManagerEvent::Unmanage(
|
||||
|
||||
@@ -40,6 +40,8 @@ use crate::window::should_act;
|
||||
use crate::window::should_act_individual;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::OptionExt;
|
||||
use komorebi_backend::MonitorId;
|
||||
use komorebi_backend::WindowId;
|
||||
use komorebi_scrolling::ScrollingSpace;
|
||||
use komorebi_themes::KomorebiTheme;
|
||||
use komorebi_themes::KomorebiThemeCustom;
|
||||
@@ -905,6 +907,7 @@ impl Workspace {
|
||||
pub fn is_focused_window_monocle_or_maximized(&self) -> eyre::Result<bool> {
|
||||
let window_id = backend()
|
||||
.foreground_window()
|
||||
.and_then(WindowId::to_u32)
|
||||
.ok_or_eyre("no foreground window")?;
|
||||
if let Some(window) = &self.maximized_window
|
||||
&& window_id == window.id
|
||||
@@ -1663,7 +1666,7 @@ impl Workspace {
|
||||
}
|
||||
|
||||
pub fn remove_focused_floating_window(&mut self) -> Option<Window> {
|
||||
let window_id = backend().foreground_window()?;
|
||||
let window_id = backend().foreground_window().and_then(WindowId::to_u32)?;
|
||||
self.remove_floating_window(window_id)
|
||||
}
|
||||
|
||||
@@ -2137,7 +2140,9 @@ impl Workspace {
|
||||
monitor_wp: &Option<Wallpaper>,
|
||||
) -> eyre::Result<()> {
|
||||
if let Some(wallpaper) = self.wallpaper.as_ref().or(monitor_wp.as_ref()) {
|
||||
if let Err(error) = backend().set_wallpaper(monitor_id, &wallpaper.path) {
|
||||
if let Err(error) =
|
||||
backend().set_wallpaper(MonitorId::from_u32(monitor_id), &wallpaper.path)
|
||||
{
|
||||
tracing::error!("failed to set wallpaper: {error}");
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,10 @@ fn focusing_towards_a_monitor_with_a_maximized_window_gives_it_the_focus() {
|
||||
);
|
||||
|
||||
assert_eq!(wm.focused_monitor_idx(), 1);
|
||||
assert_eq!(fake.foreground_window(), Some(36_064));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(36_064)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -352,7 +355,10 @@ fn eager_focus_finds_the_maximized_window_of_an_executable() {
|
||||
event(&fake, &mut wm, added(36_092));
|
||||
send(&fake, &mut wm, SocketMessage::ToggleMaximize);
|
||||
event(&fake, &mut wm, activated(36_091));
|
||||
assert_eq!(fake.foreground_window(), Some(36_091));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(36_091)
|
||||
);
|
||||
|
||||
send(
|
||||
&fake,
|
||||
@@ -360,5 +366,8 @@ fn eager_focus_finds_the_maximized_window_of_an_executable() {
|
||||
SocketMessage::EagerFocus(String::from("kate")),
|
||||
);
|
||||
|
||||
assert_eq!(fake.foreground_window(), Some(36_092));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(36_092)
|
||||
);
|
||||
}
|
||||
@@ -145,7 +145,10 @@ fn the_focus_crosses_to_the_monitor_on_that_side() {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(wm.focused_monitor_idx(), 1);
|
||||
assert_eq!(fake.foreground_window(), Some(32_011));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(32_011)
|
||||
);
|
||||
|
||||
// and with no monitor further right, it is an error that changes nothing
|
||||
let result = send(
|
||||
@@ -258,7 +261,10 @@ fn a_monitor_is_focused_by_its_index_or_in_order() {
|
||||
|
||||
send(&fake, &mut wm, SocketMessage::FocusMonitorNumber(0)).unwrap();
|
||||
assert_eq!(wm.focused_monitor_idx(), 0);
|
||||
assert_eq!(fake.foreground_window(), Some(32_051));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(32_051)
|
||||
);
|
||||
|
||||
send(
|
||||
&fake,
|
||||
@@ -267,7 +273,10 @@ fn a_monitor_is_focused_by_its_index_or_in_order() {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(wm.focused_monitor_idx(), 1);
|
||||
assert_eq!(fake.foreground_window(), Some(32_052));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(32_052)
|
||||
);
|
||||
|
||||
assert!(send(&fake, &mut wm, SocketMessage::FocusMonitorNumber(5)).is_err());
|
||||
assert_eq!(wm.focused_monitor_idx(), 1);
|
||||
@@ -396,7 +405,10 @@ fn eager_focus_finds_the_window_of_an_executable_on_any_monitor_and_workspace()
|
||||
|
||||
assert_eq!(wm.focused_monitor_idx(), 1);
|
||||
assert_eq!(wm.focused_workspace_idx().unwrap(), 1);
|
||||
assert_eq!(fake.foreground_window(), Some(32_102));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(32_102)
|
||||
);
|
||||
assert_eq!(fake.shown_workspace(RIGHT), 1);
|
||||
assert_eq!(fake.shown_workspace(LEFT), 0);
|
||||
}
|
||||
@@ -508,7 +508,10 @@ fn focusing_towards_a_monitor_in_monocle_gives_the_focus_to_its_monocle_window()
|
||||
);
|
||||
|
||||
assert_eq!(wm.focused_monitor_idx(), 1);
|
||||
assert_eq!(fake.foreground_window(), Some(35_113));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(35_113)
|
||||
);
|
||||
assert_eq!(
|
||||
wm.monitors()[1]
|
||||
.focused_workspace()
|
||||
@@ -592,5 +595,8 @@ fn eager_focus_finds_the_window_of_an_executable_in_the_monocle() {
|
||||
SocketMessage::EagerFocus(String::from("kate")),
|
||||
);
|
||||
|
||||
assert_eq!(fake.foreground_window(), Some(35_142));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(35_142)
|
||||
);
|
||||
}
|
||||
@@ -168,7 +168,10 @@ fn stacking_puts_two_windows_in_one_container_and_hides_the_one_behind() {
|
||||
// 33_023 is the bottom right tile and had the focus: it goes onto 33_022, above it
|
||||
assert_eq!(containers(&wm), [vec![33_021], vec![33_023, 33_022]]);
|
||||
assert_eq!(hidden(&fake, &ids), [33_022]);
|
||||
assert_eq!(fake.foreground_window(), Some(33_023));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(33_023)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -258,7 +261,10 @@ fn closing_the_window_in_front_of_a_stack_brings_the_next_one_forward() {
|
||||
|
||||
assert_eq!(containers(&wm), [vec![33_071]]);
|
||||
assert!(hidden(&fake, &ids).is_empty());
|
||||
assert_eq!(fake.foreground_window(), Some(33_071));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(33_071)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -504,7 +510,10 @@ fn cycling_the_stack_brings_the_next_window_to_the_front_and_hides_the_one_that_
|
||||
|
||||
assert_eq!(wm.focused_window().unwrap().id, 33_201);
|
||||
assert_eq!(hidden(&fake, &ids), [33_202, 33_203]);
|
||||
assert_eq!(fake.foreground_window(), Some(33_201));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(33_201)
|
||||
);
|
||||
|
||||
send(
|
||||
&fake,
|
||||
@@ -515,7 +524,10 @@ fn cycling_the_stack_brings_the_next_window_to_the_front_and_hides_the_one_that_
|
||||
|
||||
assert_eq!(wm.focused_window().unwrap().id, 33_203);
|
||||
assert_eq!(hidden(&fake, &ids), [33_201, 33_202]);
|
||||
assert_eq!(fake.foreground_window(), Some(33_203));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(33_203)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -560,7 +572,10 @@ fn cycling_the_index_moves_the_front_window_along_the_stack_and_keeps_it_in_fron
|
||||
assert_eq!(order(&wm), [33_223, 33_222, 33_221]);
|
||||
assert_eq!(wm.focused_window().unwrap().id, 33_223);
|
||||
assert_eq!(hidden(&fake, &ids), [33_221, 33_222]);
|
||||
assert_eq!(fake.foreground_window(), Some(33_223));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(33_223)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -572,7 +587,10 @@ fn focus_stack_window_brings_the_window_at_an_index_to_the_front() {
|
||||
|
||||
assert_eq!(wm.focused_window().unwrap().id, 33_232);
|
||||
assert_eq!(hidden(&fake, &ids), [33_231, 33_233]);
|
||||
assert_eq!(fake.foreground_window(), Some(33_232));
|
||||
assert_eq!(
|
||||
fake.foreground_window().and_then(|id| id.to_u32()),
|
||||
Some(33_232)
|
||||
);
|
||||
|
||||
send(&fake, &mut wm, SocketMessage::FocusStackWindow(0)).unwrap();
|
||||
assert_eq!(wm.focused_window().unwrap().id, 33_231);
|
||||
|
||||
@@ -264,7 +264,7 @@ fn a_window_open_on_a_desktop_at_startup_starts_on_that_workspace() {
|
||||
fake.show_workspace_by_user(MONITOR, 0);
|
||||
{
|
||||
use komorebi::backend::Backend;
|
||||
fake.set_window_workspace(10_112, 1).unwrap();
|
||||
fake.set_window_workspace(10_112.into(), 1).unwrap();
|
||||
fake.clear_commands();
|
||||
}
|
||||
let (_fake, wm) = desktop_on(fake);
|
||||
|
||||
Reference in new issue
Block a user