Skip to content

Commit ddfbc83

Browse files
committed
enh(wm): improve matching system
1 parent cb9a55f commit ddfbc83

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+527
-465
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- add new cli command to tranlate resource texts.
88

9+
### enhancements
10+
11+
- improve window manager matching system.
12+
913
## [2.4.6]
1014

1115
### features

libs/core/src/state/settings_by_app.rs

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,23 @@ use serde_alias::serde_alias;
55
use ts_rs::TS;
66

77
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
8-
#[serde(rename_all = "snake_case")]
98
#[ts(repr(enum = name))]
109
pub enum AppExtraFlag {
10+
/// Mark this app as non interactive window.
11+
#[serde(alias = "no-interactive")]
12+
NoInteractive,
1113
/// Start the app in the center of the screen as floating in the wm.
12-
Float,
13-
/// Force manage this app in the wm.
14-
Force,
14+
#[serde(alias = "float", alias = "wm-float")]
15+
WmFloat,
16+
/// Forces the management of this app in the wm. (only if it is interactable and not pinned)
17+
#[serde(alias = "force", alias = "wm-force")]
18+
WmForce,
1519
/// Unmanage this app in the wm.
16-
Unmanage,
20+
#[serde(alias = "unmanage", alias = "wm-unmanage")]
21+
WmUnmanage,
1722
/// Pin this app in all the virtual desktops in the wm.
18-
Pinned,
23+
#[serde(alias = "pinned", alias = "vd-pinned")]
24+
VdPinned,
1925
#[serde(other)]
2026
Unknown,
2127
}
@@ -78,7 +84,7 @@ pub struct AppIdentifierCache {
7884
}
7985

