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
- 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`.

View file

@ -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 {
@ -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.
@ -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 {
@ -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.

View file

@ -10,7 +10,6 @@ use windows_sys::{
System::Com::{
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,
}
#[repr(C)]
pub struct ITaskbarList {
pub lpVtbl: *const ITaskbarListVtbl,
}
#[repr(C)]
pub struct ITaskbarList2Vtbl {
pub parent: ITaskbarListVtbl,
@ -120,6 +124,7 @@ pub struct ITaskbarList2Vtbl {
fFullscreen: BOOL,
) -> HRESULT,
}
#[repr(C)]
pub struct ITaskbarList2 {
pub lpVtbl: *const ITaskbarList2Vtbl,
@ -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,

View file

@ -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 {
@ -46,6 +47,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
no_redirection_bitmap: false,
drag_and_drop: true,
preferred_theme: None,
skip_taskbar: false,
}
}
}

View file

@ -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},
@ -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();
@ -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
@ -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() {
@ -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 });
})
}