mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-14 00:52:54 +02:00
feat(cli): add last focused workspace cmd
This commit adds a new komorebic command, focus-last-workspace, which switches to the last focused workspace on the focused monitor (if there is one).
This commit is contained in:
@@ -99,6 +99,7 @@ pub enum SocketMessage {
|
|||||||
CycleFocusMonitor(CycleDirection),
|
CycleFocusMonitor(CycleDirection),
|
||||||
CycleFocusWorkspace(CycleDirection),
|
CycleFocusWorkspace(CycleDirection),
|
||||||
FocusMonitorNumber(usize),
|
FocusMonitorNumber(usize),
|
||||||
|
FocusLastWorkspace,
|
||||||
FocusWorkspaceNumber(usize),
|
FocusWorkspaceNumber(usize),
|
||||||
FocusWorkspaceNumbers(usize),
|
FocusWorkspaceNumbers(usize),
|
||||||
FocusMonitorWorkspaceNumber(usize, usize),
|
FocusMonitorWorkspaceNumber(usize, usize),
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ pub struct Monitor {
|
|||||||
work_area_offset: Option<Rect>,
|
work_area_offset: Option<Rect>,
|
||||||
workspaces: Ring<Workspace>,
|
workspaces: Ring<Workspace>,
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
|
#[getset(get_copy = "pub", set = "pub")]
|
||||||
|
last_focused_workspace: Option<usize>,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
#[getset(get_mut = "pub")]
|
#[getset(get_mut = "pub")]
|
||||||
workspace_names: HashMap<usize, String>,
|
workspace_names: HashMap<usize, String>,
|
||||||
}
|
}
|
||||||
@@ -54,6 +57,7 @@ pub fn new(id: isize, size: Rect, work_area_size: Rect, name: String) -> Monitor
|
|||||||
work_area_size,
|
work_area_size,
|
||||||
work_area_offset: None,
|
work_area_offset: None,
|
||||||
workspaces,
|
workspaces,
|
||||||
|
last_focused_workspace: None,
|
||||||
workspace_names: HashMap::default(),
|
workspace_names: HashMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,23 @@ impl WindowManager {
|
|||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match message {
|
||||||
|
SocketMessage::CycleFocusWorkspace(_) | SocketMessage::FocusWorkspaceNumber(_) => {
|
||||||
|
if let Some(monitor) = self.focused_monitor_mut() {
|
||||||
|
let idx = monitor.focused_workspace_idx();
|
||||||
|
monitor.set_last_focused_workspace(Option::from(idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SocketMessage::FocusMonitorWorkspaceNumber(target_monitor_idx, _) => {
|
||||||
|
let idx = self.focused_workspace_idx_for_monitor_idx(target_monitor_idx)?;
|
||||||
|
if let Some(monitor) = self.monitors_mut().get_mut(target_monitor_idx) {
|
||||||
|
monitor.set_last_focused_workspace(Option::from(idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
match message {
|
match message {
|
||||||
SocketMessage::Promote => self.promote_container_to_front()?,
|
SocketMessage::Promote => self.promote_container_to_front()?,
|
||||||
SocketMessage::PromoteFocus => self.promote_focus_to_front()?,
|
SocketMessage::PromoteFocus => self.promote_focus_to_front()?,
|
||||||
@@ -598,6 +615,33 @@ impl WindowManager {
|
|||||||
self.show_border()?;
|
self.show_border()?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
SocketMessage::FocusLastWorkspace => {
|
||||||
|
// This is to ensure that even on an empty workspace on a secondary monitor, the
|
||||||
|
// secondary monitor where the cursor is focused will be used as the target for
|
||||||
|
// the workspace switch op
|
||||||
|
if let Some(monitor_idx) = self.monitor_idx_from_current_pos() {
|
||||||
|
self.focus_monitor(monitor_idx)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let idx = self
|
||||||
|
.focused_monitor()
|
||||||
|
.ok_or_else(|| anyhow!("there is no monitor"))?
|
||||||
|
.focused_workspace_idx();
|
||||||
|
|
||||||
|
if let Some(monitor) = self.focused_monitor_mut() {
|
||||||
|
if let Some(last_focused_workspace) = monitor.last_focused_workspace() {
|
||||||
|
self.focus_workspace(last_focused_workspace)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.focused_monitor_mut()
|
||||||
|
.ok_or_else(|| anyhow!("there is no monitor"))?
|
||||||
|
.set_last_focused_workspace(Option::from(idx));
|
||||||
|
|
||||||
|
if BORDER_ENABLED.load(Ordering::SeqCst) {
|
||||||
|
self.show_border()?;
|
||||||
|
};
|
||||||
|
}
|
||||||
SocketMessage::FocusWorkspaceNumber(workspace_idx) => {
|
SocketMessage::FocusWorkspaceNumber(workspace_idx) => {
|
||||||
// This is to ensure that even on an empty workspace on a secondary monitor, the
|
// This is to ensure that even on an empty workspace on a secondary monitor, the
|
||||||
// secondary monitor where the cursor is focused will be used as the target for
|
// secondary monitor where the cursor is focused will be used as the target for
|
||||||
@@ -1338,21 +1382,17 @@ impl WindowManager {
|
|||||||
rect.bottom += self.invisible_borders.bottom;
|
rect.bottom += self.invisible_borders.bottom;
|
||||||
|
|
||||||
let monocle = BORDER_COLOUR_MONOCLE.load(Ordering::SeqCst);
|
let monocle = BORDER_COLOUR_MONOCLE.load(Ordering::SeqCst);
|
||||||
if monocle != 0 {
|
if monocle != 0 && self.focused_workspace()?.monocle_container().is_some() {
|
||||||
if self.focused_workspace()?.monocle_container().is_some() {
|
BORDER_COLOUR_CURRENT.store(
|
||||||
BORDER_COLOUR_CURRENT.store(
|
monocle,
|
||||||
monocle,
|
Ordering::SeqCst,
|
||||||
Ordering::SeqCst,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let stack = BORDER_COLOUR_STACK.load(Ordering::SeqCst);
|
let stack = BORDER_COLOUR_STACK.load(Ordering::SeqCst);
|
||||||
if stack != 0 {
|
if stack != 0 && self.focused_container()?.windows().len() > 1 {
|
||||||
if self.focused_container()?.windows().len() > 1 {
|
BORDER_COLOUR_CURRENT
|
||||||
BORDER_COLOUR_CURRENT
|
.store(stack, Ordering::SeqCst);
|
||||||
.store(stack, Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
||||||
|
|||||||
@@ -2198,6 +2198,14 @@ impl WindowManager {
|
|||||||
.ok_or_else(|| anyhow!("there is no workspace"))
|
.ok_or_else(|| anyhow!("there is no workspace"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn focused_workspace_idx_for_monitor_idx(&self, idx: usize) -> Result<usize> {
|
||||||
|
Ok(self
|
||||||
|
.monitors()
|
||||||
|
.get(idx)
|
||||||
|
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||||
|
.focused_workspace_idx())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn focused_workspace_for_monitor_idx(&self, idx: usize) -> Result<&Workspace> {
|
pub fn focused_workspace_for_monitor_idx(&self, idx: usize) -> Result<&Workspace> {
|
||||||
self.monitors()
|
self.monitors()
|
||||||
.get(idx)
|
.get(idx)
|
||||||
|
|||||||
@@ -868,6 +868,8 @@ enum SubCommand {
|
|||||||
/// Focus the specified monitor
|
/// Focus the specified monitor
|
||||||
#[clap(arg_required_else_help = true)]
|
#[clap(arg_required_else_help = true)]
|
||||||
FocusMonitor(FocusMonitor),
|
FocusMonitor(FocusMonitor),
|
||||||
|
/// Focus the last focused workspace on the focused monitor
|
||||||
|
FocusLastWorkspace,
|
||||||
/// Focus the specified workspace on the focused monitor
|
/// Focus the specified workspace on the focused monitor
|
||||||
#[clap(arg_required_else_help = true)]
|
#[clap(arg_required_else_help = true)]
|
||||||
FocusWorkspace(FocusWorkspace),
|
FocusWorkspace(FocusWorkspace),
|
||||||
@@ -1857,6 +1859,9 @@ Stop-Process -Name:whkd -ErrorAction SilentlyContinue
|
|||||||
SubCommand::FocusMonitor(arg) => {
|
SubCommand::FocusMonitor(arg) => {
|
||||||
send_message(&SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?;
|
send_message(&SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?;
|
||||||
}
|
}
|
||||||
|
SubCommand::FocusLastWorkspace => {
|
||||||
|
send_message(&SocketMessage::FocusLastWorkspace.as_bytes()?)?;
|
||||||
|
}
|
||||||
SubCommand::FocusWorkspace(arg) => {
|
SubCommand::FocusWorkspace(arg) => {
|
||||||
send_message(&SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
|
send_message(&SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user