mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-23 02:16:33 +11:00
On Wayland, implement 'request_user_attention'
This commit implements 'request_user_attention' on Wayland with new 'xdg_activation_v1' protocol.
This commit is contained in:
parent
c9520deef8
commit
b5d0d6ff3e
7 changed files with 133 additions and 81 deletions
|
@ -11,6 +11,7 @@
|
||||||
- On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`.
|
- On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`.
|
||||||
- **Breaking:** On Wayland, Theme trait and its support types are dropped.
|
- **Breaking:** On Wayland, Theme trait and its support types are dropped.
|
||||||
- On Wayland, bump `smithay-client-toolkit` to 0.15.
|
- On Wayland, bump `smithay-client-toolkit` to 0.15.
|
||||||
|
- On Wayland, implement `request_user_attention` with `xdg_activation_v1`.
|
||||||
|
|
||||||
|
|
||||||
# 0.25.0 (2021-05-15)
|
# 0.25.0 (2021-05-15)
|
||||||
|
|
|
@ -19,7 +19,7 @@ targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux
|
||||||
[features]
|
[features]
|
||||||
default = ["x11", "wayland"]
|
default = ["x11", "wayland"]
|
||||||
x11 = ["x11-dl", "mio", "mio-misc", "percent-encoding", "parking_lot"]
|
x11 = ["x11-dl", "mio", "mio-misc", "percent-encoding", "parking_lot"]
|
||||||
wayland = ["wayland-client", "sctk"]
|
wayland = ["wayland-client", "wayland-protocols", "sctk"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
instant = { version = "0.1", features = ["wasm-bindgen"] }
|
||||||
|
@ -83,7 +83,8 @@ features = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
|
||||||
wayland-client = { version = "0.28", features = [ "dlopen"] , optional = true }
|
wayland-client = { version = "0.29", features = [ "dlopen"], optional = true }
|
||||||
|
wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true }
|
||||||
sctk = { package = "smithay-client-toolkit", version = "0.15.0", optional = true }
|
sctk = { package = "smithay-client-toolkit", version = "0.15.0", optional = true }
|
||||||
mio = { version = "0.7", features = ["os-ext"], optional = true }
|
mio = { version = "0.7", features = ["os-ext"], optional = true }
|
||||||
mio-misc = { version = "1.0", optional = true }
|
mio-misc = { version = "1.0", optional = true }
|
||||||
|
|
|
@ -437,12 +437,12 @@ impl Window {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) {
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
Window::X(ref w) => w.request_user_attention(_request_type),
|
Window::X(ref w) => w.request_user_attention(request_type),
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
_ => (),
|
Window::Wayland(ref w) => w.request_user_attention(request_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ use sctk::reexports::protocols::xdg_shell::client::xdg_wm_base::XdgWmBase;
|
||||||
use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1;
|
use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1;
|
||||||
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
|
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
|
||||||
use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
|
use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
|
||||||
|
use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activation_v1::XdgActivationV1;
|
||||||
|
|
||||||
use sctk::environment::{Environment, SimpleGlobal};
|
use sctk::environment::{Environment, SimpleGlobal};
|
||||||
use sctk::output::{OutputHandler, OutputHandling, OutputInfo, OutputStatusListener};
|
use sctk::output::{OutputHandler, OutputHandling, OutputInfo, OutputStatusListener};
|
||||||
|
@ -24,18 +25,27 @@ use sctk::shm::ShmHandler;
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct WindowingFeatures {
|
pub struct WindowingFeatures {
|
||||||
cursor_grab: bool,
|
cursor_grab: bool,
|
||||||
|
xdg_activation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowingFeatures {
|
impl WindowingFeatures {
|
||||||
/// Create `WindowingFeatures` based on the presented interfaces.
|
/// Create `WindowingFeatures` based on the presented interfaces.
|
||||||
pub fn new(env: &Environment<WinitEnv>) -> Self {
|
pub fn new(env: &Environment<WinitEnv>) -> Self {
|
||||||
let cursor_grab = env.get_global::<ZwpPointerConstraintsV1>().is_some();
|
let cursor_grab = env.get_global::<ZwpPointerConstraintsV1>().is_some();
|
||||||
Self { cursor_grab }
|
let xdg_activation = env.get_global::<XdgActivationV1>().is_some();
|
||||||
|
Self {
|
||||||
|
cursor_grab,
|
||||||
|
xdg_activation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor_grab(&self) -> bool {
|
pub fn cursor_grab(&self) -> bool {
|
||||||
self.cursor_grab
|
self.cursor_grab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn xdg_activation(&self) -> bool {
|
||||||
|
self.xdg_activation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sctk::environment!(WinitEnv,
|
sctk::environment!(WinitEnv,
|
||||||
|
@ -50,6 +60,7 @@ sctk::environment!(WinitEnv,
|
||||||
ZwpRelativePointerManagerV1 => relative_pointer_manager,
|
ZwpRelativePointerManagerV1 => relative_pointer_manager,
|
||||||
ZwpPointerConstraintsV1 => pointer_constraints,
|
ZwpPointerConstraintsV1 => pointer_constraints,
|
||||||
ZwpTextInputManagerV3 => text_input_manager,
|
ZwpTextInputManagerV3 => text_input_manager,
|
||||||
|
XdgActivationV1 => xdg_activation,
|
||||||
],
|
],
|
||||||
multis = [
|
multis = [
|
||||||
WlSeat => seats,
|
WlSeat => seats,
|
||||||
|
@ -78,6 +89,8 @@ pub struct WinitEnv {
|
||||||
text_input_manager: SimpleGlobal<ZwpTextInputManagerV3>,
|
text_input_manager: SimpleGlobal<ZwpTextInputManagerV3>,
|
||||||
|
|
||||||
decoration_manager: SimpleGlobal<ZxdgDecorationManagerV1>,
|
decoration_manager: SimpleGlobal<ZxdgDecorationManagerV1>,
|
||||||
|
|
||||||
|
xdg_activation: SimpleGlobal<XdgActivationV1>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitEnv {
|
impl WinitEnv {
|
||||||
|
@ -109,6 +122,9 @@ impl WinitEnv {
|
||||||
// IME handling.
|
// IME handling.
|
||||||
let text_input_manager = SimpleGlobal::new();
|
let text_input_manager = SimpleGlobal::new();
|
||||||
|
|
||||||
|
// Surface activation.
|
||||||
|
let xdg_activation = SimpleGlobal::new();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
seats,
|
seats,
|
||||||
outputs,
|
outputs,
|
||||||
|
@ -120,6 +136,7 @@ impl WinitEnv {
|
||||||
relative_pointer_manager,
|
relative_pointer_manager,
|
||||||
pointer_constraints,
|
pointer_constraints,
|
||||||
text_input_manager,
|
text_input_manager,
|
||||||
|
xdg_activation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::platform_impl::{
|
||||||
MonitorHandle as PlatformMonitorHandle, OsError,
|
MonitorHandle as PlatformMonitorHandle, OsError,
|
||||||
PlatformSpecificWindowBuilderAttributes as PlatformAttributes,
|
PlatformSpecificWindowBuilderAttributes as PlatformAttributes,
|
||||||
};
|
};
|
||||||
use crate::window::{CursorIcon, Fullscreen, WindowAttributes};
|
use crate::window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes};
|
||||||
|
|
||||||
use super::env::WindowingFeatures;
|
use super::env::WindowingFeatures;
|
||||||
use super::event_loop::WinitState;
|
use super::event_loop::WinitState;
|
||||||
|
@ -197,7 +197,12 @@ impl Window {
|
||||||
let window_requests = Arc::new(Mutex::new(Vec::with_capacity(64)));
|
let window_requests = Arc::new(Mutex::new(Vec::with_capacity(64)));
|
||||||
|
|
||||||
// Create a handle that performs all the requests on underlying sctk a window.
|
// Create a handle that performs all the requests on underlying sctk a window.
|
||||||
let window_handle = WindowHandle::new(window, size.clone(), window_requests.clone());
|
let window_handle = WindowHandle::new(
|
||||||
|
&event_loop_window_target.env,
|
||||||
|
window,
|
||||||
|
size.clone(),
|
||||||
|
window_requests.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let mut winit_state = event_loop_window_target.state.borrow_mut();
|
let mut winit_state = event_loop_window_target.state.borrow_mut();
|
||||||
|
|
||||||
|
@ -251,9 +256,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_title(&self, title: &str) {
|
pub fn set_title(&self, title: &str) {
|
||||||
let title_request = WindowRequest::Title(title.to_owned());
|
self.send_request(WindowRequest::Title(title.to_owned()));
|
||||||
self.window_requests.lock().unwrap().push(title_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -285,9 +288,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn request_redraw(&self) {
|
pub fn request_redraw(&self) {
|
||||||
let redraw_request = WindowRequest::Redraw;
|
self.send_request(WindowRequest::Redraw);
|
||||||
self.window_requests.lock().unwrap().push(redraw_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -305,12 +306,7 @@ impl Window {
|
||||||
let size = size.to_logical::<u32>(scale_factor);
|
let size = size.to_logical::<u32>(scale_factor);
|
||||||
*self.size.lock().unwrap() = size;
|
*self.size.lock().unwrap() = size;
|
||||||
|
|
||||||
let frame_size_request = WindowRequest::FrameSize(size);
|
self.send_request(WindowRequest::FrameSize(size));
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(frame_size_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -318,9 +314,7 @@ impl Window {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor() as f64;
|
||||||
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
||||||
|
|
||||||
let min_size_request = WindowRequest::MinSize(size);
|
self.send_request(WindowRequest::MinSize(size));
|
||||||
self.window_requests.lock().unwrap().push(min_size_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -328,19 +322,12 @@ impl Window {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor() as f64;
|
||||||
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
||||||
|
|
||||||
let max_size_request = WindowRequest::MaxSize(size);
|
self.send_request(WindowRequest::MaxSize(size));
|
||||||
self.window_requests.lock().unwrap().push(max_size_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_resizable(&self, resizable: bool) {
|
pub fn set_resizable(&self, resizable: bool) {
|
||||||
let resizeable_request = WindowRequest::Resizeable(resizable);
|
self.send_request(WindowRequest::Resizeable(resizable));
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(resizeable_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -352,9 +339,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_decorations(&self, decorate: bool) {
|
pub fn set_decorations(&self, decorate: bool) {
|
||||||
let decorate_request = WindowRequest::Decorate(decorate);
|
self.send_request(WindowRequest::Decorate(decorate));
|
||||||
self.window_requests.lock().unwrap().push(decorate_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -364,9 +349,7 @@ impl Window {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let minimize_request = WindowRequest::Minimize;
|
self.send_request(WindowRequest::Minimize);
|
||||||
self.window_requests.lock().unwrap().push(minimize_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -376,9 +359,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_maximized(&self, maximized: bool) {
|
pub fn set_maximized(&self, maximized: bool) {
|
||||||
let maximize_request = WindowRequest::Maximize(maximized);
|
self.send_request(WindowRequest::Maximize(maximized));
|
||||||
self.window_requests.lock().unwrap().push(maximize_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -414,31 +395,17 @@ impl Window {
|
||||||
None => WindowRequest::UnsetFullscreen,
|
None => WindowRequest::UnsetFullscreen,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.window_requests
|
self.send_request(fullscreen_request);
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(fullscreen_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
|
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
|
||||||
let cursor_icon_request = WindowRequest::NewCursorIcon(cursor);
|
self.send_request(WindowRequest::NewCursorIcon(cursor));
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(cursor_icon_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cursor_visible(&self, visible: bool) {
|
pub fn set_cursor_visible(&self, visible: bool) {
|
||||||
let cursor_visible_request = WindowRequest::ShowCursor(visible);
|
self.send_request(WindowRequest::ShowCursor(visible));
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(cursor_visible_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -447,16 +414,20 @@ impl Window {
|
||||||
return Err(ExternalError::NotSupported(NotSupportedError::new()));
|
return Err(ExternalError::NotSupported(NotSupportedError::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let cursor_grab_request = WindowRequest::GrabCursor(grab);
|
self.send_request(WindowRequest::GrabCursor(grab));
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(cursor_grab_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
|
if !self.windowing_features.xdg_activation() {
|
||||||
|
warn!("`request_user_attention` isn't supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send_request(WindowRequest::Attention(request_type));
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cursor_position(&self, _: Position) -> Result<(), ExternalError> {
|
pub fn set_cursor_position(&self, _: Position) -> Result<(), ExternalError> {
|
||||||
// XXX This is possible if the locked pointer is being used. We don't have any
|
// XXX This is possible if the locked pointer is being used. We don't have any
|
||||||
|
@ -471,12 +442,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn drag_window(&self) -> Result<(), ExternalError> {
|
pub fn drag_window(&self) -> Result<(), ExternalError> {
|
||||||
let drag_window_request = WindowRequest::DragWindow;
|
self.send_request(WindowRequest::DragWindow);
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(drag_window_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -485,12 +451,7 @@ impl Window {
|
||||||
pub fn set_ime_position(&self, position: Position) {
|
pub fn set_ime_position(&self, position: Position) {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor() as f64;
|
||||||
let position = position.to_logical(scale_factor);
|
let position = position.to_logical(scale_factor);
|
||||||
let ime_position_request = WindowRequest::IMEPosition(position);
|
self.send_request(WindowRequest::IMEPosition(position));
|
||||||
self.window_requests
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(ime_position_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -530,12 +491,16 @@ impl Window {
|
||||||
..WaylandHandle::empty()
|
..WaylandHandle::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn send_request(&self, request: WindowRequest) {
|
||||||
|
self.window_requests.lock().unwrap().push(request);
|
||||||
|
self.event_loop_awakener.ping();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Window {
|
impl Drop for Window {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let close_request = WindowRequest::Close;
|
self.send_request(WindowRequest::Close);
|
||||||
self.window_requests.lock().unwrap().push(close_request);
|
|
||||||
self.event_loop_awakener.ping();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,23 @@ use std::cell::Cell;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use sctk::reexports::client::protocol::wl_output::WlOutput;
|
use sctk::reexports::client::protocol::wl_output::WlOutput;
|
||||||
|
use sctk::reexports::client::Attached;
|
||||||
|
use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activation_token_v1;
|
||||||
|
use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activation_v1::XdgActivationV1;
|
||||||
|
|
||||||
|
use sctk::environment::Environment;
|
||||||
use sctk::window::{Decorations, FallbackFrame, Window};
|
use sctk::window::{Decorations, FallbackFrame, Window};
|
||||||
|
|
||||||
use crate::dpi::{LogicalPosition, LogicalSize};
|
use crate::dpi::{LogicalPosition, LogicalSize};
|
||||||
|
|
||||||
use crate::event::WindowEvent;
|
use crate::event::WindowEvent;
|
||||||
|
use crate::platform_impl::wayland;
|
||||||
|
use crate::platform_impl::wayland::env::WinitEnv;
|
||||||
use crate::platform_impl::wayland::event_loop::WinitState;
|
use crate::platform_impl::wayland::event_loop::WinitState;
|
||||||
use crate::platform_impl::wayland::seat::pointer::WinitPointer;
|
use crate::platform_impl::wayland::seat::pointer::WinitPointer;
|
||||||
use crate::platform_impl::wayland::seat::text_input::TextInputHandler;
|
use crate::platform_impl::wayland::seat::text_input::TextInputHandler;
|
||||||
use crate::platform_impl::wayland::WindowId;
|
use crate::platform_impl::wayland::WindowId;
|
||||||
use crate::window::CursorIcon;
|
use crate::window::{CursorIcon, UserAttentionType};
|
||||||
|
|
||||||
/// A request to SCTK window from Winit window.
|
/// A request to SCTK window from Winit window.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -64,6 +70,11 @@ pub enum WindowRequest {
|
||||||
/// Set IME window position.
|
/// Set IME window position.
|
||||||
IMEPosition(LogicalPosition<u32>),
|
IMEPosition(LogicalPosition<u32>),
|
||||||
|
|
||||||
|
/// Request Attention.
|
||||||
|
///
|
||||||
|
/// `None` unsets the attention request.
|
||||||
|
Attention(Option<UserAttentionType>),
|
||||||
|
|
||||||
/// Redraw was requested.
|
/// Redraw was requested.
|
||||||
Redraw,
|
Redraw,
|
||||||
|
|
||||||
|
@ -150,14 +161,23 @@ pub struct WindowHandle {
|
||||||
|
|
||||||
/// Text inputs on the current surface.
|
/// Text inputs on the current surface.
|
||||||
text_inputs: Vec<TextInputHandler>,
|
text_inputs: Vec<TextInputHandler>,
|
||||||
|
|
||||||
|
/// XdgActivation object.
|
||||||
|
xdg_activation: Option<Attached<XdgActivationV1>>,
|
||||||
|
|
||||||
|
/// Indicator whether user attention is requested.
|
||||||
|
attention_requested: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowHandle {
|
impl WindowHandle {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
env: &Environment<WinitEnv>,
|
||||||
window: Window<FallbackFrame>,
|
window: Window<FallbackFrame>,
|
||||||
size: Arc<Mutex<LogicalSize<u32>>>,
|
size: Arc<Mutex<LogicalSize<u32>>>,
|
||||||
pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>,
|
pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let xdg_activation = env.get_global::<XdgActivationV1>();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
size,
|
size,
|
||||||
|
@ -167,6 +187,8 @@ impl WindowHandle {
|
||||||
cursor_visible: Cell::new(true),
|
cursor_visible: Cell::new(true),
|
||||||
pointers: Vec::new(),
|
pointers: Vec::new(),
|
||||||
text_inputs: Vec::new(),
|
text_inputs: Vec::new(),
|
||||||
|
xdg_activation,
|
||||||
|
attention_requested: Cell::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +210,48 @@ impl WindowHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
|
let xdg_activation = match self.xdg_activation.as_ref() {
|
||||||
|
None => return,
|
||||||
|
Some(xdg_activation) => xdg_activation,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Urgency is only removed by the compositor and there's no need to raise urgency when it
|
||||||
|
// was already raised.
|
||||||
|
if request_type.is_none() || self.attention_requested.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xdg_activation_token = xdg_activation.get_activation_token();
|
||||||
|
let surface = self.window.surface();
|
||||||
|
let window_id = wayland::make_wid(surface);
|
||||||
|
let xdg_activation = xdg_activation.clone();
|
||||||
|
|
||||||
|
xdg_activation_token.quick_assign(move |xdg_token, event, mut dispatch_data| {
|
||||||
|
let token = match event {
|
||||||
|
xdg_activation_token_v1::Event::Done { token } => token,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let winit_state = dispatch_data.get::<WinitState>().unwrap();
|
||||||
|
let window_handle = match winit_state.window_map.get_mut(&window_id) {
|
||||||
|
Some(window_handle) => window_handle,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let surface = window_handle.window.surface();
|
||||||
|
xdg_activation.activate(token, surface);
|
||||||
|
|
||||||
|
// Mark that attention request was done and drop the token.
|
||||||
|
window_handle.attention_requested.replace(false);
|
||||||
|
xdg_token.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
xdg_activation_token.set_surface(surface);
|
||||||
|
xdg_activation_token.commit();
|
||||||
|
self.attention_requested.replace(true);
|
||||||
|
}
|
||||||
|
|
||||||
/// Pointer appeared over the window.
|
/// Pointer appeared over the window.
|
||||||
pub fn pointer_entered(&mut self, pointer: WinitPointer) {
|
pub fn pointer_entered(&mut self, pointer: WinitPointer) {
|
||||||
let position = self.pointers.iter().position(|p| *p == pointer);
|
let position = self.pointers.iter().position(|p| *p == pointer);
|
||||||
|
@ -361,6 +425,9 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
|
||||||
let window_update = window_updates.get_mut(window_id).unwrap();
|
let window_update = window_updates.get_mut(window_id).unwrap();
|
||||||
window_update.refresh_frame = true;
|
window_update.refresh_frame = true;
|
||||||
}
|
}
|
||||||
|
WindowRequest::Attention(request_type) => {
|
||||||
|
window_handle.set_user_attention(request_type);
|
||||||
|
}
|
||||||
WindowRequest::Redraw => {
|
WindowRequest::Redraw => {
|
||||||
let window_update = window_updates.get_mut(window_id).unwrap();
|
let window_update = window_updates.get_mut(window_id).unwrap();
|
||||||
window_update.redraw_requested = true;
|
window_update.redraw_requested = true;
|
||||||
|
|
|
@ -755,9 +755,10 @@ impl Window {
|
||||||
///
|
///
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
/// - **iOS / Android / Web / Wayland:** Unsupported.
|
/// - **iOS / Android / Web :** Unsupported.
|
||||||
/// - **macOS:** `None` has no effect.
|
/// - **macOS:** `None` has no effect.
|
||||||
/// - **X11:** Requests for user attention must be manually cleared.
|
/// - **X11:** Requests for user attention must be manually cleared.
|
||||||
|
/// - **Wayland:** Requires `xdg_activation_v1` protocol, `None` has no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||||
self.window.request_user_attention(request_type)
|
self.window.request_user_attention(request_type)
|
||||||
|
|
Loading…
Add table
Reference in a new issue