expose set_device_event_filter in tauri (#5562)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Closes https://github.com/tauri-apps/tauri/issues/5496
This commit is contained in:
filip 2022-12-13 17:57:32 +01:00 committed by GitHub
parent 5fd4d20e3b
commit 73fd60eef2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 11 deletions

View File

@ -0,0 +1,7 @@
---
"tauri-runtime-wry": minor
"tauri-runtime": minor
"tauri": minor
---
Added `Builder::device_event_filter` and `App::set_device_event_filter` methods.

View File

@ -14,8 +14,8 @@ use tauri_runtime::{
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
CursorIcon, DetachedWindow, FileDropEvent, JsEventListenerKey, PendingWindow, WindowEvent,
},
Dispatch, Error, EventLoopProxy, ExitRequestedEventAction, Icon, Result, RunEvent, RunIteration,
Runtime, RuntimeHandle, UserAttentionType, UserEvent,
DeviceEventFilter, Dispatch, Error, EventLoopProxy, ExitRequestedEventAction, Icon, Result,
RunEvent, RunIteration, Runtime, RuntimeHandle, UserAttentionType, UserEvent,
};
use tauri_runtime::window::MenuEvent;
@ -47,7 +47,8 @@ use wry::{
},
event::{Event, StartCause, WindowEvent as WryWindowEvent},
event_loop::{
ControlFlow, EventLoop, EventLoopProxy as WryEventLoopProxy, EventLoopWindowTarget,
ControlFlow, DeviceEventFilter as WryDeviceEventFilter, EventLoop,
EventLoopProxy as WryEventLoopProxy, EventLoopWindowTarget,
},
menu::{
AboutMetadata as WryAboutMetadata, CustomMenuItem as WryCustomMenuItem, MenuBar,
@ -64,7 +65,6 @@ use wry::{
webview::{FileDropEvent as WryFileDropEvent, WebContext, WebView, WebViewBuilder},
};
pub use wry;
pub use wry::application::window::{Window, WindowBuilder as WryWindowBuilder, WindowId};
#[cfg(windows)]
@ -364,6 +364,18 @@ impl From<MenuItem> for MenuItemWrapper {
}
}
pub struct DeviceEventFilterWrapper(pub WryDeviceEventFilter);
impl From<DeviceEventFilter> for DeviceEventFilterWrapper {
fn from(item: DeviceEventFilter) -> Self {
match item {
DeviceEventFilter::Always => Self(WryDeviceEventFilter::Always),
DeviceEventFilter::Never => Self(WryDeviceEventFilter::Never),
DeviceEventFilter::Unfocused => Self(WryDeviceEventFilter::Unfocused),
}
}
}
#[cfg(target_os = "macos")]
pub struct NativeImageWrapper(pub WryNativeImage);
@ -2055,6 +2067,12 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
self.event_loop.hide_application();
}
fn set_device_event_filter(&mut self, filter: DeviceEventFilter) {
self
.event_loop
.set_device_event_filter(DeviceEventFilterWrapper::from(filter).0);
}
#[cfg(desktop)]
fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) -> RunIteration {
use wry::application::platform::run_return::EventLoopExtRunReturn;

View File

@ -184,6 +184,23 @@ pub enum UserAttentionType {
Informational,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
#[serde(tag = "type")]
pub enum DeviceEventFilter {
/// Always filter out device events.
Always,
/// Filter out device events while the window is not focused.
Unfocused,
/// Report all device events regardless of window focus.
Never,
}
impl Default for DeviceEventFilter {
fn default() -> Self {
Self::Unfocused
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
@ -461,6 +478,19 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn hide(&self);
/// Change the device event filter mode.
///
/// Since the DeviceEvent capture can lead to high CPU usage for unfocused windows, [`tao`]
/// will ignore them by default for unfocused windows on Windows. This method allows changing
/// the filter to explicitly capture them again.
///
/// ## Platform-specific
///
/// - ** Linux / macOS / iOS / Android**: Unsupported.
///
/// [`tao`]: https://crates.io/crates/tao
fn set_device_event_filter(&mut self, filter: DeviceEventFilter);
/// Runs the one step of the webview runtime event loop and returns control flow to the caller.
#[cfg(desktop)]
fn run_iteration<F: Fn(RunEvent<T>) + 'static>(&mut self, callback: F) -> RunIteration;

View File

@ -23,8 +23,8 @@ use crate::{
sealed::{ManagerBase, RuntimeOrDispatch},
utils::config::Config,
utils::{assets::Assets, resources::resource_relpath, Env},
Context, EventLoopMessage, Invoke, InvokeError, InvokeResponse, Manager, Runtime, Scopes,
StateManager, Theme, Window,
Context, DeviceEventFilter, EventLoopMessage, Invoke, InvokeError, InvokeResponse, Manager,
Runtime, Scopes, StateManager, Theme, Window,
};
#[cfg(shell_scope)]
@ -805,6 +805,35 @@ impl<R: Runtime> App<R> {
.set_activation_policy(activation_policy);
}
/// Change the device event filter mode.
///
/// Since the DeviceEvent capture can lead to high CPU usage for unfocused windows, [`tao`]
/// will ignore them by default for unfocused windows on Windows. This method allows changing
/// the filter to explicitly capture them again.
///
/// ## Platform-specific
///
/// - ** Linux / macOS / iOS / Android**: Unsupported.
///
/// # Examples
/// ```,no_run
/// let mut app = tauri::Builder::default()
/// // on an actual app, remove the string argument
/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
/// .expect("error while building tauri application");
/// app.set_device_event_filter(tauri::DeviceEventFilter::Always);
/// app.run(|_app_handle, _event| {});
/// ```
///
/// [`tao`]: https://crates.io/crates/tao
pub fn set_device_event_filter(&mut self, filter: DeviceEventFilter) {
self
.runtime
.as_mut()
.unwrap()
.set_device_event_filter(filter);
}
/// Gets the argument matches of the CLI definition configured in `tauri.conf.json`.
///
/// # Examples
@ -1008,6 +1037,9 @@ pub struct Builder<R: Runtime> {
/// The updater configuration.
#[cfg(updater)]
updater_settings: UpdaterSettings,
/// The device event filter.
device_event_filter: DeviceEventFilter,
}
impl<R: Runtime> Builder<R> {
@ -1036,6 +1068,7 @@ impl<R: Runtime> Builder<R> {
system_tray_event_listeners: Vec::new(),
#[cfg(updater)]
updater_settings: Default::default(),
device_event_filter: Default::default(),
}
}
@ -1486,6 +1519,28 @@ impl<R: Runtime> Builder<R> {
self
}
/// Change the device event filter mode.
///
/// Since the DeviceEvent capture can lead to high CPU usage for unfocused windows, [`tao`]
/// will ignore them by default for unfocused windows on Windows. This method allows changing
/// the filter to explicitly capture them again.
///
/// ## Platform-specific
///
/// - ** Linux / macOS / iOS / Android**: Unsupported.
///
/// # Examples
/// ```,no_run
/// tauri::Builder::default()
/// .device_event_filter(tauri::DeviceEventFilter::Always);
/// ```
///
/// [`tao`]: https://crates.io/crates/tao
pub fn device_event_filter(mut self, filter: DeviceEventFilter) -> Self {
self.device_event_filter = filter;
self
}
/// Builds the application.
#[allow(clippy::type_complexity)]
pub fn build<A: Assets>(mut self, context: Context<A>) -> crate::Result<App<R>> {
@ -1531,13 +1586,15 @@ impl<R: Runtime> Builder<R> {
}
#[cfg(any(windows, target_os = "linux"))]
let runtime = if self.runtime_any_thread {
let mut runtime = if self.runtime_any_thread {
R::new_any_thread()?
} else {
R::new()?
};
#[cfg(not(any(windows, target_os = "linux")))]
let runtime = R::new()?;
let mut runtime = R::new()?;
runtime.set_device_event_filter(self.device_event_filter);
let runtime_handle = runtime.handle();

View File

@ -244,7 +244,7 @@ pub use {
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
CursorIcon, FileDropEvent,
},
RunIteration, UserAttentionType,
DeviceEventFilter, RunIteration, UserAttentionType,
},
self::state::{State, StateManager},
self::utils::{

View File

@ -12,8 +12,8 @@ use tauri_runtime::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
CursorIcon, DetachedWindow, MenuEvent, PendingWindow, WindowEvent,
},
Dispatch, EventLoopProxy, Icon, Result, RunEvent, Runtime, RuntimeHandle, UserAttentionType,
UserEvent,
DeviceEventFilter, Dispatch, EventLoopProxy, Icon, Result, RunEvent, Runtime, RuntimeHandle,
UserAttentionType, UserEvent,
};
#[cfg(all(desktop, feature = "system-tray"))]
use tauri_runtime::{
@ -711,6 +711,8 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
fn hide(&self) {}
fn set_device_event_filter(&mut self, filter: DeviceEventFilter) {}
#[cfg(any(
target_os = "macos",
windows,