Skip to content

Commit

Permalink
Merge branch 'glzr-io:main' into feat-add-window-transparency-effect
Browse files Browse the repository at this point in the history
  • Loading branch information
jackssrt authored Dec 4, 2024
2 parents d804be9 + ac4ae08 commit e14e363
Show file tree
Hide file tree
Showing 28 changed files with 358 additions and 130 deletions.
84 changes: 57 additions & 27 deletions packages/wm/src/app_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
common::{
commands::{
cycle_focus, disable_binding_mode, enable_binding_mode,
reload_config, shell_exec,
reload_config, shell_exec, toggle_pause,
},
Direction, LengthValue, OpacityValue, RectDelta, TilingDirection,
},
Expand All @@ -26,8 +26,8 @@ use crate::{
windows::{
commands::{
ignore_window, move_window_in_direction, move_window_to_workspace,
resize_window, set_window_position, set_window_position_to_center,
set_window_size, update_window_state,
resize_window, set_window_position, set_window_size,
update_window_state, WindowPositionTarget,
},
traits::WindowGetters,
WindowState,
Expand Down Expand Up @@ -156,6 +156,8 @@ pub enum QueryCommand {
Windows,
/// Outputs all active workspaces.
Workspaces,
/// Outputs whether the window manager is paused.
Paused,
}

#[derive(Clone, Debug, PartialEq, ValueEnum)]
Expand All @@ -176,6 +178,7 @@ pub enum SubscribableEvent {
WorkspaceActivated,
WorkspaceDeactivated,
WorkspaceUpdated,
PauseChanged,
}

#[derive(Clone, Debug, Parser, PartialEq, Serialize)]
Expand Down Expand Up @@ -275,6 +278,7 @@ pub enum InvokeCommand {
WmExit,
WmRedraw,
WmReloadConfig,
WmTogglePause,
}

impl InvokeCommand {
Expand Down Expand Up @@ -451,11 +455,17 @@ impl InvokeCommand {
InvokeCommand::Position(args) => {
match subject_container.as_window_container() {
Ok(window) => match args.centered {
true => set_window_position_to_center(window, state),
true => set_window_position(
window,
WindowPositionTarget::Centered,
state,
),
false => set_window_position(
window,
args.x_pos.clone(),
args.y_pos.clone(),
WindowPositionTarget::Coordinates(
args.x_pos.clone(),
args.y_pos.clone(),
),
state,
),
},
Expand Down Expand Up @@ -484,37 +494,47 @@ impl InvokeCommand {
Ok(window) => {
let floating_defaults =
&config.value.window_behavior.state_defaults.floating;
let is_centered = centered.unwrap_or(floating_defaults.centered);
let centered = centered.unwrap_or(floating_defaults.centered);

let window = update_window_state(
window.clone(),
WindowState::Floating(FloatingStateConfig {
centered: is_centered,
centered,
shown_on_top: shown_on_top
.unwrap_or(floating_defaults.shown_on_top),
}),
state,
config,
)?;

if width.is_some() || height.is_some() {
set_window_size(
window.clone(),
width.clone(),
height.clone(),
state,
)?;
}
// Allow size and position to be set if window has not previously
// been manually placed.
if !window.has_custom_floating_placement() {
if width.is_some() || height.is_some() {
set_window_size(
window.clone(),
width.clone(),
height.clone(),
state,
)?;
}

if is_centered {
set_window_position_to_center(window, state)?;
} else if x_pos.is_some() || y_pos.is_some() {
set_window_position(
window.clone(),
x_pos.clone(),
y_pos.clone(),
state,
)?;
if centered {
set_window_position(
window,
WindowPositionTarget::Centered,
state,
)?;
} else if x_pos.is_some() || y_pos.is_some() {
set_window_position(
window,
WindowPositionTarget::Coordinates(
x_pos.clone(),
y_pos.clone(),
),
state,
)?;
}
}

Ok(())
Expand Down Expand Up @@ -618,19 +638,28 @@ impl InvokeCommand {
let floating_defaults =
&config.value.window_behavior.state_defaults.floating;

let centered = centered.unwrap_or(floating_defaults.centered);
let target_state = WindowState::Floating(FloatingStateConfig {
centered: centered.unwrap_or(floating_defaults.centered),
centered,
shown_on_top: shown_on_top
.unwrap_or(floating_defaults.shown_on_top),
});

update_window_state(
let window = update_window_state(
window.clone(),
window.toggled_state(target_state, config),
state,
config,
)?;

if !window.has_custom_floating_placement() && centered {
set_window_position(
window,
WindowPositionTarget::Centered,
state,
)?;
}

Ok(())
}
_ => Ok(()),
Expand Down Expand Up @@ -728,6 +757,7 @@ impl InvokeCommand {
Ok(())
}
InvokeCommand::WmReloadConfig => reload_config(state, config),
InvokeCommand::WmTogglePause => toggle_pause(state),
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/wm/src/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub fn run_cleanup(managed_windows: Vec<NativeWindow>) {
warn!("Failed to show window: {:?}", err);
}

_ = window.set_taskbar_visibility(true);
_ = window.set_border_color(None);
}
}
2 changes: 2 additions & 0 deletions packages/wm/src/common/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ mod enable_binding_mode;
mod platform_sync;
mod reload_config;
mod shell_exec;
mod toggle_pause;

pub use cycle_focus::*;
pub use disable_binding_mode::*;
pub use enable_binding_mode::*;
pub use platform_sync::*;
pub use reload_config::*;
pub use shell_exec::*;
pub use toggle_pause::*;
23 changes: 22 additions & 1 deletion packages/wm/src/common/commands/platform_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use crate::{
Container, WindowContainer,
},
user_config::{
CornerStyle, CursorJumpTrigger, UserConfig, WindowEffectConfig,
CornerStyle, CursorJumpTrigger, HideMethod, UserConfig,
WindowEffectConfig,
},
windows::traits::WindowGetters,
wm_event::WmEvent,
Expand All @@ -22,6 +23,13 @@ pub fn platform_sync(
state: &mut WmState,
config: &UserConfig,
) -> anyhow::Result<()> {
// Skip platform sync when the WM is paused.
if state.is_paused {
// Clear containers to redraw to avoid leaking memory.
state.pending_sync.containers_to_redraw.clear();
return Ok(());
}

if !state.pending_sync.containers_to_redraw.is_empty() {
redraw_containers(state, config)?;
state.pending_sync.containers_to_redraw.clear();
Expand Down Expand Up @@ -146,6 +154,19 @@ fn redraw_containers(
) {
warn!("Failed to set window position: {}", err);
}

// Skip setting taskbar visibility if the window is hidden (has no
// effect). Since cloaked windows are normally always visible in the
// taskbar, we only need to set visibility if `show_all_in_taskbar` is
// `false`.
if config.value.general.hide_method == HideMethod::Cloak
&& !config.value.general.show_all_in_taskbar
{
if let Err(err) = window.native().set_taskbar_visibility(is_visible)
{
warn!("Failed to set taskbar visibility: {}", err);
}
}
}

Ok(())
Expand Down
13 changes: 12 additions & 1 deletion packages/wm/src/common/commands/reload_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,24 @@ pub fn reload_config(

// Ensure all windows are shown when hide method is changed.
if old_config.general.hide_method != config.value.general.hide_method
&& old_config.general.hide_method == HideMethod::Hide
&& config.value.general.hide_method == HideMethod::Cloak
{
for window in state.windows() {
let _ = window.native().show();
}
}

// Ensure all windows are shown in taskbar when `show_all_in_taskbar` is
// changed.
if old_config.general.show_all_in_taskbar
!= config.value.general.show_all_in_taskbar
&& config.value.general.show_all_in_taskbar
{
for window in state.windows() {
let _ = window.native().set_taskbar_visibility(true);
}
}

// Clear active binding modes.
state.binding_modes = Vec::new();

Expand Down
22 changes: 22 additions & 0 deletions packages/wm/src/common/commands/toggle_pause.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::{wm_event::WmEvent, wm_state::WmState};

/// Pauses or unpauses the WM.
pub fn toggle_pause(state: &mut WmState) -> anyhow::Result<()> {
let new_paused_state = !state.is_paused;
state.is_paused = new_paused_state;

// Redraw full container tree on unpause.
if !new_paused_state {
let root_container = state.root_container.clone();
state
.pending_sync
.containers_to_redraw
.push(root_container.into());
}

state.emit_event(WmEvent::PauseChanged {
is_paused: new_paused_state,
});

Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ pub fn handle_window_location_changed(
// Update state with the new location of the floating window.
info!("Updating floating window position.");
window.set_floating_placement(frame_position);
window.set_has_custom_floating_placement(true);

let monitor = window.monitor().context("No monitor.")?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ pub fn handle_window_moved_or_resized_end(
}
}
WindowContainer::TilingWindow(window) => {
// Don't update state on resize events if the WM is paused.
if state.is_paused {
return Ok(());
}

info!("Tiling window resized");

let parent = window.parent().context("No parent.")?;
Expand Down Expand Up @@ -102,7 +107,7 @@ fn drop_as_tiling_window(
// Get the workspace, split containers, and other windows under the
// dragged window.
let containers_at_pos = state
.containers_at_point(&mouse_pos)
.containers_at_point(workspace.clone().into(), &mouse_pos)
.into_iter()
.filter(|container| container.id() != moved_window.id());

Expand Down
29 changes: 22 additions & 7 deletions packages/wm/src/common/platform/event_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use tokio::sync::mpsc::{self, UnboundedReceiver};

use super::{EventWindow, NativeWindow};
use crate::{
app_command::InvokeCommand,
common::Point,
user_config::{BindingModeConfig, KeybindingConfig, UserConfig},
};
Expand Down Expand Up @@ -63,15 +64,29 @@ impl EventListener {
&mut self,
config: &UserConfig,
binding_modes: &[BindingModeConfig],
paused: bool,
) {
// Modify keybindings based on active binding modes.
let keybindings = match binding_modes.first() {
Some(binding_mode) => &binding_mode.keybindings,
None => &config.value.keybindings,
// Modify keybindings based on active binding modes and paused state.
let keybindings = if paused {
&config
.value
.keybindings
.iter()
.filter(|config| {
config.commands.contains(&InvokeCommand::WmTogglePause)
})
.cloned()
.collect::<Vec<_>>()
} else {
match binding_modes.first() {
Some(binding_mode) => &binding_mode.keybindings,
None => &config.value.keybindings,
}
};

self
.event_window
.update(keybindings, config.value.general.focus_follows_cursor);
self.event_window.update(
keybindings,
config.value.general.focus_follows_cursor && !paused,
);
}
}
14 changes: 9 additions & 5 deletions packages/wm/src/common/platform/event_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ use windows::Win32::{
use super::{
KeyboardHook, MouseMoveEvent, Platform, PlatformEvent, WindowEventHook,
};
use crate::{common::Point, user_config::KeybindingConfig};
use crate::{
common::{platform::FOREGROUND_INPUT_IDENTIFIER, Point},
user_config::KeybindingConfig,
};

/// Global instance of sender for platform events.
///
Expand Down Expand Up @@ -266,13 +269,14 @@ fn handle_input_msg(
)
};

// Ignore if data is invalid or not a mouse event. The `hDevice` check
// ignores programmatic mouse inputs via `SendInput` (this caused issues
// since `NativeWindow::set_foreground` simulates a mouse input).
// Ignore if data is invalid or not a mouse event. Inputs from our own
// process are ignored, which would cause issues since
// `NativeWindow::set_foreground` simulates a mouse input.
if res_size == 0
|| raw_input_size == u32::MAX
|| raw_input.header.dwType != RIM_TYPEMOUSE.0
|| raw_input.header.hDevice.is_invalid()
|| unsafe { raw_input.data.mouse.ulExtraInformation }
== FOREGROUND_INPUT_IDENTIFIER
{
return Ok(());
}
Expand Down
Loading

0 comments on commit e14e363

Please sign in to comment.