8086
impl AppIdentifier {
81-
pub fn perform_cache(&mut self) {
87+
pub fn prepare(&mut self) {
8288
if matches!(self.matching_strategy, MatchingStrategy::Regex) {
8389
let result = Regex::new(&self.id);
8490
if let Ok(re) = result {
@@ -89,8 +95,8 @@ impl AppIdentifier {
8995
self.cache.uppercased_id = Some(self.id.to_uppercase());
9096
}
9197

92-
self.and.iter_mut().for_each(|i| i.perform_cache());
93-
self.or.iter_mut().for_each(|i| i.perform_cache());
98+
self.and.iter_mut().for_each(|i| i.prepare());
99+
self.or.iter_mut().for_each(|i| i.prepare());
94100
}
95101

96102
pub fn uppercased_id(&self) -> &str {
@@ -174,3 +180,48 @@ pub struct AppConfig {
174180
#[serde(default)]
175181
pub is_bundled: bool,
176182
}
183+
184+
impl AppConfig {
185+
pub fn prepare(&mut self) {
186+
self.identifier.prepare();
187+
}
188+
}
189+
190+
#[derive(Debug, Default, Clone)]
191+
pub struct AppsConfigurationList(Vec<AppConfig>);
192+
193+
impl AppsConfigurationList {
194+
pub fn prepare(&mut self) {
195+
self.0.iter_mut().for_each(|config| config.prepare());
196+
}
197+
198+
pub fn search(&self, title: &str, class: &str, exe: &str, path: &str) -> Option<&AppConfig> {
199+
self.0
200+
.iter()
201+
.find(|&config| config.identifier.validate(title, class, exe, path))
202+
}
203+
204+
pub fn iter(&self) -> impl Iterator<Item = &AppConfig> {
205+
self.0.iter()
206+
}
207+
208+
pub fn clear(&mut self) {
209+
self.0.clear();
210+
}
211+
212+
pub fn len(&self) -> usize {
213+
self.0.len()
214+
}
215+
216+
pub fn is_empty(&self) -> bool {
217+
self.0.is_empty()
218+
}
219+
220+
pub fn extend(&mut self, configs: Vec<AppConfig>) {
221+
self.0.extend(configs);
222+
}
223+
224+
pub fn as_slice(&self) -> &[AppConfig] {
225+
&self.0
226+
}
227+
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/background/modules/apps/application/windows.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use seelen_core::system_state::UserAppWindow;
1+
use seelen_core::{state::AppExtraFlag, system_state::UserAppWindow};
22
use windows::Win32::UI::WindowsAndMessaging::{
33
WS_CHILD, WS_EX_APPWINDOW, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_MINIMIZEBOX,
44
};
55

66
use crate::{
77
hook::HookManager,
88
modules::apps::application::{UserAppsEvent, UserAppsManager, USER_APPS_MANAGER},
9+
state::application::FULL_STATE,
910
utils::spawn_named_thread,
1011
windows_api::{
1112
window::{event::WinEvent, Window},
@@ -166,5 +167,12 @@ pub fn is_interactable_and_not_hidden(window: &Window) -> bool {
166167
return false;
167168
}
168169

170+
let guard = FULL_STATE.load();
171+
if let Some(config) = guard.get_app_config_by_window(window.hwnd()) {
172+
if config.options.contains(&AppExtraFlag::NoInteractive) {
173+
return false;
174+
}
175+
}
176+
169177
true
170178
}

src/background/state/application/events.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ impl FullState {
99
pub(super) fn emit_settings_by_app(&self) -> Result<()> {
1010
get_app_handle().emit(
1111
SeelenEvent::StateSettingsByAppChanged,
12-
&self.settings_by_app,
12+
self.settings_by_app.as_slice(),
1313
)?;
1414
Ok(())
1515
}

src/background/state/application/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ use notify_debouncer_full::{
2121
use parking_lot::Mutex;
2222
use seelen_core::{
2323
resource::ResourceKind,
24-
state::{CssStyles, LauncherHistory, Profile, SluPopupConfig, SluPopupContent, WegItems},
24+
state::{
25+
AppsConfigurationList, CssStyles, LauncherHistory, Profile, SluPopupConfig,
26+
SluPopupContent, WegItems,
27+
},
2528
};
2629
use std::{
27-
collections::{HashSet, VecDeque},
30+
collections::HashSet,
2831
path::{Path, PathBuf},
2932
sync::Arc,
3033
time::Duration,
@@ -50,7 +53,7 @@ pub struct FullState {
5053
// ======== data ========
5154
pub profiles: Vec<Profile>,
5255
pub settings: Settings,
53-
pub settings_by_app: VecDeque<AppConfig>,
56+
pub settings_by_app: AppsConfigurationList,
5457
pub weg_items: WegItems,
5558
pub toolbar_items: Placeholder,
5659
pub launcher_history: LauncherHistory,
@@ -67,7 +70,7 @@ impl FullState {
6770
// ======== data ========
6871
profiles: Vec::new(),
6972
settings: Settings::default(),
70-
settings_by_app: VecDeque::new(),
73+
settings_by_app: AppsConfigurationList::default(),
7174
weg_items: WegItems::default(),
7275
toolbar_items: Self::initial_toolbar_items(),
7376
launcher_history: LauncherHistory::default(),
@@ -327,9 +330,7 @@ impl FullState {
327330
self.settings_by_app.extend(apps);
328331
}
329332

330-
self.settings_by_app
331-
.iter_mut()
332-
.for_each(|app| app.identifier.perform_cache());
333+
self.settings_by_app.prepare();
333334
Ok(())
334335
}
335336

src/background/widgets/window_manager/mod.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use state::{WmWorkspaceState, WM_STATE};
1515
use tauri::Emitter;
1616
use windows::Win32::{
1717
Foundation::HWND,
18-
UI::WindowsAndMessaging::{WS_CAPTION, WS_EX_TOPMOST},
18+
UI::WindowsAndMessaging::{WS_EX_TOPMOST, WS_SIZEBOX},
1919
};
2020

2121
use crate::{
@@ -30,27 +30,39 @@ use crate::{
3030
};
3131

3232
impl WindowManagerV2 {
33-
fn is_manageable_window(hwnd: HWND) -> bool {
33+
fn should_be_managed(hwnd: HWND) -> bool {
3434
let window = Window::from(hwnd);
35-
window.is_interactable_and_not_hidden()
36-
// Ignore windows without a title bar, and top most windows normally are widgets or tools so they should not be managed
37-
&& (WindowsApi::get_styles(hwnd).contains(WS_CAPTION) && !WindowsApi::get_ex_styles(hwnd).contains(WS_EX_TOPMOST))
38-
&& !window.is_cloaked()
39-
}
35+
if !window.is_interactable_and_not_hidden() {
36+
return false;
37+
}
4038

41-
fn should_be_managed(hwnd: HWND) -> bool {
4239
if let Some(config) = FULL_STATE.load().get_app_config_by_window(hwnd) {
43-
if config.options.contains(&AppExtraFlag::Force) {
40+
if config.options.contains(&AppExtraFlag::VdPinned) {
41+
return false;
42+
}
43+
44+
if config.options.contains(&AppExtraFlag::WmForce) {
4445
return true;
4546
}
4647

47-
if config.options.contains(&AppExtraFlag::Unmanage)
48-
|| config.options.contains(&AppExtraFlag::Pinned)
49-
{
48+
if config.options.contains(&AppExtraFlag::WmUnmanage) {
5049
return false;
5150
}
5251
}
53-
Self::is_manageable_window(hwnd)
52+
53+
let styles = WindowsApi::get_styles(hwnd);
54+
// Ignore windows that are not resizable
55+
if !styles.contains(WS_SIZEBOX) {
56+
return false;
57+
}
58+
59+
let ex_styles = WindowsApi::get_ex_styles(hwnd);
60+
// Top most windows normally are widgets or tools that should not be managed
61+
if ex_styles.contains(WS_EX_TOPMOST) {
62+
return false;
63+
}
64+
65+
true
5466
}
5567

5668
fn is_managed(window: &Window) -> bool {

src/static/apps_templates/system.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# yaml-language-server: $schema=https://raw.githubusercontent.com/Seelen-Inc/slu-lib/refs/heads/master/gen/schemas/settings_by_app.schema.json
21
- name: Snipping Tool
32
identifier:
43
id: SnippingTool.exe
@@ -73,3 +72,21 @@
7372
matchingStrategy: Equals
7473
options:
7574
- unmanage
75+
76+
- name: System Background Apps
77+
identifier:
78+
id: Windows\SystemApps
79+
kind: Path
80+
matchingStrategy: Contains
81+
options:
82+
- no-interactive
83+
- unmanage
84+
85+
- name: Idle Windows Settings
86+
identifier:
87+
id: Windows\ImmersiveControlPanel
88+
kind: Path
89+
matchingStrategy: Contains
90+
options:
91+
- no-interactive
92+
- unmanage

src/ui/react/settings/i18n/translations/af.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ apps_configurations:
2323
ok_edit: Opdateer
2424
ok_readonly: Wysig as nuut
2525
options:
26-
float: Dryf
27-
force: Kragbestuur
28-
hidden: Verberg van die beskuldigdebalk/taakbalk
29-
pinned: Vasgaan
30-
unmanage: Onhandiging
26+
NoInteractive: Geen interaktief nie
27+
VdPinned: Wys in alle werkruimtes
28+
WmFloat: Twm - Begin dryf
29+
WmForce: Twm - Force Bestuur
30+
WmUnmanage: Twm - Onbestuur
3131
options_label: Ekstra opsies
3232
title_create: Skep {{name}}
3333
title_edit: Redigering {{name}}

src/ui/react/settings/i18n/translations/am.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ apps_configurations:
2323
ok_edit: ዝመና
2424
ok_readonly: እንደ አዲስ ያርትዑ
2525
options:
26-
float: ተንሳፋፊ
27-
force: ኃይል ማስተዳደር
28-
hidden: ከ Dock / Actorbar ይደብቁ
29-
pinned: ተያይ ated ል
30-
unmanage: አለመግባባት
26+
NoInteractive: በይነተገናኝ የለም
27+
VdPinned: በሁሉም የስራ ቦታዎች ውስጥ አሳይ
28+
WmFloat: Twm - ተንሳፋፊ ጅምር
29+
WmForce: Twm - ኃይል ያስተዳድሩ
30+
WmUnmanage: Twm - አለመግባባት
3131
options_label: ተጨማሪ አማራጮች
3232
title_create: '{{{ስም} መፍጠር}}'
3333
title_edit: አርት editing {{ስም}}}

0 commit comments

Comments
 (0)