diff --git a/cli/tsc/dts/lib.deno.wsi.d.ts b/cli/tsc/dts/lib.deno.wsi.d.ts index 36c2ec2b9e83bd..85c31459609895 100644 --- a/cli/tsc/dts/lib.deno.wsi.d.ts +++ b/cli/tsc/dts/lib.deno.wsi.d.ts @@ -10,6 +10,7 @@ declare namespace Deno { export const wsi: WSI; export class WSI { nextEvent(): Promise; + setDeviceEventFilter(filter: WSIDeviceEventFilter): void; createWindow(options?: WSICreateWindowOptions): WSIWindow; } @@ -83,6 +84,12 @@ declare namespace Deno { | "col-resize" | "row-resize"; + // https://docs.rs/winit/0.28.1/winit/event_loop/enum.DeviceEventFilter.html + export type WSIDeviceEventFilter = + | "always" + | "unfocused" + | "never"; + // https://docs.rs/winit/0.28.1/winit/event/enum.Event.html export type WSIEvent = | { diff --git a/ext/wsi/01_wsi.js b/ext/wsi/01_wsi.js index bccf88e623e6ad..6b08abf1afbc5c 100644 --- a/ext/wsi/01_wsi.js +++ b/ext/wsi/01_wsi.js @@ -95,6 +95,19 @@ return event; } + setDeviceEventFilter(filter) { + webidl.assertBranded(this, WSIPrototype); + const prefix = "Failed to execute 'setDeviceEventFilter' on 'WSI'"; + + webidl.requiredArguments(arguments.length, 1, { prefix }); + filter = webidl.converters["WSIDeviceEventFilter"](filter, { + prefix, + context: "Argument 1", + }); + + return ops.op_wsi_set_device_event_filter(filter); + } + createWindow(options) { webidl.assertBranded(this, WSIPrototype); const prefix = "Failed to execute 'createWindow' on 'WSI'"; diff --git a/ext/wsi/02_idl_types.js b/ext/wsi/02_idl_types.js index 554037da14e4dc..a92b924872620f 100644 --- a/ext/wsi/02_idl_types.js +++ b/ext/wsi/02_idl_types.js @@ -57,6 +57,16 @@ ], ); + // ENUM: WSIDeviceEventFilter + webidl.converters["WSIDeviceEventFilter"] = webidl.createEnumConverter( + "WSIDeviceEventFilter", + [ + "always", + "unfocused", + "never", + ], + ); + // ENUM: WSIIMEPurpose webidl.converters["WSIIMEPurpose"] = webidl.createEnumConverter( "WSIIMEPurpose", diff --git a/ext/wsi/input.rs b/ext/wsi/input.rs index 8840ed45fcd233..b4ece52d3e160f 100644 --- a/ext/wsi/input.rs +++ b/ext/wsi/input.rs @@ -1,7 +1,10 @@ -use serde::{Serialize, Serializer}; -use winit::event::{ - ElementState, Force, MouseButton, MouseScrollDelta, TouchPhase, - VirtualKeyCode, +use serde::{Deserialize, Serialize, Serializer}; +use winit::{ + event::{ + ElementState, Force, MouseButton, MouseScrollDelta, TouchPhase, + VirtualKeyCode, + }, + event_loop::DeviceEventFilter, }; #[derive(Debug, Serialize)] @@ -20,6 +23,24 @@ impl From for WsiButtonState { } } +#[derive(Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum WsiDeviceEventFilter { + Always, + Unfocused, + Never, +} + +impl From for DeviceEventFilter { + fn from(filter: WsiDeviceEventFilter) -> Self { + match filter { + WsiDeviceEventFilter::Always => Self::Always, + WsiDeviceEventFilter::Unfocused => Self::Unfocused, + WsiDeviceEventFilter::Never => Self::Never, + } + } +} + #[derive(Debug, Serialize)] pub struct WsiKeyCode(#[serde(with = "WsiKeyCodeDef")] pub VirtualKeyCode); diff --git a/ext/wsi/lib.rs b/ext/wsi/lib.rs index f35642a44dae8b..cac72e0d5825f1 100644 --- a/ext/wsi/lib.rs +++ b/ext/wsi/lib.rs @@ -12,6 +12,7 @@ use crate::{ cursor::{WsiCursorGrabMode, WsiCursorIcon}, event::WsiEvent, event_loop::WsiEventLoopProxy, + input::WsiDeviceEventFilter, window::{ WsiCreateWindowOptions, WsiImePurpose, WsiResizeDirection, WsiUserAttentionType, WsiWindowLevel, WsiWindowTheme, @@ -36,6 +37,7 @@ pub fn init(event_loop_proxy: Option>) -> Extension { )) .ops(vec![ op_wsi_next_event::decl(), + op_wsi_set_device_event_filter::decl(), op_wsi_create_window::decl(), op_wsi_window_set_content_protected::decl(), op_wsi_window_set_cursor_grab_mode::decl(), @@ -121,6 +123,16 @@ async fn op_wsi_next_event( } } +#[op] +fn op_wsi_set_device_event_filter( + state: &mut OpState, + filter: WsiDeviceEventFilter, +) { + try_borrow_event_loop_proxy(state, "Deno.wsi.setDeviceEventFilter").execute( + |window_target, _| window_target.set_device_event_filter(filter.into()), + ) +} + #[op] fn op_wsi_create_window( state: &mut OpState,