diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index 3e6112b45..a8cbd509b 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -88,6 +88,8 @@ pub enum SocketMessage { EnsureWorkspaces(usize, usize), EnsureNamedWorkspaces(usize, Vec), NewWorkspace, + ToggleTaskbar, + Taskbar(bool), ToggleTiling, Stop, TogglePause, diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index f4c00bfc8..e9bdb886b 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -477,6 +477,24 @@ impl WindowManager { SocketMessage::MoveWorkspaceToMonitorNumber(monitor_idx) => { self.move_workspace_to_monitor(monitor_idx)?; } + SocketMessage::ToggleTaskbar => { + let (taskbar, startmenu) = WindowsApi::get_taskbar_handles(); + let is_hidden = WindowsApi::is_taskbar_hidden(taskbar); + if is_hidden { + WindowsApi::hide_taskbar((taskbar, startmenu), true); + } else { + WindowsApi::hide_taskbar((taskbar, startmenu), false); + } + } + SocketMessage::Taskbar(show) => { + let (taskbar, startmenu) = WindowsApi::get_taskbar_handles(); + if show { + WindowsApi::hide_taskbar((taskbar, startmenu), false); + } else { + WindowsApi::hide_taskbar((taskbar, startmenu), true); + } + } + SocketMessage::TogglePause => { if self.is_paused { tracing::info!("resuming"); @@ -717,6 +735,7 @@ impl WindowManager { "received stop command, restoring all hidden windows and terminating process" ); self.restore_all_windows()?; + WindowsApi::hide_taskbar(WindowsApi::get_taskbar_handles(), false); if WindowsApi::focus_follows_mouse()? { WindowsApi::disable_focus_follows_mouse()?; diff --git a/komorebi/src/windows_api.rs b/komorebi/src/windows_api.rs index b4c8339e6..e672d58dc 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -7,7 +7,9 @@ use color_eyre::eyre::anyhow; use color_eyre::eyre::Error; use color_eyre::Result; use widestring::U16CStr; +use windows::core::s; use windows::core::Result as WindowsCrateResult; +use windows::core::PCSTR; use windows::core::PCWSTR; use windows::core::PWSTR; use windows::Win32::Foundation::CloseHandle; @@ -74,6 +76,8 @@ use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow; use windows::Win32::UI::WindowsAndMessaging::BringWindowToTop; use windows::Win32::UI::WindowsAndMessaging::CreateWindowExW; use windows::Win32::UI::WindowsAndMessaging::EnumWindows; +use windows::Win32::UI::WindowsAndMessaging::FindWindowA; +use windows::Win32::UI::WindowsAndMessaging::FindWindowExA; use windows::Win32::UI::WindowsAndMessaging::GetCursorPos; use windows::Win32::UI::WindowsAndMessaging::GetDesktopWindow; use windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow; @@ -119,6 +123,7 @@ use windows::Win32::UI::WindowsAndMessaging::SW_HIDE; use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE; use windows::Win32::UI::WindowsAndMessaging::SW_MINIMIZE; use windows::Win32::UI::WindowsAndMessaging::SW_NORMAL; +use windows::Win32::UI::WindowsAndMessaging::SW_SHOW; use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNOACTIVATE; use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION; use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS; @@ -571,6 +576,29 @@ impl WindowsApi { Self::set_cursor_pos(rect.left + (rect.right / 2), rect.top + (rect.bottom / 2)) } + pub fn get_taskbar_handles() -> (HWND, HWND) { + let taskbar = unsafe { FindWindowA(s!("Shell_TrayWnd"), PCSTR::null()) }; + let startmenu = unsafe { FindWindowExA(taskbar, HWND { 0: 0 }, s!("Button"), s!("Start")) }; + (HWND(taskbar.0), HWND(startmenu.0)) + } + + pub fn is_taskbar_hidden(taskbar_hwnd: HWND) -> bool { + unsafe { IsWindowVisible(taskbar_hwnd) }.as_bool() + } + + pub fn hide_taskbar(taskbar_hwnds: (HWND, HWND), hide: bool) { + unsafe { + if hide { + // 0 hides the taskbar and 5 enables visibility + ShowWindow(taskbar_hwnds.0, SW_HIDE); + ShowWindow(taskbar_hwnds.1, SW_HIDE); + } else { + ShowWindow(taskbar_hwnds.0, SW_SHOW); + ShowWindow(taskbar_hwnds.1, SW_SHOW); + } + } + } + pub fn window_thread_process_id(hwnd: HWND) -> (u32, u32) { let mut process_id: u32 = 0; diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 0afac1188..f73c4618a 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -167,6 +167,7 @@ gen_enum_subcommand_args! { CycleLayout: CycleDirection, WatchConfiguration: BooleanState, MouseFollowsFocus: BooleanState, + Taskbar: BooleanState, Query: StateQuery, WindowHidingBehaviour: HidingBehaviour, CrossMonitorMoveBehaviour: MoveBehaviour, @@ -1052,6 +1053,11 @@ enum SubCommand { /// Set the workspace name for the specified workspace #[clap(arg_required_else_help = true)] WorkspaceName(WorkspaceName), + /// Toggles tasbar visibility + ToggleTaskbar, + /// shows tasbar + #[clap(arg_required_else_help = true)] + Taskbar(Taskbar), /// Toggle the behaviour for new windows (stacking or dynamic tiling) ToggleWindowContainerBehaviour, /// Toggle window tiling on the focused workspace @@ -1993,6 +1999,12 @@ Stop-Process -Name:whkd -ErrorAction SilentlyContinue .as_bytes()?, )?; } + SubCommand::ToggleTaskbar => { + send_message(&SocketMessage::ToggleTaskbar.as_bytes()?)?; + } + SubCommand::Taskbar(arg) => { + send_message(&SocketMessage::Taskbar(arg.boolean_state.into()).as_bytes()?)?; + } SubCommand::MonitorIndexPreference(arg) => { send_message( &SocketMessage::MonitorIndexPreference(