diff --git a/komorebi-bar/src/main.rs b/komorebi-bar/src/main.rs index 7053502e..af0dfffa 100644 --- a/komorebi-bar/src/main.rs +++ b/komorebi-bar/src/main.rs @@ -103,7 +103,7 @@ fn process_hwnd() -> Option { } pub enum KomorebiEvent { - Notification(komorebi_client::Notification), + Notification(Box), Reconnect, } @@ -381,7 +381,7 @@ fn main() -> color_eyre::Result<()> { Ok(notification) => { tracing::debug!("received notification from komorebi"); - if let Err(error) = tx_gui.send(KomorebiEvent::Notification(notification)) { + if let Err(error) = tx_gui.send(KomorebiEvent::Notification(Box::new(notification))) { tracing::error!("could not send komorebi notification update to gui thread: {error}") } diff --git a/komorebi-client/src/lib.rs b/komorebi-client/src/lib.rs index 86de081a..62625be8 100644 --- a/komorebi-client/src/lib.rs +++ b/komorebi-client/src/lib.rs @@ -7,7 +7,6 @@ pub use komorebi::AspectRatio; pub use komorebi::BorderColours; pub use komorebi::Colour; pub use komorebi::CrossBoundaryBehaviour; -pub use komorebi::GlobalState; pub use komorebi::KomorebiTheme; pub use komorebi::MonitorConfig; pub use komorebi::Notification; @@ -16,7 +15,6 @@ pub use komorebi::PredefinedAspectRatio; pub use komorebi::Rgb; pub use komorebi::RuleDebug; pub use komorebi::StackbarConfig; -pub use komorebi::State; pub use komorebi::StaticConfig; pub use komorebi::SubscribeOptions; pub use komorebi::TabsConfig; @@ -68,6 +66,8 @@ pub use komorebi::core::replace_env_in_path; pub use komorebi::monitor::Monitor; pub use komorebi::monitor_reconciliator::MonitorNotification; pub use komorebi::ring::Ring; +pub use komorebi::state::GlobalState; +pub use komorebi::state::State; pub use komorebi::win32_display_data; pub use komorebi::window::Window; pub use komorebi::window_manager_event::WindowManagerEvent; diff --git a/komorebi/src/lib.rs b/komorebi/src/lib.rs index f4e3baba..0b9d6fa0 100644 --- a/komorebi/src/lib.rs +++ b/komorebi/src/lib.rs @@ -17,6 +17,7 @@ pub mod process_movement; pub mod reaper; pub mod set_window_position; pub mod stackbar_manager; +pub mod state; pub mod static_config; pub mod styles; pub mod theme_manager; @@ -70,6 +71,7 @@ use parking_lot::RwLock; use regex::Regex; use serde::Deserialize; use serde::Serialize; +use state::State; use uds_windows::UnixStream; use which::which; use winreg::RegKey; diff --git a/komorebi/src/main.rs b/komorebi/src/main.rs index 75785482..65d7307b 100644 --- a/komorebi/src/main.rs +++ b/komorebi/src/main.rs @@ -50,10 +50,10 @@ use komorebi::process_event::listen_for_events; use komorebi::process_movement::listen_for_movements; use komorebi::reaper; use komorebi::stackbar_manager; +use komorebi::state::State; use komorebi::static_config::StaticConfig; use komorebi::theme_manager; use komorebi::transparency_manager; -use komorebi::window_manager::State; use komorebi::window_manager::WindowManager; use komorebi::windows_api::WindowsApi; use komorebi::winevent_listener; diff --git a/komorebi/src/monitor_reconciliator/mod.rs b/komorebi/src/monitor_reconciliator/mod.rs index a96417ef..755e463b 100644 --- a/komorebi/src/monitor_reconciliator/mod.rs +++ b/komorebi/src/monitor_reconciliator/mod.rs @@ -4,7 +4,6 @@ use crate::DISPLAY_INDEX_PREFERENCES; use crate::DUPLICATE_MONITOR_SERIAL_IDS; use crate::Notification; use crate::NotificationEvent; -use crate::State; use crate::WORKSPACE_MATCHING_RULES; use crate::WindowManager; use crate::WindowsApi; @@ -15,6 +14,7 @@ use crate::monitor; use crate::monitor::Monitor; use crate::monitor_reconciliator::hidden::Hidden; use crate::notify_subscribers; +use crate::state::State; use crossbeam_channel::Receiver; use crossbeam_channel::Sender; use crossbeam_utils::atomic::AtomicConsume; diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index f4b8a5cd..a057fd5b 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -24,7 +24,6 @@ use crate::CUSTOM_FFM; use crate::DATA_DIR; use crate::DISPLAY_INDEX_PREFERENCES; use crate::FLOATING_APPLICATIONS; -use crate::GlobalState; use crate::HIDING_BEHAVIOUR; use crate::IGNORE_IDENTIFIERS; use crate::INITIAL_CONFIGURATION_LOADED; @@ -40,7 +39,6 @@ use crate::SESSION_FLOATING_APPLICATIONS; use crate::SUBSCRIPTION_PIPES; use crate::SUBSCRIPTION_SOCKET_OPTIONS; use crate::SUBSCRIPTION_SOCKETS; -use crate::State; use crate::TCP_CONNECTIONS; use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS; use crate::WINDOWS_11; @@ -81,12 +79,14 @@ use crate::notify_subscribers; use crate::stackbar_manager; use crate::stackbar_manager::STACKBAR_FONT_FAMILY; use crate::stackbar_manager::STACKBAR_FONT_SIZE; +use crate::state; +use crate::state::GlobalState; +use crate::state::State; use crate::static_config::StaticConfig; use crate::theme_manager; use crate::transparency_manager; use crate::window::RuleDebug; use crate::window::Window; -use crate::window_manager; use crate::window_manager::WindowManager; use crate::windows_api::WindowsApi; use crate::winevent_listener; @@ -1358,8 +1358,7 @@ impl WindowManager { self.set_workspace_name(monitor_idx, workspace_idx, name.to_string())?; } SocketMessage::State => { - let state = match serde_json::to_string_pretty(&window_manager::State::from(&*self)) - { + let state = match serde_json::to_string_pretty(&state::State::from(&*self)) { Ok(state) => state, Err(error) => error.to_string(), }; diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index ca20989d..1c4208fe 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -19,7 +19,6 @@ use crate::Layout; use crate::Notification; use crate::NotificationEvent; use crate::REGEX_IDENTIFIERS; -use crate::State; use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS; use crate::VirtualDesktopNotification; use crate::Window; @@ -29,6 +28,7 @@ use crate::border_manager::BORDER_WIDTH; use crate::current_virtual_desktop; use crate::notify_subscribers; use crate::stackbar_manager; +use crate::state::State; use crate::transparency_manager; use crate::window::RuleDebug; use crate::window::should_act; diff --git a/komorebi/src/state.rs b/komorebi/src/state.rs new file mode 100644 index 00000000..700db806 --- /dev/null +++ b/komorebi/src/state.rs @@ -0,0 +1,306 @@ +use crate::BorderColours; +use crate::BorderStyle; +use crate::CURRENT_VIRTUAL_DESKTOP; +use crate::CUSTOM_FFM; +use crate::DATA_DIR; +use crate::DISPLAY_INDEX_PREFERENCES; +use crate::DUPLICATE_MONITOR_SERIAL_IDS; +use crate::FocusFollowsMouseImplementation; +use crate::HIDING_BEHAVIOUR; +use crate::HOME_DIR; +use crate::HidingBehaviour; +use crate::IGNORE_IDENTIFIERS; +use crate::LAYERED_WHITELIST; +use crate::MANAGE_IDENTIFIERS; +use crate::MONITOR_INDEX_PREFERENCES; +use crate::MoveBehaviour; +use crate::OBJECT_NAME_CHANGE_ON_LAUNCH; +use crate::OperationBehaviour; +use crate::REMOVE_TITLEBARS; +use crate::Rect; +use crate::StackbarLabel; +use crate::StackbarMode; +use crate::TRANSPARENCY_BLACKLIST; +use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS; +use crate::WORKSPACE_MATCHING_RULES; +use crate::WindowContainerBehaviour; +use crate::WindowManager; +use crate::border_manager; +use crate::border_manager::STYLE; +use crate::config_generation::MatchingRule; +use crate::config_generation::WorkspaceMatchingRule; +use crate::monitor::Monitor; +use crate::ring::Ring; +use crate::stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR; +use crate::stackbar_manager::STACKBAR_LABEL; +use crate::stackbar_manager::STACKBAR_MODE; +use crate::stackbar_manager::STACKBAR_TAB_BACKGROUND_COLOUR; +use crate::stackbar_manager::STACKBAR_TAB_HEIGHT; +use crate::stackbar_manager::STACKBAR_TAB_WIDTH; +use crate::stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR; +use crate::transparency_manager::TRANSPARENCY_ALPHA; +use crate::transparency_manager::TRANSPARENCY_ENABLED; +use crate::workspace::Workspace; +use komorebi_themes::colour::Colour; +use komorebi_themes::colour::Rgb; +use serde::Deserialize; +use serde::Serialize; +use std::collections::HashMap; +use std::collections::VecDeque; +use std::path::PathBuf; +use std::sync::atomic::Ordering; + +#[allow(clippy::struct_excessive_bools)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +pub struct State { + pub monitors: Ring, + pub monitor_usr_idx_map: HashMap, + pub is_paused: bool, + pub resize_delta: i32, + pub new_window_behaviour: WindowContainerBehaviour, + pub float_override: bool, + pub cross_monitor_move_behaviour: MoveBehaviour, + pub unmanaged_window_operation_behaviour: OperationBehaviour, + pub work_area_offset: Option, + pub focus_follows_mouse: Option, + pub mouse_follows_focus: bool, + pub has_pending_raise_op: bool, + pub virtual_desktop_id: Option>, +} + +impl State { + pub fn has_been_modified(&self, wm: &WindowManager) -> bool { + let new = Self::from(wm); + + if self.monitors != new.monitors { + return true; + } + + if self.is_paused != new.is_paused { + return true; + } + + if self.new_window_behaviour != new.new_window_behaviour { + return true; + } + + if self.float_override != new.float_override { + return true; + } + + if self.cross_monitor_move_behaviour != new.cross_monitor_move_behaviour { + return true; + } + + if self.unmanaged_window_operation_behaviour != new.unmanaged_window_operation_behaviour { + return true; + } + + if self.work_area_offset != new.work_area_offset { + return true; + } + + if self.focus_follows_mouse != new.focus_follows_mouse { + return true; + } + + if self.mouse_follows_focus != new.mouse_follows_focus { + return true; + } + + if self.has_pending_raise_op != new.has_pending_raise_op { + return true; + } + + false + } +} + +#[allow(clippy::struct_excessive_bools)] +#[derive(Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +pub struct GlobalState { + pub border_enabled: bool, + pub border_colours: BorderColours, + pub border_style: BorderStyle, + pub border_offset: i32, + pub border_width: i32, + pub stackbar_mode: StackbarMode, + pub stackbar_label: StackbarLabel, + pub stackbar_focused_text_colour: Colour, + pub stackbar_unfocused_text_colour: Colour, + pub stackbar_tab_background_colour: Colour, + pub stackbar_tab_width: i32, + pub stackbar_height: i32, + pub transparency_enabled: bool, + pub transparency_alpha: u8, + pub transparency_blacklist: Vec, + pub remove_titlebars: bool, + #[serde(alias = "float_identifiers")] + pub ignore_identifiers: Vec, + pub manage_identifiers: Vec, + pub layered_whitelist: Vec, + pub tray_and_multi_window_identifiers: Vec, + pub name_change_on_launch_identifiers: Vec, + pub monitor_index_preferences: HashMap, + pub display_index_preferences: HashMap, + pub ignored_duplicate_monitor_serial_ids: Vec, + pub workspace_rules: Vec, + pub window_hiding_behaviour: HidingBehaviour, + pub configuration_dir: PathBuf, + pub data_dir: PathBuf, + pub custom_ffm: bool, + pub current_virtual_desktop_id: Option>, +} + +impl Default for GlobalState { + fn default() -> Self { + Self { + border_enabled: border_manager::BORDER_ENABLED.load(Ordering::SeqCst), + border_colours: BorderColours { + single: Option::from(Colour::Rgb(Rgb::from( + border_manager::FOCUSED.load(Ordering::SeqCst), + ))), + stack: Option::from(Colour::Rgb(Rgb::from( + border_manager::STACK.load(Ordering::SeqCst), + ))), + monocle: Option::from(Colour::Rgb(Rgb::from( + border_manager::MONOCLE.load(Ordering::SeqCst), + ))), + floating: Option::from(Colour::Rgb(Rgb::from( + border_manager::FLOATING.load(Ordering::SeqCst), + ))), + unfocused: Option::from(Colour::Rgb(Rgb::from( + border_manager::UNFOCUSED.load(Ordering::SeqCst), + ))), + unfocused_locked: Option::from(Colour::Rgb(Rgb::from( + border_manager::UNFOCUSED_LOCKED.load(Ordering::SeqCst), + ))), + }, + border_style: STYLE.load(), + border_offset: border_manager::BORDER_OFFSET.load(Ordering::SeqCst), + border_width: border_manager::BORDER_WIDTH.load(Ordering::SeqCst), + stackbar_mode: STACKBAR_MODE.load(), + stackbar_label: STACKBAR_LABEL.load(), + stackbar_focused_text_colour: Colour::Rgb(Rgb::from( + STACKBAR_FOCUSED_TEXT_COLOUR.load(Ordering::SeqCst), + )), + stackbar_unfocused_text_colour: Colour::Rgb(Rgb::from( + STACKBAR_UNFOCUSED_TEXT_COLOUR.load(Ordering::SeqCst), + )), + stackbar_tab_background_colour: Colour::Rgb(Rgb::from( + STACKBAR_TAB_BACKGROUND_COLOUR.load(Ordering::SeqCst), + )), + stackbar_tab_width: STACKBAR_TAB_WIDTH.load(Ordering::SeqCst), + stackbar_height: STACKBAR_TAB_HEIGHT.load(Ordering::SeqCst), + transparency_enabled: TRANSPARENCY_ENABLED.load(Ordering::SeqCst), + transparency_alpha: TRANSPARENCY_ALPHA.load(Ordering::SeqCst), + transparency_blacklist: TRANSPARENCY_BLACKLIST.lock().clone(), + remove_titlebars: REMOVE_TITLEBARS.load(Ordering::SeqCst), + ignore_identifiers: IGNORE_IDENTIFIERS.lock().clone(), + manage_identifiers: MANAGE_IDENTIFIERS.lock().clone(), + layered_whitelist: LAYERED_WHITELIST.lock().clone(), + tray_and_multi_window_identifiers: TRAY_AND_MULTI_WINDOW_IDENTIFIERS.lock().clone(), + name_change_on_launch_identifiers: OBJECT_NAME_CHANGE_ON_LAUNCH.lock().clone(), + monitor_index_preferences: MONITOR_INDEX_PREFERENCES.lock().clone(), + display_index_preferences: DISPLAY_INDEX_PREFERENCES.read().clone(), + ignored_duplicate_monitor_serial_ids: DUPLICATE_MONITOR_SERIAL_IDS.read().clone(), + workspace_rules: WORKSPACE_MATCHING_RULES.lock().clone(), + window_hiding_behaviour: *HIDING_BEHAVIOUR.lock(), + configuration_dir: HOME_DIR.clone(), + data_dir: DATA_DIR.clone(), + custom_ffm: CUSTOM_FFM.load(Ordering::SeqCst), + current_virtual_desktop_id: CURRENT_VIRTUAL_DESKTOP.lock().clone(), + } + } +} + +impl From<&WindowManager> for State { + fn from(wm: &WindowManager) -> Self { + // This is used to remove any information that doesn't need to be passed on to subscribers + // or to be shown with the `komorebic state` command. Currently it is only removing the + // `workspace_config` field from every workspace, but more stripping can be added later if + // needed. + let mut stripped_monitors = Ring::default(); + *stripped_monitors.elements_mut() = wm + .monitors() + .iter() + .map(|monitor| Monitor { + id: monitor.id, + name: monitor.name.clone(), + device: monitor.device.clone(), + device_id: monitor.device_id.clone(), + serial_number_id: monitor.serial_number_id.clone(), + size: monitor.size, + work_area_size: monitor.work_area_size, + work_area_offset: monitor.work_area_offset, + window_based_work_area_offset: monitor.window_based_work_area_offset, + window_based_work_area_offset_limit: monitor.window_based_work_area_offset_limit, + workspaces: { + let mut ws = Ring::default(); + *ws.elements_mut() = monitor + .workspaces() + .iter() + .map(|workspace| Workspace { + name: workspace.name.clone(), + containers: workspace.containers.clone(), + monocle_container: workspace.monocle_container.clone(), + monocle_container_restore_idx: workspace.monocle_container_restore_idx, + maximized_window: workspace.maximized_window, + maximized_window_restore_idx: workspace.maximized_window_restore_idx, + floating_windows: workspace.floating_windows.clone(), + layout: workspace.layout.clone(), + layout_options: workspace.layout_options, + layout_rules: workspace.layout_rules.clone(), + layout_flip: workspace.layout_flip, + workspace_padding: workspace.workspace_padding, + container_padding: workspace.container_padding, + latest_layout: workspace.latest_layout.clone(), + resize_dimensions: workspace.resize_dimensions.clone(), + tile: workspace.tile, + work_area_offset: workspace.work_area_offset, + apply_window_based_work_area_offset: workspace + .apply_window_based_work_area_offset, + window_container_behaviour: workspace.window_container_behaviour, + window_container_behaviour_rules: workspace + .window_container_behaviour_rules + .clone(), + float_override: workspace.float_override, + layer: workspace.layer, + floating_layer_behaviour: workspace.floating_layer_behaviour, + globals: workspace.globals, + wallpaper: workspace.wallpaper.clone(), + workspace_config: None, + }) + .collect::>(); + ws.focus(monitor.workspaces.focused_idx()); + ws + }, + last_focused_workspace: monitor.last_focused_workspace, + workspace_names: monitor.workspace_names.clone(), + container_padding: monitor.container_padding, + workspace_padding: monitor.workspace_padding, + wallpaper: monitor.wallpaper.clone(), + floating_layer_behaviour: monitor.floating_layer_behaviour, + }) + .collect::>(); + stripped_monitors.focus(wm.monitors.focused_idx()); + + Self { + monitors: stripped_monitors, + monitor_usr_idx_map: wm.monitor_usr_idx_map.clone(), + is_paused: wm.is_paused, + work_area_offset: wm.work_area_offset, + resize_delta: wm.resize_delta, + new_window_behaviour: wm.window_management_behaviour.current_behaviour, + float_override: wm.window_management_behaviour.float_override, + cross_monitor_move_behaviour: wm.cross_monitor_move_behaviour, + focus_follows_mouse: wm.focus_follows_mouse, + mouse_follows_focus: wm.mouse_follows_focus, + has_pending_raise_op: wm.has_pending_raise_op, + unmanaged_window_operation_behaviour: wm.unmanaged_window_operation_behaviour, + virtual_desktop_id: wm.virtual_desktop_id.clone(), + } + } +} diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 86603a16..c3e2662b 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -19,8 +19,6 @@ use hotwatch::EventKind; use hotwatch::Hotwatch; use hotwatch::notify::ErrorKind as NotifyErrorKind; use parking_lot::Mutex; -use serde::Deserialize; -use serde::Serialize; use uds_windows::UnixListener; use uds_windows::UnixStream; @@ -30,69 +28,40 @@ use crate::animation::AnimationEngine; use crate::core::Arrangement; use crate::core::Axis; use crate::core::BorderImplementation; -use crate::core::BorderStyle; use crate::core::CycleDirection; use crate::core::DefaultLayout; use crate::core::FocusFollowsMouseImplementation; -use crate::core::HidingBehaviour; use crate::core::Layout; use crate::core::MoveBehaviour; use crate::core::OperationBehaviour; use crate::core::OperationDirection; use crate::core::Rect; use crate::core::Sizing; -use crate::core::StackbarLabel; use crate::core::WindowContainerBehaviour; use crate::core::WindowManagementBehaviour; use crate::core::config_generation::MatchingRule; use crate::core::custom_layout::CustomLayout; -use crate::BorderColours; -use crate::CUSTOM_FFM; -use crate::Colour; use crate::CrossBoundaryBehaviour; use crate::DATA_DIR; -use crate::DISPLAY_INDEX_PREFERENCES; -use crate::DUPLICATE_MONITOR_SERIAL_IDS; -use crate::HIDING_BEHAVIOUR; use crate::HOME_DIR; -use crate::IGNORE_IDENTIFIERS; -use crate::LAYERED_WHITELIST; -use crate::MANAGE_IDENTIFIERS; -use crate::MONITOR_INDEX_PREFERENCES; use crate::NO_TITLEBAR; -use crate::OBJECT_NAME_CHANGE_ON_LAUNCH; use crate::REGEX_IDENTIFIERS; -use crate::REMOVE_TITLEBARS; -use crate::Rgb; use crate::SUBSCRIPTION_SOCKETS; -use crate::TRANSPARENCY_BLACKLIST; -use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS; use crate::WORKSPACE_MATCHING_RULES; use crate::border_manager; use crate::border_manager::BORDER_OFFSET; use crate::border_manager::BORDER_WIDTH; -use crate::border_manager::STYLE; -use crate::config_generation::WorkspaceMatchingRule; use crate::container::Container; -use crate::core::StackbarMode; use crate::current_virtual_desktop; use crate::load_configuration; use crate::monitor::Monitor; use crate::ring::Ring; use crate::should_act; use crate::should_act_individual; -use crate::stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR; -use crate::stackbar_manager::STACKBAR_LABEL; -use crate::stackbar_manager::STACKBAR_MODE; -use crate::stackbar_manager::STACKBAR_TAB_BACKGROUND_COLOUR; -use crate::stackbar_manager::STACKBAR_TAB_HEIGHT; -use crate::stackbar_manager::STACKBAR_TAB_WIDTH; -use crate::stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR; +use crate::state::State; use crate::static_config::StaticConfig; use crate::transparency_manager; -use crate::transparency_manager::TRANSPARENCY_ALPHA; -use crate::transparency_manager::TRANSPARENCY_ENABLED; use crate::window::Window; use crate::window_manager_event::WindowManagerEvent; use crate::windows_api::WindowsApi; @@ -125,263 +94,12 @@ pub struct WindowManager { pub known_hwnds: HashMap, } -#[allow(clippy::struct_excessive_bools)] -#[derive(Clone, Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -pub struct State { - pub monitors: Ring, - pub monitor_usr_idx_map: HashMap, - pub is_paused: bool, - pub resize_delta: i32, - pub new_window_behaviour: WindowContainerBehaviour, - pub float_override: bool, - pub cross_monitor_move_behaviour: MoveBehaviour, - pub unmanaged_window_operation_behaviour: OperationBehaviour, - pub work_area_offset: Option, - pub focus_follows_mouse: Option, - pub mouse_follows_focus: bool, - pub has_pending_raise_op: bool, -} - -impl State { - pub fn has_been_modified(&self, wm: &WindowManager) -> bool { - let new = Self::from(wm); - - if self.monitors != new.monitors { - return true; - } - - if self.is_paused != new.is_paused { - return true; - } - - if self.new_window_behaviour != new.new_window_behaviour { - return true; - } - - if self.float_override != new.float_override { - return true; - } - - if self.cross_monitor_move_behaviour != new.cross_monitor_move_behaviour { - return true; - } - - if self.unmanaged_window_operation_behaviour != new.unmanaged_window_operation_behaviour { - return true; - } - - if self.work_area_offset != new.work_area_offset { - return true; - } - - if self.focus_follows_mouse != new.focus_follows_mouse { - return true; - } - - if self.mouse_follows_focus != new.mouse_follows_focus { - return true; - } - - if self.has_pending_raise_op != new.has_pending_raise_op { - return true; - } - - false - } -} - -#[allow(clippy::struct_excessive_bools)] -#[derive(Debug, Serialize, Deserialize)] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -pub struct GlobalState { - pub border_enabled: bool, - pub border_colours: BorderColours, - pub border_style: BorderStyle, - pub border_offset: i32, - pub border_width: i32, - pub stackbar_mode: StackbarMode, - pub stackbar_label: StackbarLabel, - pub stackbar_focused_text_colour: Colour, - pub stackbar_unfocused_text_colour: Colour, - pub stackbar_tab_background_colour: Colour, - pub stackbar_tab_width: i32, - pub stackbar_height: i32, - pub transparency_enabled: bool, - pub transparency_alpha: u8, - pub transparency_blacklist: Vec, - pub remove_titlebars: bool, - #[serde(alias = "float_identifiers")] - pub ignore_identifiers: Vec, - pub manage_identifiers: Vec, - pub layered_whitelist: Vec, - pub tray_and_multi_window_identifiers: Vec, - pub name_change_on_launch_identifiers: Vec, - pub monitor_index_preferences: HashMap, - pub display_index_preferences: HashMap, - pub ignored_duplicate_monitor_serial_ids: Vec, - pub workspace_rules: Vec, - pub window_hiding_behaviour: HidingBehaviour, - pub configuration_dir: PathBuf, - pub data_dir: PathBuf, - pub custom_ffm: bool, -} - -impl Default for GlobalState { - fn default() -> Self { - Self { - border_enabled: border_manager::BORDER_ENABLED.load(Ordering::SeqCst), - border_colours: BorderColours { - single: Option::from(Colour::Rgb(Rgb::from( - border_manager::FOCUSED.load(Ordering::SeqCst), - ))), - stack: Option::from(Colour::Rgb(Rgb::from( - border_manager::STACK.load(Ordering::SeqCst), - ))), - monocle: Option::from(Colour::Rgb(Rgb::from( - border_manager::MONOCLE.load(Ordering::SeqCst), - ))), - floating: Option::from(Colour::Rgb(Rgb::from( - border_manager::FLOATING.load(Ordering::SeqCst), - ))), - unfocused: Option::from(Colour::Rgb(Rgb::from( - border_manager::UNFOCUSED.load(Ordering::SeqCst), - ))), - unfocused_locked: Option::from(Colour::Rgb(Rgb::from( - border_manager::UNFOCUSED_LOCKED.load(Ordering::SeqCst), - ))), - }, - border_style: STYLE.load(), - border_offset: border_manager::BORDER_OFFSET.load(Ordering::SeqCst), - border_width: border_manager::BORDER_WIDTH.load(Ordering::SeqCst), - stackbar_mode: STACKBAR_MODE.load(), - stackbar_label: STACKBAR_LABEL.load(), - stackbar_focused_text_colour: Colour::Rgb(Rgb::from( - STACKBAR_FOCUSED_TEXT_COLOUR.load(Ordering::SeqCst), - )), - stackbar_unfocused_text_colour: Colour::Rgb(Rgb::from( - STACKBAR_UNFOCUSED_TEXT_COLOUR.load(Ordering::SeqCst), - )), - stackbar_tab_background_colour: Colour::Rgb(Rgb::from( - STACKBAR_TAB_BACKGROUND_COLOUR.load(Ordering::SeqCst), - )), - stackbar_tab_width: STACKBAR_TAB_WIDTH.load(Ordering::SeqCst), - stackbar_height: STACKBAR_TAB_HEIGHT.load(Ordering::SeqCst), - transparency_enabled: TRANSPARENCY_ENABLED.load(Ordering::SeqCst), - transparency_alpha: TRANSPARENCY_ALPHA.load(Ordering::SeqCst), - transparency_blacklist: TRANSPARENCY_BLACKLIST.lock().clone(), - remove_titlebars: REMOVE_TITLEBARS.load(Ordering::SeqCst), - ignore_identifiers: IGNORE_IDENTIFIERS.lock().clone(), - manage_identifiers: MANAGE_IDENTIFIERS.lock().clone(), - layered_whitelist: LAYERED_WHITELIST.lock().clone(), - tray_and_multi_window_identifiers: TRAY_AND_MULTI_WINDOW_IDENTIFIERS.lock().clone(), - name_change_on_launch_identifiers: OBJECT_NAME_CHANGE_ON_LAUNCH.lock().clone(), - monitor_index_preferences: MONITOR_INDEX_PREFERENCES.lock().clone(), - display_index_preferences: DISPLAY_INDEX_PREFERENCES.read().clone(), - ignored_duplicate_monitor_serial_ids: DUPLICATE_MONITOR_SERIAL_IDS.read().clone(), - workspace_rules: WORKSPACE_MATCHING_RULES.lock().clone(), - window_hiding_behaviour: *HIDING_BEHAVIOUR.lock(), - configuration_dir: HOME_DIR.clone(), - data_dir: DATA_DIR.clone(), - custom_ffm: CUSTOM_FFM.load(Ordering::SeqCst), - } - } -} - impl AsRef for WindowManager { fn as_ref(&self) -> &Self { self } } -impl From<&WindowManager> for State { - fn from(wm: &WindowManager) -> Self { - // This is used to remove any information that doesn't need to be passed on to subscribers - // or to be shown with the `komorebic state` command. Currently it is only removing the - // `workspace_config` field from every workspace, but more stripping can be added later if - // needed. - let mut stripped_monitors = Ring::default(); - *stripped_monitors.elements_mut() = wm - .monitors() - .iter() - .map(|monitor| Monitor { - id: monitor.id, - name: monitor.name.clone(), - device: monitor.device.clone(), - device_id: monitor.device_id.clone(), - serial_number_id: monitor.serial_number_id.clone(), - size: monitor.size, - work_area_size: monitor.work_area_size, - work_area_offset: monitor.work_area_offset, - window_based_work_area_offset: monitor.window_based_work_area_offset, - window_based_work_area_offset_limit: monitor.window_based_work_area_offset_limit, - workspaces: { - let mut ws = Ring::default(); - *ws.elements_mut() = monitor - .workspaces() - .iter() - .map(|workspace| Workspace { - name: workspace.name.clone(), - containers: workspace.containers.clone(), - monocle_container: workspace.monocle_container.clone(), - monocle_container_restore_idx: workspace.monocle_container_restore_idx, - maximized_window: workspace.maximized_window, - maximized_window_restore_idx: workspace.maximized_window_restore_idx, - floating_windows: workspace.floating_windows.clone(), - layout: workspace.layout.clone(), - layout_options: workspace.layout_options, - layout_rules: workspace.layout_rules.clone(), - layout_flip: workspace.layout_flip, - workspace_padding: workspace.workspace_padding, - container_padding: workspace.container_padding, - latest_layout: workspace.latest_layout.clone(), - resize_dimensions: workspace.resize_dimensions.clone(), - tile: workspace.tile, - work_area_offset: workspace.work_area_offset, - apply_window_based_work_area_offset: workspace - .apply_window_based_work_area_offset, - window_container_behaviour: workspace.window_container_behaviour, - window_container_behaviour_rules: workspace - .window_container_behaviour_rules - .clone(), - float_override: workspace.float_override, - layer: workspace.layer, - floating_layer_behaviour: workspace.floating_layer_behaviour, - globals: workspace.globals, - wallpaper: workspace.wallpaper.clone(), - workspace_config: None, - }) - .collect::>(); - ws.focus(monitor.workspaces.focused_idx()); - ws - }, - last_focused_workspace: monitor.last_focused_workspace, - workspace_names: monitor.workspace_names.clone(), - container_padding: monitor.container_padding, - workspace_padding: monitor.workspace_padding, - wallpaper: monitor.wallpaper.clone(), - floating_layer_behaviour: monitor.floating_layer_behaviour, - }) - .collect::>(); - stripped_monitors.focus(wm.monitors.focused_idx()); - - Self { - monitors: stripped_monitors, - monitor_usr_idx_map: wm.monitor_usr_idx_map.clone(), - is_paused: wm.is_paused, - work_area_offset: wm.work_area_offset, - resize_delta: wm.resize_delta, - new_window_behaviour: wm.window_management_behaviour.current_behaviour, - float_override: wm.window_management_behaviour.float_override, - cross_monitor_move_behaviour: wm.cross_monitor_move_behaviour, - focus_follows_mouse: wm.focus_follows_mouse, - mouse_follows_focus: wm.mouse_follows_focus, - has_pending_raise_op: wm.has_pending_raise_op, - unmanaged_window_operation_behaviour: wm.unmanaged_window_operation_behaviour, - } - } -} - impl_ring_elements!(WindowManager, Monitor); #[derive(Debug, Clone, Copy)]