Skip to content

Commit

Permalink
feat(wm): add all matching strats for ws rules
Browse files Browse the repository at this point in the history
This commit ensures that the full range of matching strategies for both
Simple and Composite matching rules will be respected for both initial
and persistent workspace rules.

The generate-static-config command will no longer attempt to populate
workspace rules, and will likely slowly be deprecated as the
overwhelming majority have users have already migrated to the static
configuration file format.

fix #991
  • Loading branch information
LGUG2Z committed Oct 2, 2024
1 parent b719824 commit 7b563aa
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 264 deletions.
8 changes: 8 additions & 0 deletions komorebi/src/core/config_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ pub enum MatchingRule {
Composite(Vec<IdWithIdentifier>),
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct WorkspaceMatchingRule {
pub monitor_index: usize,
pub workspace_index: usize,
pub matching_rule: MatchingRule,
pub initial_only: bool,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct IdWithIdentifier {
pub kind: ApplicationIdentifier,
Expand Down
7 changes: 3 additions & 4 deletions komorebi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub use windows_api::*;
use crate::core::config_generation::IdWithIdentifier;
use crate::core::config_generation::MatchingRule;
use crate::core::config_generation::MatchingStrategy;
use crate::core::config_generation::WorkspaceMatchingRule;
use color_eyre::Result;
use os_info::Version;
use parking_lot::Mutex;
Expand All @@ -74,8 +75,6 @@ use which::which;
use winreg::enums::HKEY_CURRENT_USER;
use winreg::RegKey;

type WorkspaceRule = (usize, usize, bool);

lazy_static! {
static ref HIDDEN_HWNDS: Arc<Mutex<Vec<isize>>> = Arc::new(Mutex::new(vec![]));
static ref LAYERED_WHITELIST: Arc<Mutex<Vec<MatchingRule>>> = Arc::new(Mutex::new(vec![
Expand Down Expand Up @@ -135,8 +134,8 @@ lazy_static! {
Arc::new(Mutex::new(HashMap::new()));
static ref DISPLAY_INDEX_PREFERENCES: Arc<Mutex<HashMap<usize, String>>> =
Arc::new(Mutex::new(HashMap::new()));
static ref WORKSPACE_RULES: Arc<Mutex<HashMap<String, WorkspaceRule>>> =
Arc::new(Mutex::new(HashMap::new()));
static ref WORKSPACE_MATCHING_RULES: Arc<Mutex<Vec<WorkspaceMatchingRule>>> =
Arc::new(Mutex::new(Vec::new()));
static ref REGEX_IDENTIFIERS: Arc<Mutex<HashMap<String, Regex>>> =
Arc::new(Mutex::new(HashMap::new()));
static ref MANAGE_IDENTIFIERS: Arc<Mutex<Vec<MatchingRule>>> = Arc::new(Mutex::new(vec![]));
Expand Down
153 changes: 76 additions & 77 deletions komorebi/src/process_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use crate::border_manager;
use crate::border_manager::IMPLEMENTATION;
use crate::border_manager::STYLE;
use crate::colour::Rgb;
use crate::config_generation::WorkspaceMatchingRule;
use crate::current_virtual_desktop;
use crate::notify_subscribers;
use crate::stackbar_manager;
Expand Down Expand Up @@ -81,7 +82,7 @@ use crate::SUBSCRIPTION_SOCKETS;
use crate::TCP_CONNECTIONS;
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
use crate::WINDOWS_11;
use crate::WORKSPACE_RULES;
use crate::WORKSPACE_MATCHING_RULES;
use stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR;
use stackbar_manager::STACKBAR_LABEL;
use stackbar_manager::STACKBAR_MODE;
Expand Down Expand Up @@ -269,58 +270,101 @@ impl WindowManager {
self.set_workspace_padding(monitor_idx, workspace_idx, size)?;
}
}
SocketMessage::InitialWorkspaceRule(_, ref id, monitor_idx, workspace_idx) => {
self.handle_initial_workspace_rules(id, monitor_idx, workspace_idx)?;
SocketMessage::InitialWorkspaceRule(identifier, ref id, monitor_idx, workspace_idx) => {
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();
let workspace_matching_rule = WorkspaceMatchingRule {
monitor_index: monitor_idx,
workspace_index: workspace_idx,
matching_rule: MatchingRule::Simple(IdWithIdentifier {
kind: identifier,
id: id.to_string(),
matching_strategy: Some(MatchingStrategy::Legacy),
}),
initial_only: true,
};

if !workspace_rules.contains(&workspace_matching_rule) {
workspace_rules.push(workspace_matching_rule);
}
}
SocketMessage::InitialNamedWorkspaceRule(_, ref id, ref workspace) => {
SocketMessage::InitialNamedWorkspaceRule(identifier, ref id, ref workspace) => {
if let Some((monitor_idx, workspace_idx)) =
self.monitor_workspace_index_by_name(workspace)
{
self.handle_initial_workspace_rules(id, monitor_idx, workspace_idx)?;
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();
let workspace_matching_rule = WorkspaceMatchingRule {
monitor_index: monitor_idx,
workspace_index: workspace_idx,
matching_rule: MatchingRule::Simple(IdWithIdentifier {
kind: identifier,
id: id.to_string(),
matching_strategy: Some(MatchingStrategy::Legacy),
}),
initial_only: true,
};

if !workspace_rules.contains(&workspace_matching_rule) {
workspace_rules.push(workspace_matching_rule);
}
}
}
SocketMessage::WorkspaceRule(_, ref id, monitor_idx, workspace_idx) => {
self.handle_definitive_workspace_rules(id, monitor_idx, workspace_idx)?;
SocketMessage::WorkspaceRule(identifier, ref id, monitor_idx, workspace_idx) => {
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();
let workspace_matching_rule = WorkspaceMatchingRule {
monitor_index: monitor_idx,
workspace_index: workspace_idx,
matching_rule: MatchingRule::Simple(IdWithIdentifier {
kind: identifier,
id: id.to_string(),
matching_strategy: Some(MatchingStrategy::Legacy),
}),
initial_only: false,
};

if !workspace_rules.contains(&workspace_matching_rule) {
workspace_rules.push(workspace_matching_rule);
}
}
SocketMessage::NamedWorkspaceRule(_, ref id, ref workspace) => {
SocketMessage::NamedWorkspaceRule(identifier, ref id, ref workspace) => {
if let Some((monitor_idx, workspace_idx)) =
self.monitor_workspace_index_by_name(workspace)
{
self.handle_definitive_workspace_rules(id, monitor_idx, workspace_idx)?;
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();
let workspace_matching_rule = WorkspaceMatchingRule {
monitor_index: monitor_idx,
workspace_index: workspace_idx,
matching_rule: MatchingRule::Simple(IdWithIdentifier {
kind: identifier,
id: id.to_string(),
matching_strategy: Some(MatchingStrategy::Legacy),
}),
initial_only: false,
};

if !workspace_rules.contains(&workspace_matching_rule) {
workspace_rules.push(workspace_matching_rule);
}
}
}
SocketMessage::ClearWorkspaceRules(monitor_idx, workspace_idx) => {
let mut workspace_rules = WORKSPACE_RULES.lock();
let mut to_remove = vec![];
for (id, (m_idx, w_idx, _)) in workspace_rules.iter() {
if monitor_idx == *m_idx && workspace_idx == *w_idx {
to_remove.push(id.clone());
}
}
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();

for rule in to_remove {
workspace_rules.remove(&rule);
}
workspace_rules.retain(|r| {
r.monitor_index != monitor_idx && r.workspace_index != workspace_idx
});
}
SocketMessage::ClearNamedWorkspaceRules(ref workspace) => {
if let Some((monitor_idx, workspace_idx)) =
self.monitor_workspace_index_by_name(workspace)
{
let mut workspace_rules = WORKSPACE_RULES.lock();
let mut to_remove = vec![];
for (id, (m_idx, w_idx, _)) in workspace_rules.iter() {
if monitor_idx == *m_idx && workspace_idx == *w_idx {
to_remove.push(id.clone());
}
}

for rule in to_remove {
workspace_rules.remove(&rule);
}
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();
workspace_rules.retain(|r| {
r.monitor_index != monitor_idx && r.workspace_index != workspace_idx
});
}
}
SocketMessage::ClearAllWorkspaceRules => {
let mut workspace_rules = WORKSPACE_RULES.lock();
let mut workspace_rules = WORKSPACE_MATCHING_RULES.lock();
workspace_rules.clear();
}
SocketMessage::ManageRule(identifier, ref id) => {
Expand Down Expand Up @@ -1102,7 +1146,7 @@ impl WindowManager {
// Check that this is a valid static config file first
if StaticConfig::read(config).is_ok() {
// Clear workspace rules; these will need to be replaced
WORKSPACE_RULES.lock().clear();
WORKSPACE_MATCHING_RULES.lock().clear();
// Pause so that restored windows come to the foreground from all workspaces
self.is_paused = true;
// Bring all windows to the foreground
Expand Down Expand Up @@ -1496,51 +1540,6 @@ impl WindowManager {
tracing::info!("processed");
Ok(())
}

#[tracing::instrument(skip(self), level = "debug")]
fn handle_initial_workspace_rules(
&mut self,
id: &String,
monitor_idx: usize,
workspace_idx: usize,
) -> Result<()> {
self.handle_workspace_rules(id, monitor_idx, workspace_idx, true)?;

Ok(())
}

#[tracing::instrument(skip(self), level = "debug")]
fn handle_definitive_workspace_rules(
&mut self,
id: &String,
monitor_idx: usize,
workspace_idx: usize,
) -> Result<()> {
self.handle_workspace_rules(id, monitor_idx, workspace_idx, false)?;

Ok(())
}

#[tracing::instrument(skip(self), level = "debug")]
pub fn handle_workspace_rules(
&mut self,
id: &String,
monitor_idx: usize,
workspace_idx: usize,
initial_workspace_rule: bool,
) -> Result<()> {
{
let mut workspace_rules = WORKSPACE_RULES.lock();
workspace_rules.insert(
id.to_string(),
(monitor_idx, workspace_idx, initial_workspace_rule),
);
}

self.enforce_workspace_rules()?;

Ok(())
}
}

pub fn read_commands_uds(wm: &Arc<Mutex<WindowManager>>, mut stream: UnixStream) -> Result<()> {
Expand Down
Loading

0 comments on commit 7b563aa

Please sign in to comment.