feat(Windows): add skip taskbar methods (#2177)

This commit is contained in:
Amr Bashir 2022-04-01 20:21:09 +02:00 committed by GitHub
parent 52c4670237
commit ab1f636960
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 14 deletions

View file

@ -8,7 +8,8 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased # 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. - On Windows, remove internally unique DC per window.
- macOS: Remove the need to call `set_ime_position` after moving the window. - macOS: Remove the need to call `set_ime_position` after moving the window.
- Added `Window::is_visible`. - Added `Window::is_visible`.

View file

@ -140,6 +140,9 @@ pub trait WindowExtWindows {
/// Returns the current window theme. /// Returns the current window theme.
fn theme(&self) -> 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 { impl WindowExtWindows for Window {
@ -167,6 +170,11 @@ impl WindowExtWindows for Window {
fn theme(&self) -> Theme { fn theme(&self) -> Theme {
self.window.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. /// Additional methods on `WindowBuilder` that are specific to Windows.
@ -218,6 +226,9 @@ pub trait WindowBuilderExtWindows {
/// Forces a theme or uses the system settings if `None` was provided. /// Forces a theme or uses the system settings if `None` was provided.
fn with_theme(self, theme: Option<Theme>) -> WindowBuilder; 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 { impl WindowBuilderExtWindows for WindowBuilder {
@ -262,6 +273,12 @@ impl WindowBuilderExtWindows for WindowBuilder {
self.platform_specific.preferred_theme = theme; self.platform_specific.preferred_theme = theme;
self 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. /// Additional methods on `MonitorHandle` that are specific to Windows.

View file

@ -10,7 +10,6 @@ use windows_sys::{
System::Com::{ System::Com::{
IAdviseSink, IDataObject, IEnumFORMATETC, IEnumSTATDATA, FORMATETC, STGMEDIUM, IAdviseSink, IDataObject, IEnumFORMATETC, IEnumSTATDATA, FORMATETC, STGMEDIUM,
}, },
UI::Shell::ITaskbarList,
}, },
}; };
@ -111,6 +110,11 @@ pub struct ITaskbarListVtbl {
pub SetActiveAlt: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT, pub SetActiveAlt: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT,
} }
#[repr(C)]
pub struct ITaskbarList {
pub lpVtbl: *const ITaskbarListVtbl,
}
#[repr(C)] #[repr(C)]
pub struct ITaskbarList2Vtbl { pub struct ITaskbarList2Vtbl {
pub parent: ITaskbarListVtbl, pub parent: ITaskbarListVtbl,
@ -120,6 +124,7 @@ pub struct ITaskbarList2Vtbl {
fFullscreen: BOOL, fFullscreen: BOOL,
) -> HRESULT, ) -> HRESULT,
} }
#[repr(C)] #[repr(C)]
pub struct ITaskbarList2 { pub struct ITaskbarList2 {
pub lpVtbl: *const ITaskbarList2Vtbl, pub lpVtbl: *const ITaskbarList2Vtbl,
@ -132,6 +137,13 @@ pub const CLSID_TaskbarList: GUID = GUID {
data4: [0x95, 0x8a, 0x00, 0x60, 0x97, 0xc9, 0xa0, 0x90], 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 { pub const IID_ITaskbarList2: GUID = GUID {
data1: 0x602d4995, data1: 0x602d4995,
data2: 0xb13a, data2: 0xb13a,

View file

@ -35,6 +35,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub no_redirection_bitmap: bool, pub no_redirection_bitmap: bool,
pub drag_and_drop: bool, pub drag_and_drop: bool,
pub preferred_theme: Option<Theme>, pub preferred_theme: Option<Theme>,
pub skip_taskbar: bool,
} }
impl Default for PlatformSpecificWindowBuilderAttributes { impl Default for PlatformSpecificWindowBuilderAttributes {
@ -46,6 +47,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
no_redirection_bitmap: false, no_redirection_bitmap: false,
drag_and_drop: true, drag_and_drop: true,
preferred_theme: None, preferred_theme: None,
skip_taskbar: false,
} }
} }
} }

View file

@ -62,7 +62,9 @@ use crate::{
monitor::MonitorHandle as RootMonitorHandle, monitor::MonitorHandle as RootMonitorHandle,
platform_impl::platform::{ platform_impl::platform::{
dark_mode::try_theme, 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}, dpi::{dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi},
drop_handler::FileDropHandler, drop_handler::FileDropHandler,
event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID}, event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID},
@ -665,6 +667,43 @@ impl Window {
self.window_state.lock().current_theme 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] #[inline]
pub fn focus_window(&self) { pub fn focus_window(&self) {
let window = self.window.clone(); let window = self.window.clone();
@ -839,6 +878,8 @@ impl<'a, T: 'static> InitData<'a, T> {
DeleteObject(region); DeleteObject(region);
} }
win.set_skip_taskbar(self.pl_attribs.skip_taskbar);
let attributes = self.attributes.clone(); let attributes = self.attributes.clone();
// Set visible before setting the size to ensure the // Set visible before setting the size to ensure the
@ -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() { pub fn com_initialized() {
@ -1017,30 +1059,30 @@ pub fn com_initialized() {
unsafe fn taskbar_mark_fullscreen(handle: HWND, fullscreen: bool) { unsafe fn taskbar_mark_fullscreen(handle: HWND, fullscreen: bool) {
com_initialized(); com_initialized();
TASKBAR_LIST.with(|task_bar_list_ptr| { TASKBAR_LIST2.with(|task_bar_list2_ptr| {
let mut task_bar_list = task_bar_list_ptr.get(); 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( let hr = CoCreateInstance(
&CLSID_TaskbarList, &CLSID_TaskbarList,
ptr::null_mut(), ptr::null_mut(),
CLSCTX_ALL, CLSCTX_ALL,
&IID_ITaskbarList2, &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 // In some old windows, the taskbar object could not be created, we just ignore it
return; 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(); task_bar_list2 = task_bar_list2_ptr.get();
let mark_fullscreen_window = (*(*task_bar_list).lpVtbl).MarkFullscreenWindow; let mark_fullscreen_window = (*(*task_bar_list2).lpVtbl).MarkFullscreenWindow;
mark_fullscreen_window(task_bar_list, handle, if fullscreen { 1 } else { 0 }); mark_fullscreen_window(task_bar_list2, handle, if fullscreen { 1 } else { 0 });
}) })
} }