Skip to content

Commit

Permalink
feat(taskbar): add with_skip_taskbar for windows and linux (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
lemarier committed Jul 14, 2021
1 parent ff0903f commit e7cdb95
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 43 deletions.
4 changes: 4 additions & 0 deletions .changes/withskip_taskbar_platformext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
"tao": patch
---
Add `with_skip_taskbar` behind `WindowBuilderExtWindows` and `WindowBuilderExtUnix`.
27 changes: 22 additions & 5 deletions examples/system_tray_no_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ fn main() {
use tao::menu::{ContextMenu, MenuItemAttributes};
#[cfg(target_os = "macos")]
use tao::platform::macos::{ActivationPolicy, EventLoopExtMacOS};
#[cfg(target_os = "linux")]
use tao::platform::unix::WindowBuilderExtUnix;
#[cfg(target_os = "windows")]
use tao::platform::windows::WindowBuilderExtWindows;
use tao::{
dpi::LogicalSize,
event::{Event, Rectangle, TrayEvent, WindowEvent},
Expand Down Expand Up @@ -66,6 +70,7 @@ fn main() {
let icon = Path::new(env!("CARGO_MANIFEST_DIR")).join("examples/icon.png");

// linux require a menu so let's add only a open button
#[cfg(target_os = "linux")]
let open_menu_id = MenuId::new("open_menu");
let quit_menu_id = MenuId::new("quit_menu");
#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -99,8 +104,12 @@ fn main() {
}
// if we got a menu event from our `open_menu_id` open a new window..
// (used on linux)
#[cfg(target_os = "linux")]
Event::MenuEvent { menu_id, .. } if menu_id == open_menu_id => {
let window = WindowBuilder::new().build(event_loop).unwrap();
let window = WindowBuilder::new()
.with_skip_taskbar(true)
.build(event_loop)
.unwrap();
windows.insert(window.id(), window);
}
// if we got `Quit` click, exit the app
Expand All @@ -119,13 +128,21 @@ fn main() {
// window size
let window_inner_size = LogicalSize::new(200.0, 200.0);
// create our window
let window = WindowBuilder::new()
let mut window_builder = WindowBuilder::new();
window_builder = window_builder
// position our window centered with tray bounds
.with_position(window_position_center_tray(&mut bounds, window_inner_size).position)
.with_inner_size(window_inner_size)
.with_resizable(false)
.build(event_loop)
.unwrap();
// disallow resize
.with_resizable(false);

// skip taskbar on windows & linux
#[cfg(any(target_os = "linux", target_os = "windows"))]
{
window_builder = window_builder.with_skip_taskbar(true);
}

let window = window_builder.build(event_loop).unwrap();
windows.insert(window.id(), window);
} else {
for window in windows.values() {
Expand Down
16 changes: 14 additions & 2 deletions src/platform/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
))]

pub use crate::platform_impl::hit_test;
use crate::window::Window;
use crate::window::{Window, WindowBuilder};

/// Additional methods on `Window` that are specific to Unix.
pub trait WindowExtUnix {
/// Returns the `ApplicatonWindow` from gtk crate that is used by this window.
fn gtk_window(&self) -> &gtk::ApplicationWindow;

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

Expand All @@ -30,3 +30,15 @@ impl WindowExtUnix for Window {
self.window.set_skip_taskbar(skip);
}
}

pub trait WindowBuilderExtUnix {
/// Whether to create the window icon with the taskbar icon or not.
fn with_skip_taskbar(self, skip: bool) -> WindowBuilder;
}

impl WindowBuilderExtUnix for WindowBuilder {
fn with_skip_taskbar(mut self, skip: bool) -> WindowBuilder {
self.platform_specific.skip_taskbar = skip;
self
}
}
35 changes: 11 additions & 24 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub trait WindowExtWindows {
/// Starts the resizing drag from given edge
fn begin_resize_drag(&self, edge: isize);

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

Expand Down Expand Up @@ -174,29 +174,7 @@ impl WindowExtWindows for Window {

#[inline]
fn set_skip_taskbar(&self, skip: bool) {
use winapi::{
um::{
combaseapi::{CoCreateInstance, CLSCTX_SERVER},
shobjidl_core::{CLSID_TaskbarList, ITaskbarList},
},
Interface,
};
unsafe {
let mut taskbar_list: *mut ITaskbarList = std::mem::zeroed();
CoCreateInstance(
&CLSID_TaskbarList,
std::ptr::null_mut(),
CLSCTX_SERVER,
&ITaskbarList::uuidof(),
&mut taskbar_list as *mut _ as *mut _,
);
if skip {
(*taskbar_list).DeleteTab(self.hwnd() as _);
} else {
(*taskbar_list).AddTab(self.hwnd() as _);
}
(*taskbar_list).Release();
}
self.window.set_skip_taskbar(skip);
}
}

Expand Down Expand Up @@ -247,6 +225,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 to create the window icon with the taskbar icon or not.
fn with_skip_taskbar(self, skip: bool) -> WindowBuilder;
}

impl WindowBuilderExtWindows for WindowBuilder {
Expand Down Expand Up @@ -291,6 +272,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
20 changes: 17 additions & 3 deletions src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ pub use self::{
};
pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget};
pub use monitor::{MonitorHandle, VideoMode};
pub use window::{
hit_test, PlatformIcon, PlatformSpecificWindowBuilderAttributes, Window, WindowId,
};
pub use window::{hit_test, PlatformIcon, Window, WindowId};

use crate::keyboard::Key;

Expand All @@ -42,6 +40,22 @@ pub struct KeyEventExtra {
pub key_without_modifiers: Key<'static>,
}

#[derive(Clone)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub skip_taskbar: bool,
}

impl Default for PlatformSpecificWindowBuilderAttributes {
fn default() -> Self {
Self {
skip_taskbar: false,
}
}
}

unsafe impl Send for PlatformSpecificWindowBuilderAttributes {}
unsafe impl Sync for PlatformSpecificWindowBuilderAttributes {}

#[derive(Debug, Clone)]
pub struct OsError;

Expand Down
19 changes: 12 additions & 7 deletions src/platform_impl/linux/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ use crate::{
window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes},
};

