diff --git a/.gitignore b/.gitignore index ebed8e3651..f789d938d2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ rls/ *.js #*# .DS_Store +.idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md index e7c1facc4b..e5320cd8ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ And please only add new entries to the top of this list, right below the `# Unre - **Breaking:** `CursorIcon` is now used from the `cursor-icon` crate. - **Breaking:** `CursorIcon::Hand` is now named `CursorIcon::Pointer`. - **Breaking:** `CursorIcon::Arrow` was removed. +- **Breaking:** Web: Canvases will now capture the contextmenu if prevent_default is enabled so they don't interfere with right click pointer events. +- **Breaking:** Web: Canvases will now have `user-select: none` to prevent double clicks from selecting text outside the canvas. - On Wayland, fix maximized startup not taking full size on GNOME. - On Wayland, fix initial window size not restored for maximized/fullscreened on startup window. - On Wayland, `Window::outer_size` now accounts for **client side** decorations. diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 17aafd946d..33dca0cbaf 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -85,6 +85,8 @@ impl EventLoopWindowTarget { }); }); + canvas.on_contextmenu(prevent_default); + let runner = self.runner.clone(); canvas.on_keyboard_press( move |scancode, virtual_keycode, modifiers| { diff --git a/src/platform_impl/web/web_sys/canvas.rs b/src/platform_impl/web/web_sys/canvas.rs index 1157a4f2d0..dfd0b5c48d 100644 --- a/src/platform_impl/web/web_sys/canvas.rs +++ b/src/platform_impl/web/web_sys/canvas.rs @@ -27,6 +27,7 @@ pub struct Canvas { on_touch_end: Option>, on_focus: Option>, on_blur: Option>, + on_contextmenu: Option>, on_keyboard_release: Option>, on_keyboard_press: Option>, on_received_character: Option>, @@ -72,6 +73,12 @@ impl Canvas { .map_err(|_| os_error!(OsError("Failed to set a tabindex".to_owned())))?; } + // Prevent double clicks on the canvas from causing text selections elsewhere on the page + // Calling preventDefault within a dblclick/pointerdown handler on the canvas does not work. + for prefix in ["", "-webkit-", "-moz-", "-ms-"] { + super::set_canvas_style_property(&canvas, &format!("{}user-select", prefix), "none"); + } + let mouse_state = if has_pointer_event() { MouseState::HasPointerEvent(pointer_handler::PointerHandler::new()) } else { @@ -87,6 +94,7 @@ impl Canvas { on_touch_end: None, on_blur: None, on_focus: None, + on_contextmenu: None, on_keyboard_release: None, on_keyboard_press: None, on_received_character: None, @@ -172,6 +180,19 @@ impl Canvas { })); } + pub fn on_contextmenu(&mut self, prevent_default: bool) { + // Setup a handler to prevent the default context menu from appearing. + // + // contextmenu events normally occur on right click and can interfere with the sequence of + // pointer events, e.g. https://github.com/rust-windowing/winit/issues/2608. + self.on_contextmenu = Some(self.common.add_event("contextmenu", move |event: Event| { + if prevent_default { + trace!("contextmenu event ignored because prevent_default is true"); + event.prevent_default(); + } + })); + } + pub fn on_keyboard_release(&mut self, mut handler: F, prevent_default: bool) where F: 'static + FnMut(ScanCode, Option, ModifiersState), @@ -364,6 +385,7 @@ impl Canvas { pub fn remove_listeners(&mut self) { self.on_focus = None; self.on_blur = None; + self.on_contextmenu = None; self.on_keyboard_release = None; self.on_keyboard_press = None; self.on_received_character = None;