Skip to content

Commit

Permalink
feat(rules): add explicit matching strategies
Browse files Browse the repository at this point in the history
This commit is the first in a series of commits which will pave the way
for regex rule matching support in komorebi.

For now, in order to maintain backwards compat and not break anything,
all rules without a matching strategy will get assigned as using the
"Legacy" strategy.

This and the "Equals" strategy are the only two which have been
implemented so far.

There should not be any breaking changes in this commit, not any
functionality lost for users with pre-existing configurations.

re #60
  • Loading branch information
LGUG2Z committed Sep 22, 2023
1 parent 57cc02f commit 0797316
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 26 deletions.
26 changes: 25 additions & 1 deletion komorebi-core/src/config_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,22 @@ impl ApplicationOptions {
}
}

#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct IdWithIdentifier {
pub kind: ApplicationIdentifier,
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub matching_strategy: Option<MatchingStrategy>,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub enum MatchingStrategy {
Legacy,
Equals,
StartsWith,
EndsWith,
Contains,
Regex,
}

#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
Expand All @@ -62,6 +74,18 @@ pub struct IdWithIdentifierAndComment {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub matching_strategy: Option<MatchingStrategy>,
}

impl From<IdWithIdentifierAndComment> for IdWithIdentifier {
fn from(value: IdWithIdentifierAndComment) -> Self {
Self {
kind: value.kind,
id: value.id.clone(),
matching_strategy: value.matching_strategy,
}
}
}

#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
Expand Down
12 changes: 11 additions & 1 deletion komorebi-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,17 @@ pub enum StateQuery {
}