use super::{event_loop::EventLoopWindowTarget, menu, monitor::MonitorHandle};

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {}
use super::{
event_loop::EventLoopWindowTarget, menu, monitor::MonitorHandle,
PlatformSpecificWindowBuilderAttributes,
};

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(pub(crate) u32);
Expand Down Expand Up @@ -99,7 +99,7 @@ impl Window {
pub(crate) fn new<T>(
event_loop_window_target: &EventLoopWindowTarget<T>,
attributes: WindowAttributes,
_pl_attribs: PlatformSpecificWindowBuilderAttributes,
pl_attribs: PlatformSpecificWindowBuilderAttributes,
) -> Result<Self, RootOsError> {
let app = &event_loop_window_target.app;
let window_requests_tx = event_loop_window_target.window_requests_tx.clone();
Expand Down Expand Up @@ -315,7 +315,8 @@ impl Window {
});

window.queue_draw();
Ok(Self {

let win = Self {
window_id,
window,
window_requests_tx,
Expand All @@ -327,7 +328,11 @@ impl Window {
maximized,
minimized,
fullscreen: RefCell::new(attributes.fullscreen),
})
};

win.set_skip_taskbar(pl_attribs.skip_taskbar);

Ok(win)
}

pub fn id(&self) -> WindowId {
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 @@ -45,6 +45,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub parent: Parent,
pub menu: Option<HMENU>,
pub taskbar_icon: Option<Icon>,
pub skip_taskbar: bool,
pub no_redirection_bitmap: bool,
pub drag_and_drop: bool,
pub preferred_theme: Option<Theme>,
Expand All @@ -59,6 +60,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
no_redirection_bitmap: false,
drag_and_drop: true,
preferred_theme: None,
skip_taskbar: false,
}
}
}
Expand Down
27 changes: 25 additions & 2 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ use winapi::{
windef::{self, HWND, POINT, POINTS, RECT},
},
um::{
combaseapi, dwmapi,
combaseapi::{self, CoCreateInstance, CLSCTX_SERVER},
dwmapi,
imm::{CFS_POINT, COMPOSITIONFORM},
libloaderapi,
objbase::COINIT_APARTMENTTHREADED,
ole2,
oleidl::LPDROPTARGET,
shobjidl_core::{CLSID_TaskbarList, ITaskbarList2},
shobjidl_core::{CLSID_TaskbarList, ITaskbarList, ITaskbarList2},
wingdi::{CreateRectRgn, DeleteObject},
winnt::{LPCWSTR, SHORT},
winuser,
Expand Down Expand Up @@ -759,6 +760,26 @@ impl Window {
);
}
}

#[inline]
pub(crate) fn set_skip_taskbar(&self, skip: bool) {
unsafe {
let mut taskbar_list: *mut ITaskbarList = std::mem::zeroed();
CoCreateInstance(
&CLSID_TaskbarList,
std::ptr::null_mut(),
CLSCTX_SERVER,
&ITaskbarList::uuidof(),
&mut taskbar_list as *mut _ as *mut _,
);
if skip {
(*taskbar_list).DeleteTab(self.hwnd() as _);
} else {
(*taskbar_list).AddTab(self.hwnd() as _);
}
(*taskbar_list).Release();
}
}
}

impl Drop for Window {
Expand Down Expand Up @@ -940,6 +961,8 @@ unsafe fn init<T: 'static>(
win.menu = menu::initialize(window_menu, window_handle, menu_handler).map(|m| HMenuWrapper(m));
}

win.set_skip_taskbar(pl_attribs.skip_taskbar);

Ok(win)
}

Expand Down

0 comments on commit e7cdb95

Please sign in to comment.