Skip to content

Commit

Permalink
feat(Windows): add skip taskbar methods (#2177)
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir authored Apr 1, 2022
1 parent 52c4670 commit ab1f636
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 14 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ And please only add new entries to the top of this list, right below the `# Unre

# Unreleased

- On Windows, Added `EventLoopBuilderExtWindows::with_msg_hook`
- On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`.
- On Windows, added `EventLoopBuilderExtWindows::with_msg_hook`.
- On Windows, remove internally unique DC per window.
- macOS: Remove the need to call `set_ime_position` after moving the window.
- Added `Window::is_visible`.
Expand Down
17 changes: 17 additions & 0 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ pub trait WindowExtWindows {

/// Returns the current window theme.
fn theme(&self) -> Theme;

/// Whether to show or hide the window icon in the taskbar.
fn set_skip_taskbar(&self, skip: bool);
}

impl WindowExtWindows for Window {
Expand Down Expand Up @@ -167,6 +170,11 @@ impl WindowExtWindows for Window {
fn theme(&self) -> Theme {
self.window.theme()
}

#[inline]
fn set_skip_taskbar(&self, skip: bool) {
self.window.set_skip_taskbar(skip)
}
}

/// Additional methods on `WindowBuilder` that are specific to Windows.
Expand Down Expand Up @@ -218,6 +226,9 @@ pub trait WindowBuilderExtWindows {

/// Forces a theme or uses the system settings if `None` was provided.
fn with_theme(self, theme: Option<Theme>) -> WindowBuilder;

/// Whether show or hide the window icon in the taskbar.
fn with_skip_taskbar(self, skip: bool) -> WindowBuilder;
}

impl WindowBuilderExtWindows for WindowBuilder {
Expand Down Expand Up @@ -262,6 +273,12 @@ impl WindowBuilderExtWindows for WindowBuilder {
self.platform_specific.preferred_theme = theme;
self
}

#[inline]
fn with_skip_taskbar(mut self, skip: bool) -> WindowBuilder {
self.platform_specific.skip_taskbar = skip;
self
}
}

/// Additional methods on `MonitorHandle` that are specific to Windows.
Expand Down
14 changes: 13 additions & 1 deletion src/platform_impl/windows/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use windows_sys::{
System::Com::{
IAdviseSink, IDataObject, IEnumFORMATETC, IEnumSTATDATA, FORMATETC, STGMEDIUM,
},
UI::Shell::ITaskbarList,
},
};

Expand Down Expand Up @@ -111,6 +110,11 @@ pub struct ITaskbarListVtbl {
pub SetActiveAlt: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT,
}

#[repr(C)]
pub struct ITaskbarList {
pub lpVtbl: *const ITaskbarListVtbl,
}

#[repr(C)]
pub struct ITaskbarList2Vtbl {
pub parent: ITaskbarListVtbl,
Expand All @@ -120,6 +124,7 @@ pub struct ITaskbarList2Vtbl {
fFullscreen: BOOL,
) -> HRESULT,
}

#[repr(C)]
pub struct ITaskbarList2 {
pub lpVtbl: *const ITaskbarList2Vtbl,
Expand All @@ -132,6 +137,13 @@ pub const CLSID_TaskbarList: GUID = GUID {
data4: [0x95, 0x8a, 0x00, 0x60, 0x97, 0xc9, 0xa0, 0x90],
};

pub const IID_ITaskbarList: GUID = GUID {
data1: 0x56FDF342,
data2: 0xFD6D,
data3: 0x11D0,
data4: [0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90],
};

pub const IID_ITaskbarList2: GUID = GUID {
data1: 0x602d4995,
data2: 0xb13a,
Expand Down
2 changes: 2 additions & 0 deletions src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub no_redirection_bitmap: bool,
pub drag_and_drop: bool,
pub preferred_theme: Option<Theme>,
pub skip_taskbar: bool,
}

impl Default for PlatformSpecificWindowBuilderAttributes {
Expand All @@ -46,6 +47,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
no_redirection_bitmap: false,
drag_and_drop: true,
preferred_theme: None,
skip_taskbar: false,
}
}
}
Expand Down
66 changes: 54 additions & 12 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ use crate::{
monitor::MonitorHandle as RootMonitorHandle,
platform_impl::platform::{
dark_mode::try_theme,
definitions::{CLSID_TaskbarList, IID_ITaskbarList2, ITaskbarList2},
definitions::{
CLSID_TaskbarList, IID_ITaskbarList, IID_ITaskbarList2, ITaskbarList, ITaskbarList2,
},
dpi::{dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi},
drop_handler::FileDropHandler,
event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID},
Expand Down Expand Up @@ -665,6 +667,43 @@ impl Window {
self.window_state.lock().current_theme
}

#[inline]
pub fn set_skip_taskbar(&self, skip: bool) {
com_initialized();
unsafe {
TASKBAR_LIST.with(|task_bar_list_ptr| {
let mut task_bar_list = task_bar_list_ptr.get();

if task_bar_list.is_null() {
let hr = CoCreateInstance(
&CLSID_TaskbarList,
ptr::null_mut(),
CLSCTX_ALL,
&IID_ITaskbarList,
&mut task_bar_list as *mut _ as *mut _,
);

let hr_init = (*(*task_bar_list).lpVtbl).HrInit;

if hr != S_OK || hr_init(task_bar_list.cast()) != S_OK {
// In some old windows, the taskbar object could not be created, we just ignore it
return;
}
task_bar_list_ptr.set(task_bar_list)
}

task_bar_list = task_bar_list_ptr.get();
if skip {
let delete_tab = (*(*task_bar_list).lpVtbl).DeleteTab;
delete_tab(task_bar_list, self.window.0);
} else {
let add_tab = (*(*task_bar_list).lpVtbl).AddTab;
add_tab(task_bar_list, self.window.0);
}
});
}
}

#[inline]
pub fn focus_window(&self) {
let window = self.window.clone();
Expand Down Expand Up @@ -839,6 +878,8 @@ impl<'a, T: 'static> InitData<'a, T> {
DeleteObject(region);
}

win.set_skip_taskbar(self.pl_attribs.skip_taskbar);

let attributes = self.attributes.clone();

// Set visible before setting the size to ensure the
Expand Down Expand Up @@ -999,7 +1040,8 @@ thread_local! {
}
};

