mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
Add 'request_user_attention' to Window
This commit introduces a cross platform way to request a user attention to the window via a 'request_user_attention' method on a Window struct. This method is inspired by macOS's 'request_user_attention' method and thus reuses its signature and semantics to some extent.
This commit is contained in:
parent
f79efec7ef
commit
0861a353d6
|
@ -13,6 +13,9 @@
|
||||||
- On X11, fix `Window::request_redraw` not waking the event loop.
|
- On X11, fix `Window::request_redraw` not waking the event loop.
|
||||||
- On Wayland, the keypad arrow keys are now recognized.
|
- On Wayland, the keypad arrow keys are now recognized.
|
||||||
- **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`.
|
- **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`.
|
||||||
|
- Added `request_user_attention` method to `Window`.
|
||||||
|
- **Breaking:** On macOS, removed `WindowExt::request_user_attention`, use `Window::request_user_attention`.
|
||||||
|
- **Breaking:** On X11, removed `WindowExt::set_urgent`, use `Window::request_user_attention`.
|
||||||
- On Wayland, default font size in CSD increased from 11 to 17.
|
- On Wayland, default font size in CSD increased from 11 to 17.
|
||||||
|
|
||||||
# 0.23.0 (2020-10-02)
|
# 0.23.0 (2020-10-02)
|
||||||
|
|
|
@ -9,26 +9,6 @@ use crate::{
|
||||||
window::{Window, WindowBuilder},
|
window::{Window, WindowBuilder},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Corresponds to `NSRequestUserAttentionType`.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
||||||
pub enum RequestUserAttentionType {
|
|
||||||
/// Corresponds to `NSCriticalRequest`.
|
|
||||||
///
|
|
||||||
/// Dock icon will bounce until the application is focused.
|
|
||||||
Critical,
|
|
||||||
|
|
||||||
/// Corresponds to `NSInformationalRequest`.
|
|
||||||
///
|
|
||||||
/// Dock icon will bounce once.
|
|
||||||
Informational,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for RequestUserAttentionType {
|
|
||||||
fn default() -> Self {
|
|
||||||
RequestUserAttentionType::Critical
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Additional methods on `Window` that are specific to MacOS.
|
/// Additional methods on `Window` that are specific to MacOS.
|
||||||
pub trait WindowExtMacOS {
|
pub trait WindowExtMacOS {
|
||||||
/// Returns a pointer to the cocoa `NSWindow` that is used by this window.
|
/// Returns a pointer to the cocoa `NSWindow` that is used by this window.
|
||||||
|
@ -41,10 +21,6 @@ pub trait WindowExtMacOS {
|
||||||
/// The pointer will become invalid when the `Window` is destroyed.
|
/// The pointer will become invalid when the `Window` is destroyed.
|
||||||
fn ns_view(&self) -> *mut c_void;
|
fn ns_view(&self) -> *mut c_void;
|
||||||
|
|
||||||
/// Request user attention, causing the application's dock icon to bounce.
|
|
||||||
/// Note that this has no effect if the application is already focused.
|
|
||||||
fn request_user_attention(&self, request_type: RequestUserAttentionType);
|
|
||||||
|
|
||||||
/// Returns whether or not the window is in simple fullscreen mode.
|
/// Returns whether or not the window is in simple fullscreen mode.
|
||||||
fn simple_fullscreen(&self) -> bool;
|
fn simple_fullscreen(&self) -> bool;
|
||||||
|
|
||||||
|
@ -75,11 +51,6 @@ impl WindowExtMacOS for Window {
|
||||||
self.window.ns_view()
|
self.window.ns_view()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn request_user_attention(&self, request_type: RequestUserAttentionType) {
|
|
||||||
self.window.request_user_attention(request_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn simple_fullscreen(&self) -> bool {
|
fn simple_fullscreen(&self) -> bool {
|
||||||
self.window.simple_fullscreen()
|
self.window.simple_fullscreen()
|
||||||
|
|
|
@ -213,10 +213,6 @@ pub trait WindowExtUnix {
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
|
fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
|
||||||
|
|
||||||
/// Set window urgency hint (`XUrgencyHint`). Only relevant on X.
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
fn set_urgent(&self, is_urgent: bool);
|
|
||||||
|
|
||||||
/// This function returns the underlying `xcb_connection_t` of an xlib `Display`.
|
/// This function returns the underlying `xcb_connection_t` of an xlib `Display`.
|
||||||
///
|
///
|
||||||
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
|
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
|
||||||
|
@ -297,16 +293,6 @@ impl WindowExtUnix for Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[cfg(feature = "x11")]
|
|
||||||
fn set_urgent(&self, is_urgent: bool) {
|
|
||||||
match self.window {
|
|
||||||
LinuxWindow::X(ref w) => w.set_urgent(is_urgent),
|
|
||||||
#[cfg(feature = "wayland")]
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
fn xcb_connection(&self) -> Option<*mut raw::c_void> {
|
fn xcb_connection(&self) -> Option<*mut raw::c_void> {
|
||||||
|
|
|
@ -484,6 +484,8 @@ impl Window {
|
||||||
|
|
||||||
pub fn set_ime_position(&self, _position: Position) {}
|
pub fn set_ime_position(&self, _position: Position) {}
|
||||||
|
|
||||||
|
pub fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
|
||||||
|
|
||||||
pub fn set_cursor_icon(&self, _: window::CursorIcon) {}
|
pub fn set_cursor_icon(&self, _: window::CursorIcon) {}
|
||||||
|
|
||||||
pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> {
|
pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> {
|
||||||
|
|
|
@ -22,7 +22,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
monitor, view, EventLoopWindowTarget, MonitorHandle,
|
monitor, view, EventLoopWindowTarget, MonitorHandle,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes, WindowId as RootWindowId},
|
window::{
|
||||||
|
CursorIcon, Fullscreen, UserAttentionType, WindowAttributes, WindowId as RootWindowId,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Inner {
|
pub struct Inner {
|
||||||
|
@ -260,6 +262,10 @@ impl Inner {
|
||||||
warn!("`Window::set_ime_position` is ignored on iOS")
|
warn!("`Window::set_ime_position` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) {
|
||||||
|
warn!("`Window::request_user_attention` is ignored on iOS")
|
||||||
|
}
|
||||||
|
|
||||||
// Allow directly accessing the current monitor internally without unwrapping.
|
// Allow directly accessing the current monitor internally without unwrapping.
|
||||||
fn current_monitor_inner(&self) -> RootMonitorHandle {
|
fn current_monitor_inner(&self) -> RootMonitorHandle {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -30,7 +30,7 @@ use crate::{
|
||||||
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
||||||
icon::Icon,
|
icon::Icon,
|
||||||
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
||||||
|
@ -418,6 +418,16 @@ impl Window {
|
||||||
x11_or_wayland!(match self; Window(w) => w.set_ime_position(position))
|
x11_or_wayland!(match self; Window(w) => w.set_ime_position(position))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) {
|
||||||
|
match self {
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
&Window::X(ref w) => w.request_user_attention(_request_type),
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn request_redraw(&self) {
|
pub fn request_redraw(&self) {
|
||||||
x11_or_wayland!(match self; Window(w) => w.request_redraw())
|
x11_or_wayland!(match self; Window(w) => w.request_redraw())
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
MonitorHandle as PlatformMonitorHandle, OsError, PlatformSpecificWindowBuilderAttributes,
|
MonitorHandle as PlatformMonitorHandle, OsError, PlatformSpecificWindowBuilderAttributes,
|
||||||
VideoMode as PlatformVideoMode,
|
VideoMode as PlatformVideoMode,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, Icon, WindowAttributes},
|
window::{CursorIcon, Fullscreen, Icon, UserAttentionType, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ffi, util, EventLoopWindowTarget, ImeSender, WindowId, XConnection, XError};
|
use super::{ffi, util, EventLoopWindowTarget, ImeSender, WindowId, XConnection, XError};
|
||||||
|
@ -523,23 +523,6 @@ impl UnownedWindow {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn set_urgent(&self, is_urgent: bool) {
|
|
||||||
let mut wm_hints = self
|
|
||||||
.xconn
|
|
||||||
.get_wm_hints(self.xwindow)
|
|
||||||
.expect("`XGetWMHints` failed");
|
|
||||||
if is_urgent {
|
|
||||||
(*wm_hints).flags |= ffi::XUrgencyHint;
|
|
||||||
} else {
|
|
||||||
(*wm_hints).flags &= !ffi::XUrgencyHint;
|
|
||||||
}
|
|
||||||
self.xconn
|
|
||||||
.set_wm_hints(self.xwindow, wm_hints)
|
|
||||||
.flush()
|
|
||||||
.expect("Failed to set urgency hint");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_netwm(
|
fn set_netwm(
|
||||||
&self,
|
&self,
|
||||||
operation: util::StateOperation,
|
operation: util::StateOperation,
|
||||||
|
@ -1306,6 +1289,23 @@ impl UnownedWindow {
|
||||||
self.set_ime_position_physical(x, y);
|
self.set_ime_position_physical(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
|
let mut wm_hints = self
|
||||||
|
.xconn
|
||||||
|
.get_wm_hints(self.xwindow)
|
||||||
|
.expect("`XGetWMHints` failed");
|
||||||
|
if request_type.is_some() {
|
||||||
|
(*wm_hints).flags |= ffi::XUrgencyHint;
|
||||||
|
} else {
|
||||||
|
(*wm_hints).flags &= !ffi::XUrgencyHint;
|
||||||
|
}
|
||||||
|
self.xconn
|
||||||
|
.set_wm_hints(self.xwindow, wm_hints)
|
||||||
|
.flush()
|
||||||
|
.expect("Failed to set urgency hint");
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id(&self) -> WindowId {
|
pub fn id(&self) -> WindowId {
|
||||||
WindowId(self.xwindow)
|
WindowId(self.xwindow)
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||||
icon::Icon,
|
icon::Icon,
|
||||||
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
||||||
platform::macos::{ActivationPolicy, RequestUserAttentionType, WindowExtMacOS},
|
platform::macos::{ActivationPolicy, WindowExtMacOS},
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state::AppState,
|
app_state::AppState,
|
||||||
app_state::INTERRUPT_EVENT_LOOP_EXIT,
|
app_state::INTERRUPT_EVENT_LOOP_EXIT,
|
||||||
|
@ -28,7 +28,9 @@ use crate::{
|
||||||
window_delegate::new_delegate,
|
window_delegate::new_delegate,
|
||||||
OsError,
|
OsError,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes, WindowId as RootWindowId},
|
window::{
|
||||||
|
CursorIcon, Fullscreen, UserAttentionType, WindowAttributes, WindowId as RootWindowId,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{
|
appkit::{
|
||||||
|
@ -977,6 +979,19 @@ impl UnownedWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
|
let ns_request_type = request_type.map(|ty| match ty {
|
||||||
|
UserAttentionType::Critical => NSRequestUserAttentionType::NSCriticalRequest,
|
||||||
|
UserAttentionType::Informational => NSRequestUserAttentionType::NSInformationalRequest,
|
||||||
|
});
|
||||||
|
unsafe {
|
||||||
|
if let Some(ty) = ns_request_type {
|
||||||
|
NSApp().requestUserAttention_(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
// Allow directly accessing the current monitor internally without unwrapping.
|
// Allow directly accessing the current monitor internally without unwrapping.
|
||||||
pub(crate) fn current_monitor_inner(&self) -> RootMonitorHandle {
|
pub(crate) fn current_monitor_inner(&self) -> RootMonitorHandle {
|
||||||
|
@ -1030,18 +1045,6 @@ impl WindowExtMacOS for UnownedWindow {
|
||||||
*self.ns_view as *mut _
|
*self.ns_view as *mut _
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn request_user_attention(&self, request_type: RequestUserAttentionType) {
|
|
||||||
unsafe {
|
|
||||||
NSApp().requestUserAttention_(match request_type {
|
|
||||||
RequestUserAttentionType::Critical => NSRequestUserAttentionType::NSCriticalRequest,
|
|
||||||
RequestUserAttentionType::Informational => {
|
|
||||||
NSRequestUserAttentionType::NSInformationalRequest
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn simple_fullscreen(&self) -> bool {
|
fn simple_fullscreen(&self) -> bool {
|
||||||
let shared_state_lock = self.shared_state.lock().unwrap();
|
let shared_state_lock = self.shared_state.lock().unwrap();
|
||||||
|
|
|
@ -3,7 +3,9 @@ use crate::error::{ExternalError, NotSupportedError, OsError as RootOE};
|
||||||
use crate::event;
|
use crate::event;
|
||||||
use crate::icon::Icon;
|
use crate::icon::Icon;
|
||||||
use crate::monitor::MonitorHandle as RootMH;
|
use crate::monitor::MonitorHandle as RootMH;
|
||||||
use crate::window::{CursorIcon, Fullscreen, WindowAttributes, WindowId as RootWI};
|
use crate::window::{
|
||||||
|
CursorIcon, Fullscreen, UserAttentionType, WindowAttributes, WindowId as RootWI,
|
||||||
|
};
|
||||||
|
|
||||||
use raw_window_handle::web::WebHandle;
|
use raw_window_handle::web::WebHandle;
|
||||||
|
|
||||||
|
@ -268,6 +270,11 @@ impl Window {
|
||||||
// Currently a no-op as it does not seem there is good support for this on web
|
// Currently a no-op as it does not seem there is good support for this on web
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) {
|
||||||
|
// Currently an intentional no-op
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
// Allow directly accessing the current monitor internally without unwrapping.
|
// Allow directly accessing the current monitor internally without unwrapping.
|
||||||
fn current_monitor_inner(&self) -> RootMH {
|
fn current_monitor_inner(&self) -> RootMH {
|
||||||
|
|
|
@ -43,7 +43,7 @@ use crate::{
|
||||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||||
PlatformSpecificWindowBuilderAttributes, WindowId,
|
PlatformSpecificWindowBuilderAttributes, WindowId,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The Win32 implementation of the main `Window` object.
|
/// The Win32 implementation of the main `Window` object.
|
||||||
|
@ -621,6 +621,37 @@ impl Window {
|
||||||
warn!("`Window::set_ime_position` is ignored on Windows")
|
warn!("`Window::set_ime_position` is ignored on Windows")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
|
let window = self.window.clone();
|
||||||
|
let active_window_handle = unsafe { winuser::GetActiveWindow() };
|
||||||
|
if window.0 == active_window_handle {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.thread_executor.execute_in_thread(move || unsafe {
|
||||||
|
let (flags, count) = request_type
|
||||||
|
.map(|ty| match ty {
|
||||||
|
UserAttentionType::Critical => {
|
||||||
|
(winuser::FLASHW_ALL | winuser::FLASHW_TIMERNOFG, u32::MAX)
|
||||||
|
}
|
||||||
|
UserAttentionType::Informational => {
|
||||||
|
(winuser::FLASHW_TRAY | winuser::FLASHW_TIMERNOFG, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or((winuser::FLASHW_STOP, 0));
|
||||||
|
|
||||||
|
let mut flash_info = winuser::FLASHWINFO {
|
||||||
|
cbSize: mem::size_of::<winuser::FLASHWINFO>() as UINT,
|
||||||
|
hwnd: window.0,
|
||||||
|
dwFlags: flags,
|
||||||
|
uCount: count,
|
||||||
|
dwTimeout: 0,
|
||||||
|
};
|
||||||
|
winuser::FlashWindowEx(&mut flash_info);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_dark_mode(&self) -> bool {
|
pub fn is_dark_mode(&self) -> bool {
|
||||||
self.window_state.lock().is_dark_mode
|
self.window_state.lock().is_dark_mode
|
||||||
|
|
|
@ -682,6 +682,23 @@ impl Window {
|
||||||
pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
|
pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
|
||||||
self.window.set_ime_position(position.into())
|
self.window.set_ime_position(position.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Requests user attention to the window, this has no effect if the application
|
||||||
|
/// is already focused. How requesting for user attention manifests is platform dependent,
|
||||||
|
/// see `UserAttentionType` for details.
|
||||||
|
///
|
||||||
|
/// Providing `None` will unset the request for user attention. Unsetting the request for
|
||||||
|
/// user attention might not be done automatically by the WM when the window receives input.
|
||||||
|
///
|
||||||
|
/// ## Platform-specific
|
||||||
|
///
|
||||||
|
/// - **iOS / Android / Web / Wayland:** Unsupported.
|
||||||
|
/// - **macOS:** `None` has no effect.
|
||||||
|
/// - **X11:** Requests for user attention must be manually cleared.
|
||||||
|
#[inline]
|
||||||
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
|
self.window.request_user_attention(request_type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cursor functions.
|
/// Cursor functions.
|
||||||
|
@ -874,3 +891,24 @@ pub enum Theme {
|
||||||
Light,
|
Light,
|
||||||
Dark,
|
Dark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ## Platform-specific
|
||||||
|
///
|
||||||
|
/// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between `Critical` and `Informational`.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum UserAttentionType {
|
||||||
|
/// ## Platform-specific
|
||||||
|
/// - **macOS:** Bounces the dock icon until the application is in focus.
|
||||||
|
/// - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
|
||||||
|
Critical,
|
||||||
|
/// ## Platform-specific
|
||||||
|
/// - **macOS:** Bounces the dock icon once.
|
||||||
|
/// - **Windows:** Flashes the taskbar button until the application is in focus.
|
||||||
|
Informational,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for UserAttentionType {
|
||||||
|
fn default() -> Self {
|
||||||
|
UserAttentionType::Informational
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue