From 99018669626acb2fffbdb3cb729563529b04a4fa Mon Sep 17 00:00:00 2001 From: rawnly Date: Thu, 30 Nov 2023 03:04:08 +0100 Subject: [PATCH] macos: floating window logic cleanup --- config/src/keyassignment.rs | 11 ++++++-- wezterm-gui/src/commands.rs | 23 ++++++++++++---- wezterm-gui/src/termwindow/mod.rs | 46 ++++++++++++------------------- window/src/lib.rs | 7 +++++ window/src/os/macos/window.rs | 9 +----- 5 files changed, 51 insertions(+), 45 deletions(-) diff --git a/config/src/keyassignment.rs b/config/src/keyassignment.rs index ec64bda1c..ae1cc84fa 100644 --- a/config/src/keyassignment.rs +++ b/config/src/keyassignment.rs @@ -501,13 +501,20 @@ fn default_fuzzy_description() -> String { "Fuzzy matching: ".to_string() } +// FIXME: this is so ugly we should use `window::WindowLevel` instead +#[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)] +pub enum SetWindowLevelLevel { + Normal, + AlwaysOnTop, + AlwaysOnBottom, +} + #[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)] pub enum KeyAssignment { SpawnTab(SpawnTabDomain), SpawnWindow, ToggleFullScreen, - ToggleAlwaysOnTop, - ToggleAlwaysOnBottom, + SetWindowLevel(SetWindowLevelLevel), CopyTo(ClipboardCopyDestination), CopyTextTo { text: String, diff --git a/wezterm-gui/src/commands.rs b/wezterm-gui/src/commands.rs index 747b16fc4..3d79d885c 100644 --- a/wezterm-gui/src/commands.rs +++ b/wezterm-gui/src/commands.rs @@ -681,20 +681,28 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option CommandDef { + SetWindowLevel(SetWindowLevelLevel::AlwaysOnTop) => CommandDef { brief: "Always on Top".into(), doc: "Toggles the window between floating and non-floating states to stay on top of other windows.".into(), keys: vec![], args: &[ArgType::ActiveWindow], - menubar: &["Window"], + menubar: &["Window", "Level"], icon: None, }, - ToggleAlwaysOnBottom => CommandDef { + SetWindowLevel(SetWindowLevelLevel::Normal) => CommandDef { + brief: "Normal".into(), + doc: "Set window level to normal".into(), + keys: vec![], + args: &[ArgType::ActiveWindow], + menubar: &["Window", "Level"], + icon: None, + }, + SetWindowLevel(SetWindowLevelLevel::AlwaysOnBottom) => CommandDef { brief: "Always on Bottom".into(), doc: "Toggles the window to remain behind all other windows.".into(), keys: vec![], args: &[ArgType::ActiveWindow], - menubar: &["Window"], + menubar: &["Window", "Level"], icon: None, }, Hide => CommandDef { @@ -2032,8 +2040,11 @@ fn compute_default_actions() -> Vec { ScrollToBottom, // ----------------- Window ToggleFullScreen, - ToggleAlwaysOnTop, - ToggleAlwaysOnBottom, + + SetWindowLevel(SetWindowLevelLevel::AlwaysOnBottom), + SetWindowLevel(SetWindowLevelLevel::Normal), + SetWindowLevel(SetWindowLevelLevel::AlwaysOnTop), + Hide, Search(Pattern::CurrentSelectionOrEmptyString), PaneSelect(PaneSelectArguments { diff --git a/wezterm-gui/src/termwindow/mod.rs b/wezterm-gui/src/termwindow/mod.rs index b83660790..99f04acd0 100644 --- a/wezterm-gui/src/termwindow/mod.rs +++ b/wezterm-gui/src/termwindow/mod.rs @@ -30,7 +30,7 @@ use ::window::*; use anyhow::{anyhow, ensure, Context}; use config::keyassignment::{ KeyAssignment, PaneDirection, Pattern, PromptInputLine, QuickSelectArguments, - RotationDirection, SpawnCommand, SplitSize, + RotationDirection, SpawnCommand, SplitSize, SetWindowLevelLevel, }; use config::{ configuration, AudibleBell, ConfigHandle, Dimension, DimensionContext, FrontEndSelection, @@ -2507,45 +2507,33 @@ impl TermWindow { ToggleFullScreen => { self.window.as_ref().unwrap().toggle_fullscreen(); } - // TODO: check what happens if we enable always on top when is always on bottom - ToggleAlwaysOnBottom => { + SetWindowLevel(level) => { let window = self.window.clone().unwrap(); let is_always_on_top = self.window_state.intersects(WindowState::ALWAYS_ON_TOP); let is_always_on_bottom = self.window_state.intersects(WindowState::ALWAYS_ON_BOTTOM); - // check if always on top is enabled. - // if it is, disable it to prevent impossible state. if is_always_on_top { self.window_state -= WindowState::ALWAYS_ON_TOP; - } + } if is_always_on_bottom { - window.set_window_level(WindowLevel::Normal); self.window_state -= WindowState::ALWAYS_ON_BOTTOM; - } else { - window.set_window_level(WindowLevel::AlwaysOnBottom); - self.window_state = self.window_state | WindowState::ALWAYS_ON_BOTTOM; + } + + match level { + SetWindowLevelLevel::AlwaysOnTop => { + window.set_window_level(WindowLevel::AlwaysOnTop); + self.window_state = self.window_state | WindowState::ALWAYS_ON_TOP; + } + SetWindowLevelLevel::AlwaysOnBottom => { + window.set_window_level(WindowLevel::AlwaysOnBottom); + self.window_state = self.window_state | WindowState::ALWAYS_ON_BOTTOM; + } + SetWindowLevelLevel::Normal => { + window.set_window_level(WindowLevel::Normal); + } } }, - ToggleAlwaysOnTop => { - let window = self.window.clone().unwrap(); - let is_always_on_top = self.window_state.intersects(WindowState::ALWAYS_ON_TOP); - let is_always_on_bottom = self.window_state.intersects(WindowState::ALWAYS_ON_BOTTOM); - - // check if always on bottom is enabled. - // if it is, disable it to prevent impossible state. - if is_always_on_bottom { - self.window_state -= WindowState::ALWAYS_ON_BOTTOM; - } - - if is_always_on_top { - window.set_window_level(WindowLevel::Normal); - self.window_state -= WindowState::ALWAYS_ON_TOP; - } else { - window.set_window_level(WindowLevel::AlwaysOnTop); - self.window_state = self.window_state | WindowState::ALWAYS_ON_TOP; - } - } CopyTo(dest) => { let text = self.selection_text(pane); self.copy_to_clipboard(*dest, text); diff --git a/window/src/lib.rs b/window/src/lib.rs index 74e1a70c7..d3ccd2ec5 100644 --- a/window/src/lib.rs +++ b/window/src/lib.rs @@ -71,6 +71,13 @@ pub enum MouseCursor { SizeLeftRight, } +#[derive(Debug)] +pub enum WindowLevel { + AlwaysOnBottom = -1, + Normal = 0, + AlwaysOnTop = 3, +} + /// Represents the preferred appearance of the windowing /// environment. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/window/src/os/macos/window.rs b/window/src/os/macos/window.rs index ed2c1f585..95bc4f3ae 100644 --- a/window/src/os/macos/window.rs +++ b/window/src/os/macos/window.rs @@ -8,7 +8,7 @@ use crate::connection::ConnectionOps; use crate::os::macos::menu::{MenuItem, RepresentedItem}; use crate::parameters::{Border, Parameters, TitleBar}; use crate::{ - Clipboard, Connection, DeadKeyStatus, Dimensions, Handled, KeyCode, KeyEvent, Modifiers, + Clipboard, WindowLevel, Connection, DeadKeyStatus, Dimensions, Handled, KeyCode, KeyEvent, Modifiers, MouseButtons, MouseCursor, MouseEvent, MouseEventKind, MousePress, Point, RawKeyEvent, Rect, RequestedWindowGeometry, ResolvedGeometry, ScreenPoint, Size, ULength, WindowDecorations, WindowEvent, WindowEventSender, WindowOps, WindowState, @@ -1078,13 +1078,6 @@ impl WindowInner { /// @see https://developer.apple.com/documentation/appkit/nswindow/level -#[derive(Debug)] -pub enum WindowLevel { - AlwaysOnBottom = -1, - Normal = 0, - AlwaysOnTop = 3, -} - impl WindowInner { fn show(&mut self) {