feat(wm): add additional manage rules

Following on from 8ffe6f78b7, this commit
introduces a command to add rules to forcibly manage windows that don't
get picked up by the rough heuristics that are able to target most
windows for management in Window.should_manage.

Since there is again no overlap (or at least, no undesired overlap)
between executable names and classes, I'll keep both class and exe names
in a single lookup vec.

re #16
This commit is contained in:
LGUG2Z
2021-08-19 14:34:59 -07:00
parent 8ffe6f78b7
commit 4e9b294835
6 changed files with 35 additions and 7 deletions

View File

@@ -179,9 +179,12 @@ toggle-float Toggle floating mode for the focused window
toggle-monocle Toggle monocle mode for the focused container
toggle-maximize Toggle native maximization for the focused window
restore-windows Restore all hidden windows (debugging command)
manage Force komorebi to manage the focused window
unmanage Unmanage a window that was forcibly managed
reload-configuration Reload ~/komorebi.ahk (if it exists)
watch-configuration Toggle the automatic reloading of ~/komorebi.ahk (if it exists)
float-rule Add a rule to always float the specified application
manage-rule Add a rule to always manage the specified application
workspace-rule Add a rule to associate an application with a workspace
identify-tray-application Identify an application that closes to the system tray
focus-follows-mouse Enable or disable focus follows mouse for the operating system
@@ -209,6 +212,7 @@ help Print this message or the help of the given subcomm
- [x] Equal-width, max-height column layout
- [x] Floating rules based on exe name, window title and class
- [x] Workspace rules based on exe name and window class
- [x] Additional manage rules based on exe name and window class
- [x] Identify 'close/minimize to tray' applications by exe name and class
- [x] Toggle floating windows
- [x] Toggle monocle window

View File

@@ -61,6 +61,7 @@ pub enum SocketMessage {
FloatExe(String),
FloatTitle(String),
WorkspaceRule(ApplicationIdentifier, String, usize, usize),
ManageRule(ApplicationIdentifier, String),
IdentifyTrayApplication(ApplicationIdentifier, String),
State,
FocusFollowsMouse(bool),

View File

@@ -70,6 +70,7 @@ lazy_static! {
]));
static ref WORKSPACE_RULES: Arc<Mutex<HashMap<String, (usize, usize)>>> =
Arc::new(Mutex::new(HashMap::new()));
static ref MANAGE_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
}
fn setup() -> Result<(WorkerGuard, WorkerGuard)> {

View File

@@ -19,6 +19,7 @@ use crate::windows_api::WindowsApi;
use crate::FLOAT_CLASSES;
use crate::FLOAT_EXES;
use crate::FLOAT_TITLES;
use crate::MANAGE_IDENTIFIERS;
use crate::TRAY_AND_MULTI_WINDOW_CLASSES;
use crate::TRAY_AND_MULTI_WINDOW_EXES;
use crate::WORKSPACE_RULES;
@@ -116,6 +117,19 @@ impl WindowManager {
ApplicationIdentifier::Title => {}
}
}
SocketMessage::ManageRule(identifier, id) => match identifier {
ApplicationIdentifier::Exe | ApplicationIdentifier::Class => {
{
let mut manage_identifiers = MANAGE_IDENTIFIERS.lock();
if !manage_identifiers.contains(&id) {
manage_identifiers.push(id);
}
}
self.update_focused_workspace(false)?;
}
ApplicationIdentifier::Title => {}
},
SocketMessage::AdjustContainerPadding(sizing, adjustment) => {
self.adjust_container_padding(sizing, adjustment)?;
}

View File

@@ -20,6 +20,7 @@ use crate::FLOAT_EXES;
use crate::FLOAT_TITLES;
use crate::HIDDEN_HWNDS;
use crate::LAYERED_EXE_WHITELIST;
use crate::MANAGE_IDENTIFIERS;
#[derive(Debug, Clone, Copy)]
pub struct Window {
@@ -219,9 +220,9 @@ impl Window {
#[tracing::instrument(fields(exe, title))]
pub fn should_manage(self, event: Option<WindowManagerEvent>) -> Result<bool> {
let classes = FLOAT_CLASSES.lock();
let exes = FLOAT_EXES.lock();
let titles = FLOAT_TITLES.lock();
let float_classes = FLOAT_CLASSES.lock();
let float_exes = FLOAT_EXES.lock();
let float_titles = FLOAT_TITLES.lock();
if self.title().is_err() {
return Ok(false);
@@ -239,17 +240,17 @@ impl Window {
(true, _) |
// If not allowing cloaked windows, we need to ensure the window is not cloaked
(false, false) => {
if let (Ok(title), Ok(exe_name)) = (self.title(), self.exe()) {
if titles.contains(&title) {
if let (Ok(title), Ok(exe_name), Ok(class)) = (self.title(), self.exe(), self.class()) {
if float_titles.contains(&title) {
return Ok(false);
}
if exes.contains(&exe_name) {
if float_exes.contains(&exe_name) {
return Ok(false);
}
if let Ok(class) = self.class() {
if classes.contains(&class) {
if float_classes.contains(&class) {
return Ok(false);
}
}
@@ -267,6 +268,7 @@ impl Window {
// allowing a specific layered window on the whitelist (like Steam), it should
// pass this check
&& (allow_layered || !ex_style.contains(GwlExStyle::LAYERED))
|| MANAGE_IDENTIFIERS.lock().contains(&exe_name) || MANAGE_IDENTIFIERS.lock().contains(&class)
{
Ok(true)
} else {

View File

@@ -281,6 +281,9 @@ enum SubCommand {
/// Add a rule to always float the specified application
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
FloatRule(ApplicationTarget),
/// Add a rule to always manage the specified application
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
ManageRule(ApplicationTarget),
/// Add a rule to associate an application with a workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
WorkspaceRule(WorkspaceRule),
@@ -432,6 +435,9 @@ fn main() -> Result<()> {
send_message(&*SocketMessage::FloatTitle(arg.id).as_bytes()?)?;
}
},
SubCommand::ManageRule(arg) => {
send_message(&*SocketMessage::ManageRule(arg.identifier, arg.id).as_bytes()?)?;
}
SubCommand::WorkspaceRule(arg) => {
send_message(
&*SocketMessage::WorkspaceRule(arg.identifier, arg.id, arg.monitor, arg.workspace)