#[derive(
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
Copy,
Clone,
Debug,
Eq,
PartialEq,
Serialize,
Deserialize,
Display,
EnumString,
ValueEnum,
JsonSchema,
)]
#[strum(serialize_all = "snake_case")]
pub enum ApplicationIdentifier {
Expand Down
17 changes: 14 additions & 3 deletions komorebi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ use winreg::enums::HKEY_CURRENT_USER;
use winreg::RegKey;

use crate::hidden::Hidden;
use komorebi_core::config_generation::IdWithIdentifier;
use komorebi_core::config_generation::MatchingStrategy;
use komorebi_core::ApplicationIdentifier;
use komorebi_core::HidingBehaviour;
use komorebi_core::Rect;
use komorebi_core::SocketMessage;
Expand Down Expand Up @@ -106,11 +109,19 @@ lazy_static! {
static ref WORKSPACE_RULES: Arc<Mutex<HashMap<String, WorkspaceRule>>> =
Arc::new(Mutex::new(HashMap::new()));
static ref MANAGE_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
static ref FLOAT_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![
static ref FLOAT_IDENTIFIERS: Arc<Mutex<Vec<IdWithIdentifier>>> = Arc::new(Mutex::new(vec![
// mstsc.exe creates these on Windows 11 when a WSL process is launched
// https://github.com/LGUG2Z/komorebi/issues/74
"OPContainerClass".to_string(),
"IHWindowClass".to_string()
IdWithIdentifier {
kind: ApplicationIdentifier::Class,
id: String::from("OPContainerClass"),
matching_strategy: Option::from(MatchingStrategy::Equals),
},
IdWithIdentifier {
kind: ApplicationIdentifier::Class,
id: String::from("IHWindowClass"),
matching_strategy: Option::from(MatchingStrategy::Equals),
}
]));
static ref PERMAIGNORE_CLASSES: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![
"Chrome_RenderWidgetHostHWND".to_string(),
Expand Down
18 changes: 16 additions & 2 deletions komorebi/src/process_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use parking_lot::Mutex;
use schemars::schema_for;
use uds_windows::UnixStream;

use komorebi_core::config_generation::IdWithIdentifier;
use komorebi_core::config_generation::MatchingStrategy;
use komorebi_core::ApplicationIdentifier;
use komorebi_core::Axis;
use komorebi_core::FocusFollowsMouseImplementation;
Expand Down Expand Up @@ -246,8 +248,20 @@ impl WindowManager {
}
SocketMessage::FloatRule(identifier, ref id) => {
let mut float_identifiers = FLOAT_IDENTIFIERS.lock();
if !float_identifiers.contains(id) {
float_identifiers.push(id.to_string());

let mut should_push = true;
for f in &*float_identifiers {
if f.id.eq(id) {
should_push = false;
}
}

if should_push {
float_identifiers.push(IdWithIdentifier {
kind: identifier,
id: id.clone(),
matching_strategy: Option::from(MatchingStrategy::Legacy),
});
}

let invisible_borders = self.invisible_borders;
Expand Down
28 changes: 20 additions & 8 deletions komorebi/src/static_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use hotwatch::Hotwatch;
use komorebi_core::config_generation::ApplicationConfigurationGenerator;
use komorebi_core::config_generation::ApplicationOptions;
use komorebi_core::config_generation::IdWithIdentifier;
use komorebi_core::config_generation::MatchingStrategy;
use komorebi_core::ApplicationIdentifier;
use komorebi_core::DefaultLayout;
use komorebi_core::FocusFollowsMouseImplementation;
Expand Down Expand Up @@ -139,6 +140,7 @@ impl From<&Workspace> for WorkspaceConfig {
let rule = IdWithIdentifier {
kind: ApplicationIdentifier::Exe,
id: identifier.clone(),
matching_strategy: None,
};

if *is_initial {
Expand Down Expand Up @@ -433,7 +435,7 @@ impl From<&WindowManager> for StaticConfig {

impl StaticConfig {
#[allow(clippy::cognitive_complexity, clippy::too_many_lines)]
fn apply_globals(&self) -> Result<()> {
fn apply_globals(&mut self) -> Result<()> {
if let Some(monitor_index_preferences) = &self.monitor_index_preferences {
let mut preferences = MONITOR_INDEX_PREFERENCES.lock();
*preferences = monitor_index_preferences.clone();
Expand Down Expand Up @@ -508,10 +510,14 @@ impl StaticConfig {
let mut object_name_change_identifiers = OBJECT_NAME_CHANGE_ON_LAUNCH.lock();
let mut layered_identifiers = LAYERED_WHITELIST.lock();

if let Some(float) = &self.float_rules {
if let Some(float) = &mut self.float_rules {
for identifier in float {
if !float_identifiers.contains(&identifier.id) {
float_identifiers.push(identifier.id.clone());
if identifier.matching_strategy.is_none() {
identifier.matching_strategy = Option::from(MatchingStrategy::Legacy);
}

if !float_identifiers.contains(identifier) {
float_identifiers.push(identifier.clone());
}
}
}
Expand Down Expand Up @@ -569,8 +575,14 @@ impl StaticConfig {
for entry in asc {
if let Some(float) = entry.float_identifiers {
for f in float {
if !float_identifiers.contains(&f.id) {
float_identifiers.push(f.id.clone());
let mut without_comment: IdWithIdentifier = f.into();
if without_comment.matching_strategy.is_none() {
without_comment.matching_strategy =
Option::from(MatchingStrategy::Legacy);
}

if !float_identifiers.contains(&without_comment) {
float_identifiers.push(without_comment.clone());
}
}
}
Expand Down Expand Up @@ -620,7 +632,7 @@ impl StaticConfig {
incoming: Arc<Mutex<Receiver<WindowManagerEvent>>>,
) -> Result<WindowManager> {
let content = std::fs::read_to_string(path)?;
let value: Self = serde_json::from_str(&content)?;
let mut value: Self = serde_json::from_str(&content)?;
value.apply_globals()?;

let socket = DATA_DIR.join("komorebi.sock");
Expand Down Expand Up @@ -740,7 +752,7 @@ impl StaticConfig {

pub fn reload(path: &PathBuf, wm: &mut WindowManager) -> Result<()> {
let content = std::fs::read_to_string(path)?;
let value: Self = serde_json::from_str(&content)?;
let mut value: Self = serde_json::from_str(&content)?;

value.apply_globals()?;

Expand Down
51 changes: 41 additions & 10 deletions komorebi/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::sync::atomic::Ordering;

use color_eyre::eyre::anyhow;
use color_eyre::Result;
use komorebi_core::config_generation::MatchingStrategy;
use schemars::JsonSchema;
use serde::ser::Error;
use serde::ser::SerializeStruct;
Expand All @@ -17,6 +18,7 @@ use winput::press;
use winput::release;
use winput::Vk;

use komorebi_core::ApplicationIdentifier;
use komorebi_core::HidingBehaviour;
use komorebi_core::Rect;

Expand Down Expand Up @@ -474,16 +476,45 @@ fn window_is_eligible(
{
let float_identifiers = FLOAT_IDENTIFIERS.lock();
for identifier in float_identifiers.iter() {
if title.starts_with(identifier) || title.ends_with(identifier) {
should_float = true;
}

if class.starts_with(identifier) || class.ends_with(identifier) {
should_float = true;
}

if identifier == exe_name {
should_float = true;
match identifier.matching_strategy {
None => {
panic!("there is no matching strategy identified for this rule");
}
Some(MatchingStrategy::Equals) => match identifier.kind {
ApplicationIdentifier::Title => {
if title.eq(&identifier.id) {
should_float = true;
}
}
ApplicationIdentifier::Class => {
if class.eq(&identifier.id) {
should_float = true;
}
}
ApplicationIdentifier::Exe => {
if exe_name.eq(&identifier.id) {
should_float = true;
}
}
},
Some(MatchingStrategy::Legacy) => match identifier.kind {
ApplicationIdentifier::Title => {
if title.starts_with(&identifier.id) || title.ends_with(&identifier.id) {
should_float = true;
}
}
ApplicationIdentifier::Class => {
if class.starts_with(&identifier.id) || class.ends_with(&identifier.id) {
should_float = true;
}
}
ApplicationIdentifier::Exe => {
if exe_name.eq(&identifier.id) {
should_float = true;
}
}
},
_ => unimplemented!(),
}
}
};
Expand Down
3 changes: 2 additions & 1 deletion komorebi/src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use schemars::JsonSchema;
use serde::Serialize;
use uds_windows::UnixListener;

use komorebi_core::config_generation::IdWithIdentifier;
use komorebi_core::custom_layout::CustomLayout;
use komorebi_core::Arrangement;
use komorebi_core::Axis;
Expand Down Expand Up @@ -93,7 +94,7 @@ pub struct State {
pub mouse_follows_focus: bool,
pub has_pending_raise_op: bool,
pub remove_titlebars: bool,
pub float_identifiers: Vec<String>,
pub float_identifiers: Vec<IdWithIdentifier>,
pub manage_identifiers: Vec<String>,
pub layered_whitelist: Vec<String>,
pub tray_and_multi_window_identifiers: Vec<String>,
Expand Down

0 comments on commit 0797316

Please sign in to comment.