Skip to content

Commit

Permalink
feat: Window::set_ignore_cursor_events, closes #184 (#421)
Browse files Browse the repository at this point in the history
* feat: `Window::set_ignore_cursor_events`, closes #184

Co-authored-by: Markus Siglreithmaier <[email protected]>
Co-authored-by: z4122 <[email protected]>
Co-authored-by: Kirill Chibisov <[email protected]>

* linux attempt failed

* changefile

* linux

Co-authored-by: Markus Siglreithmaier <[email protected]>
Co-authored-by: z4122 <[email protected]>
Co-authored-by: Kirill Chibisov <[email protected]>
  • Loading branch information
4 people authored Jun 13, 2022
1 parent f1e8d75 commit 4fa8761
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changes/window_ignore_cursor_events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

Add `Window::set_ignore_cursor_events`
6 changes: 6 additions & 0 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,12 @@ impl Window {
))
}

pub fn set_ignore_cursor_events(&self, _ignore: bool) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(
error::NotSupportedError::new(),
))
}

pub fn raw_window_handle(&self) -> RawWindowHandle {
// TODO: Use main activity instead?
let mut handle = AndroidNdkHandle::empty();
Expand Down
4 changes: 4 additions & 0 deletions src/platform_impl/ios/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ impl Inner {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}

pub fn set_ignore_cursor_events(&self, _ignore: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}

pub fn set_minimized(&self, _minimized: bool) {
warn!("`Window::set_minimized` is ignored on iOS")
}
Expand Down
17 changes: 17 additions & 0 deletions src/platform_impl/linux/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::{
time::Instant,
};

use cairo::{RectangleInt, Region};
use gdk::{Cursor, CursorType, EventKey, EventMask, ScrollDirection, WindowEdge, WindowState};
use gio::{prelude::*, Cancellable};
use glib::{source::Priority, Continue, MainContext};
Expand Down Expand Up @@ -310,6 +311,22 @@ impl<T: 'static> EventLoop<T> {
}
}
}
WindowRequest::CursorIgnoreEvents(ignore) => {
if ignore {
let empty_region = Region::create_rectangle(&RectangleInt {
x: 0,
y: 0,
width: 1,
height: 1,
});
window
.window()
.unwrap()
.input_shape_combine_region(&empty_region, 0, 0);
} else {
window.input_shape_combine_region(None)
};
}
WindowRequest::WireUpEvents => {
window.add_events(
EventMask::POINTER_MOTION_MASK
Expand Down
12 changes: 12 additions & 0 deletions src/platform_impl/linux/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,17 @@ impl Window {
Ok(())
}

pub fn set_ignore_cursor_events(&self, ignore: bool) -> Result<(), ExternalError> {
if let Err(e) = self
.window_requests_tx
.send((self.window_id, WindowRequest::CursorIgnoreEvents(ignore)))
{
log::warn!("Fail to send cursor position request: {}", e);
}

Ok(())
}

pub fn set_cursor_visible(&self, visible: bool) {
let cursor = if visible {
Some(CursorIcon::Default)
Expand Down Expand Up @@ -664,6 +675,7 @@ pub enum WindowRequest {
SetSkipTaskbar(bool),
CursorIcon(Option<CursorIcon>),
CursorPosition((i32, i32)),
CursorIgnoreEvents(bool),
WireUpEvents,
Redraw,
Menu((Option<MenuItem>, Option<MenuId>)),
Expand Down
8 changes: 8 additions & 0 deletions src/platform_impl/macos/util/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,11 @@ pub unsafe fn close_async(ns_window: IdRef) {
});
});
}

// `setIgnoresMouseEvents_:` isn't thread-safe, and fails silently.
pub unsafe fn set_ignore_mouse_events(ns_window: id, ignore: bool) {
let ns_window = MainThreadSafe(ns_window);
Queue::main().exec_async(move || {
ns_window.setIgnoresMouseEvents_(if ignore { YES } else { NO });
});
}
9 changes: 9 additions & 0 deletions src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,15 @@ impl UnownedWindow {
Ok(())
}

#[inline]
pub fn set_ignore_cursor_events(&self, ignore: bool) -> Result<(), ExternalError> {
unsafe {
util::set_ignore_mouse_events(*self.ns_window, ignore);
}

Ok(())
}

pub(crate) fn is_zoomed(&self) -> bool {
// because `isZoomed` doesn't work if the window's borderless,
// we make it resizable temporalily.
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,19 @@ impl Window {
Ok(())
}

#[inline]
pub fn set_ignore_cursor_events(&self, ignore: bool) -> Result<(), ExternalError> {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
self.thread_executor.execute_in_thread(move || {
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
f.set(WindowFlags::IGNORE_CURSOR_EVENT, ignore)
});
});

Ok(())
}

#[inline]
pub fn id(&self) -> WindowId {
WindowId(self.window.0 .0)
Expand Down
5 changes: 5 additions & 0 deletions src/platform_impl/windows/window_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ bitflags! {

const MINIMIZED = 1 << 12;

const IGNORE_CURSOR_EVENT = 1 << 15;

const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits;
const INVISIBLE_AND_MASK = !WindowFlags::MAXIMIZED.bits;
}
Expand Down Expand Up @@ -225,6 +227,9 @@ impl WindowFlags {
if self.contains(WindowFlags::MAXIMIZED) {
style |= WS_MAXIMIZE;
}
if self.contains(WindowFlags::IGNORE_CURSOR_EVENT) {
style_ex |= WS_EX_TRANSPARENT | WS_EX_LAYERED;
}
if self.intersects(
WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN | WindowFlags::MARKER_BORDERLESS_FULLSCREEN,
) {
Expand Down
13 changes: 13 additions & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,19 @@ impl Window {
pub fn drag_window(&self) -> Result<(), ExternalError> {
self.window.drag_window()
}

/// Modifies whether the window catches cursor events.
///
/// If `true`, the events are passed through the window such that any other window behind it receives them.
/// If `false` the window will catch the cursor events. By default cursor events are not ignored.
///
/// ## Platform-specific
///
/// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`]
#[inline]
pub fn set_ignore_cursor_events(&self, ignore: bool) -> Result<(), ExternalError> {
self.window.set_ignore_cursor_events(ignore)
}
}

/// Monitor info functions.
Expand Down

0 comments on commit 4fa8761

Please sign in to comment.