Skip to content

Commit

Permalink
feat(cli): add last focused workspace cmd
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
LGUG2Z committed Jan 12, 2024
1 parent 8f30612 commit d6e83e1
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 12 deletions.
1 change: 1 addition & 0 deletions komorebi-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub enum SocketMessage {
CycleFocusMonitor(CycleDirection),
CycleFocusWorkspace(CycleDirection),
FocusMonitorNumber(usize),
FocusLastWorkspace,
FocusWorkspaceNumber(usize),
FocusWorkspaceNumbers(usize),
FocusMonitorWorkspaceNumber(usize, usize),
Expand Down
4 changes: 4 additions & 0 deletions komorebi/src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ pub struct Monitor {
work_area_offset: Option<Rect>,
workspaces: Ring<Workspace>,
#[serde(skip_serializing)]
#[getset(get_copy = "pub", set = "pub")]
last_focused_workspace: Option<usize>,
#[serde(skip_serializing)]
#[getset(get_mut = "pub")]
workspace_names: HashMap<usize, String>,
}
Expand All @@ -54,6 +57,7 @@ pub fn new(id: isize, size: Rect, work_area_size: Rect, name: String) -> Monitor
work_area_size,
work_area_offset: None,
workspaces,
last_focused_workspace: None,
workspace_names: HashMap::default(),
}
}
Expand Down
64 changes: 52 additions & 12 deletions komorebi/src/process_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
SocketMessage::Promote => self.promote_container_to_front()?,
SocketMessage::PromoteFocus => self.promote_focus_to_front()?,
Expand Down Expand Up @@ -598,6 +615,33 @@ impl WindowManager {
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) => {
// 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
Expand Down Expand Up @@ -1338,21 +1382,17 @@ impl WindowManager {
rect.bottom += self.invisible_borders.bottom;

let monocle = BORDER_COLOUR_MONOCLE.load(Ordering::SeqCst);
if monocle != 0 {
if self.focused_workspace()?.monocle_container().is_some() {
BORDER_COLOUR_CURRENT.store(
monocle,
Ordering::SeqCst,
);
}
if monocle != 0 && self.focused_workspace()?.monocle_container().is_some() {
BORDER_COLOUR_CURRENT.store(
monocle,
Ordering::SeqCst,
);
}

let stack = BORDER_COLOUR_STACK.load(Ordering::SeqCst);
if stack != 0 {
if self.focused_container()?.windows().len() > 1 {
BORDER_COLOUR_CURRENT
.store(stack, Ordering::SeqCst);
}
if stack != 0 && self.focused_container()?.windows().len() > 1 {
BORDER_COLOUR_CURRENT
.store(stack, Ordering::SeqCst);
}

let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
Expand Down
8 changes: 8 additions & 0 deletions komorebi/src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2198,6 +2198,14 @@ impl WindowManager {
.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> {
self.monitors()
.get(idx)
Expand Down
5 changes: 5 additions & 0 deletions komorebic/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,8 @@ enum SubCommand {
/// Focus the specified monitor
#[clap(arg_required_else_help = true)]
FocusMonitor(FocusMonitor),
/// Focus the last focused workspace on the focused monitor
FocusLastWorkspace,
/// Focus the specified workspace on the focused monitor
#[clap(arg_required_else_help = true)]
FocusWorkspace(FocusWorkspace),
Expand Down Expand Up @@ -1857,6 +1859,9 @@ Stop-Process -Name:whkd -ErrorAction SilentlyContinue
SubCommand::FocusMonitor(arg) => {
send_message(&SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?;
}
SubCommand::FocusLastWorkspace => {
send_message(&SocketMessage::FocusLastWorkspace.as_bytes()?)?;
}
SubCommand::FocusWorkspace(arg) => {
send_message(&SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
}
Expand Down

0 comments on commit d6e83e1

Please sign in to comment.