static TASKBAR_LIST: Cell<*mut ITaskbarList2> = Cell::new(ptr::null_mut());
static TASKBAR_LIST: Cell<*mut ITaskbarList> = Cell::new(ptr::null_mut());
static TASKBAR_LIST2: Cell<*mut ITaskbarList2> = Cell::new(ptr::null_mut());
}

pub fn com_initialized() {
Expand All @@ -1017,30 +1059,30 @@ pub fn com_initialized() {
unsafe fn taskbar_mark_fullscreen(handle: HWND, fullscreen: bool) {
com_initialized();

TASKBAR_LIST.with(|task_bar_list_ptr| {
let mut task_bar_list = task_bar_list_ptr.get();
TASKBAR_LIST2.with(|task_bar_list2_ptr| {
let mut task_bar_list2 = task_bar_list2_ptr.get();

if task_bar_list.is_null() {
if task_bar_list2.is_null() {
let hr = CoCreateInstance(
&CLSID_TaskbarList,
ptr::null_mut(),
CLSCTX_ALL,
&IID_ITaskbarList2,
&mut task_bar_list as *mut _ as *mut _,
&mut task_bar_list2 as *mut _ as *mut _,
);

let hr_init = (*(*task_bar_list).lpVtbl).parent.HrInit;
let hr_init = (*(*task_bar_list2).lpVtbl).parent.HrInit;

if hr != S_OK || hr_init(task_bar_list.cast()) != S_OK {
if hr != S_OK || hr_init(task_bar_list2.cast()) != S_OK {
// In some old windows, the taskbar object could not be created, we just ignore it
return;
}
task_bar_list_ptr.set(task_bar_list)
task_bar_list2_ptr.set(task_bar_list2)
}

task_bar_list = task_bar_list_ptr.get();
let mark_fullscreen_window = (*(*task_bar_list).lpVtbl).MarkFullscreenWindow;
mark_fullscreen_window(task_bar_list, handle, if fullscreen { 1 } else { 0 });
task_bar_list2 = task_bar_list2_ptr.get();
let mark_fullscreen_window = (*(*task_bar_list2).lpVtbl).MarkFullscreenWindow;
mark_fullscreen_window(task_bar_list2, handle, if fullscreen { 1 } else { 0 });
})
}

Expand Down

0 comments on commit ab1f636

Please sign in to comment.