From e413dd13d3c30033ec58fc81b647a2f53511c2d5 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 31 Aug 2022 15:01:30 -0700 Subject: [PATCH 01/14] feat: replace scroll-touch* with generic input-event --- docs/api/browser-window.md | 6 +- docs/api/structures/input-event.md | 1 + docs/api/web-contents.md | 7 ++ docs/breaking-changes.md | 49 ++++++++ lib/browser/api/browser-window.ts | 21 ++++ lib/common/deprecate.ts | 9 +- shell/browser/api/electron_api_base_window.cc | 8 -- shell/browser/api/electron_api_base_window.h | 2 - .../api/electron_api_browser_window.cc | 27 ---- .../browser/api/electron_api_browser_window.h | 6 - .../browser/api/electron_api_web_contents.cc | 21 ++++ shell/browser/api/electron_api_web_contents.h | 6 + shell/browser/native_window.cc | 10 -- shell/browser/native_window.h | 2 - shell/browser/native_window_mac.mm | 26 ---- shell/browser/native_window_observer.h | 2 - .../common/gin_converters/blink_converter.cc | 116 ++++++++++++------ shell/common/gin_converters/blink_converter.h | 11 ++ 18 files changed, 205 insertions(+), 125 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 16a005cd35706..280c266f412c6 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -652,15 +652,15 @@ The following app commands are explicitly supported on Linux: * `browser-backward` * `browser-forward` -#### Event: 'scroll-touch-begin' _macOS_ +#### Event: 'scroll-touch-begin' _macOS_ _Deprecated_ Emitted when scroll wheel event phase has begun. -#### Event: 'scroll-touch-end' _macOS_ +#### Event: 'scroll-touch-end' _macOS_ _Deprecated_ Emitted when scroll wheel event phase has ended. -#### Event: 'scroll-touch-edge' _macOS_ +#### Event: 'scroll-touch-edge' _macOS_ _Deprecated_ Emitted when scroll wheel event phase filed upon reaching the edge of element. diff --git a/docs/api/structures/input-event.md b/docs/api/structures/input-event.md index 21efec36d3e41..bcaae8460ba57 100644 --- a/docs/api/structures/input-event.md +++ b/docs/api/structures/input-event.md @@ -1,5 +1,6 @@ # InputEvent Object +* `type` string - One of "undefined", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "contextmenu", "mousewheel", "rawkeydown", "keydown", "keyup", "char", "gesturescrollbegin", "gesturescrollend", "gesturescrollupdate", "gestureflingstart", "gestureflingcancel", "gesturepinchbegin", "gesturepinchend", "gesturepinchupdate", "gesturetapdown", "gestureshowpress", "gesturetap", "gesturetapcancel", "gestureshortpress", "gesturelongpress", "gesturelongtap", "gesturetwofingertap", "gesturetapunconfirmed", "gesturedoubletap", "touchstart", "touchmove", "touchend", "touchcancel", "touchscrollstarted", "pointerdown", "pointerup", "pointermove", "pointerrawupdate", "pointercancel", or "pointercauseduaaction". * `modifiers` string[] (optional) - An array of modifiers of the event, can be `shift`, `control`, `ctrl`, `alt`, `meta`, `command`, `cmd`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 2cf6e17263088..be486f06e76b4 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -396,6 +396,13 @@ Emitted when a plugin process has crashed. Emitted when `webContents` is destroyed. +#### Event: 'input-event' + +Returns: + +* `event` Event +* `inputEvent` [InputEvent](structures/input-event.md) + #### Event: 'before-input-event' Returns: diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index f7bea50260f1d..319290bb8ce66 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -30,6 +30,55 @@ webContents.setWindowOpenHandler((details) => { }) ``` +### Removed: BrowserWindow `scroll-touch-*` events + +The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on +BrowserWindow have been removed. + +```js +// Removed in Electron 22.0 +win.on('scroll-touch-begin', scrollTouchBegin) +win.on('scroll-touch-edge', scrollTouchEdge) +win.on('scroll-touch-end', scrollTouchEnd) + +// Replace with +win.webContents.on('input-event', (_, event) => { + if (event.type === 'gesturescrollbegin') { + scrollTouchBegin() + } else if (event.type === 'gesturescrollupdate') { + scrollTouchEdge() + } else if (event.type === 'gesturescrollend') { + scrollTouchEnd() + } +}) +``` + +## Planned Breaking API Changes (21.0) + +### Deprecated: BrowserWindow `scroll-touch-*` events + +The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on +BrowserWindow are deprecated. Instead, use the newly available `input-event` +event on WebContents. + +```js +// Deprecated +win.on('scroll-touch-begin', scrollTouchBegin) +win.on('scroll-touch-edge', scrollTouchEdge) +win.on('scroll-touch-end', scrollTouchEnd) + +// Replace with +win.webContents.on('input-event', (_, event) => { + if (event.type === 'gesturescrollbegin') { + scrollTouchBegin() + } else if (event.type === 'gesturescrollupdate') { + scrollTouchEdge() + } else if (event.type === 'gesturescrollend') { + scrollTouchEnd() + } +}) +``` + ## Planned Breaking API Changes (20.0) ### Behavior Changed: V8 Memory Cage enabled diff --git a/lib/browser/api/browser-window.ts b/lib/browser/api/browser-window.ts index d20ea0bda5571..638de4289bad8 100644 --- a/lib/browser/api/browser-window.ts +++ b/lib/browser/api/browser-window.ts @@ -1,5 +1,6 @@ import { BaseWindow, WebContents, Event, BrowserView, TouchBar } from 'electron/main'; import type { BrowserWindow as BWT } from 'electron/main'; +import * as deprecate from '@electron/internal/common/deprecate'; const { BrowserWindow } = process._linkedBinding('electron_browser_window') as { BrowserWindow: typeof BWT }; Object.setPrototypeOf(BrowserWindow.prototype, BaseWindow.prototype); @@ -44,6 +45,26 @@ BrowserWindow.prototype._init = function (this: BWT) { this.on(event as any, visibilityChanged); } + const warn = deprecate.warnOnceMessage('\'scroll-touch-{begin,end,edge}\' are deprecated and will be removed. Please use the WebContents \'input-event\' event instead.'); + this.webContents.on('input-event', (_, e) => { + if (e.type === 'gesturescrollbegin') { + if (this.listenerCount('scroll-touch-begin') !== 0) { + warn(); + this.emit('scroll-touch-begin'); + } + } else if (e.type === 'gesturescrollupdate') { + if (this.listenerCount('scroll-touch-edge') !== 0) { + warn(); + this.emit('scroll-touch-edge'); + } + } else if (e.type === 'gesturescrollend') { + if (this.listenerCount('scroll-touch-end') !== 0) { + warn(); + this.emit('scroll-touch-end'); + } + } + }); + // Notify the creation of the window. const event = process._linkedBinding('electron_browser_event').createEmpty(); app.emit('browser-window-created', event, this); diff --git a/lib/common/deprecate.ts b/lib/common/deprecate.ts index b9c42c3cc0b9e..dc6d9d0eb9815 100644 --- a/lib/common/deprecate.ts +++ b/lib/common/deprecate.ts @@ -3,10 +3,13 @@ type DeprecationHandler = (message: string) => void; let deprecationHandler: DeprecationHandler | null = null; export function warnOnce (oldName: string, newName?: string) { - let warned = false; - const msg = newName + return warnOnceMessage(newName ? `'${oldName}' is deprecated and will be removed. Please use '${newName}' instead.` - : `'${oldName}' is deprecated and will be removed.`; + : `'${oldName}' is deprecated and will be removed.`); +} + +export function warnOnceMessage (msg: string) { + let warned = false; return () => { if (!warned && !process.noDeprecation) { warned = true; diff --git a/shell/browser/api/electron_api_base_window.cc b/shell/browser/api/electron_api_base_window.cc index 3a87a11d22f06..c2b8721548983 100644 --- a/shell/browser/api/electron_api_base_window.cc +++ b/shell/browser/api/electron_api_base_window.cc @@ -247,14 +247,6 @@ void BaseWindow::OnWindowLeaveFullScreen() { Emit("leave-full-screen"); } -void BaseWindow::OnWindowScrollTouchBegin() { - Emit("scroll-touch-begin"); -} - -void BaseWindow::OnWindowScrollTouchEnd() { - Emit("scroll-touch-end"); -} - void BaseWindow::OnWindowSwipe(const std::string& direction) { Emit("swipe", direction); } diff --git a/shell/browser/api/electron_api_base_window.h b/shell/browser/api/electron_api_base_window.h index 482f510f4ed40..52dcbb8586e30 100644 --- a/shell/browser/api/electron_api_base_window.h +++ b/shell/browser/api/electron_api_base_window.h @@ -67,8 +67,6 @@ class BaseWindow : public gin_helper::TrackableObject, bool* prevent_default) override; void OnWindowMove() override; void OnWindowMoved() override; - void OnWindowScrollTouchBegin() override; - void OnWindowScrollTouchEnd() override; void OnWindowSwipe(const std::string& direction) override; void OnWindowRotateGesture(float rotation) override; void OnWindowSheetBegin() override; diff --git a/shell/browser/api/electron_api_browser_window.cc b/shell/browser/api/electron_api_browser_window.cc index 3d1ec969123c8..cebf4d3dcbb32 100644 --- a/shell/browser/api/electron_api_browser_window.cc +++ b/shell/browser/api/electron_api_browser_window.cc @@ -107,10 +107,6 @@ BrowserWindow::BrowserWindow(gin::Arguments* args, // Associate with BrowserWindow. web_contents->SetOwnerWindow(window()); - auto* host = web_contents->web_contents()->GetRenderViewHost(); - if (host) - host->GetWidget()->AddInputEventObserver(this); - InitWithArgs(args); // Install the content view after BaseWindow's JS code is initialized. @@ -129,35 +125,12 @@ BrowserWindow::~BrowserWindow() { if (api_web_contents_) { // Cleanup the observers if user destroyed this instance directly instead of // gracefully closing content::WebContents. - auto* host = web_contents()->GetRenderViewHost(); - if (host) - host->GetWidget()->RemoveInputEventObserver(this); api_web_contents_->RemoveObserver(this); // Destroy the WebContents. OnCloseContents(); } } -void BrowserWindow::OnInputEvent(const blink::WebInputEvent& event) { - switch (event.GetType()) { - case blink::WebInputEvent::Type::kGestureScrollBegin: - case blink::WebInputEvent::Type::kGestureScrollUpdate: - case blink::WebInputEvent::Type::kGestureScrollEnd: - Emit("scroll-touch-edge"); - break; - default: - break; - } -} - -void BrowserWindow::RenderViewHostChanged(content::RenderViewHost* old_host, - content::RenderViewHost* new_host) { - if (old_host) - old_host->GetWidget()->RemoveInputEventObserver(this); - if (new_host) - new_host->GetWidget()->AddInputEventObserver(this); -} - void BrowserWindow::RenderFrameCreated( content::RenderFrameHost* render_frame_host) { if (!window()->transparent()) diff --git a/shell/browser/api/electron_api_browser_window.h b/shell/browser/api/electron_api_browser_window.h index 91195053495ba..ecaa915745c34 100644 --- a/shell/browser/api/electron_api_browser_window.h +++ b/shell/browser/api/electron_api_browser_window.h @@ -17,7 +17,6 @@ namespace electron::api { class BrowserWindow : public BaseWindow, - public content::RenderWidgetHost::InputEventObserver, public content::WebContentsObserver, public ExtendedWebContentsObserver { public: @@ -43,12 +42,7 @@ class BrowserWindow : public BaseWindow, BrowserWindow(gin::Arguments* args, const gin_helper::Dictionary& options); ~BrowserWindow() override; - // content::RenderWidgetHost::InputEventObserver: - void OnInputEvent(const blink::WebInputEvent& event) override; - // content::WebContentsObserver: - void RenderViewHostChanged(content::RenderViewHost* old_host, - content::RenderViewHost* new_host) override; void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; void DidFirstVisuallyNonEmptyPaint() override; void BeforeUnloadDialogCancelled() override; diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 9411bc0926926..305f19829ebf6 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -816,6 +816,12 @@ void WebContents::InitZoomController(content::WebContents* web_contents, double zoom_factor; if (options.Get(options::kZoomFactor, &zoom_factor)) zoom_controller_->SetDefaultZoomFactor(zoom_factor); + + // Nothing to do with ZoomController, but this function gets called in all + // init cases! + content::RenderViewHost* host = web_contents->GetRenderViewHost(); + if (host) + host->GetWidget()->AddInputEventObserver(this); } void WebContents::InitWithSessionAndOptions( @@ -1671,6 +1677,14 @@ void WebContents::OnWebContentsLostFocus( Emit("blur"); } +void WebContents::RenderViewHostChanged(content::RenderViewHost* old_host, + content::RenderViewHost* new_host) { + if (old_host) + old_host->GetWidget()->RemoveInputEventObserver(this); + if (new_host) + new_host->GetWidget()->AddInputEventObserver(this); +} + void WebContents::DOMContentLoaded( content::RenderFrameHost* render_frame_host) { auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host); @@ -2059,6 +2073,9 @@ void WebContents::WebContentsDestroyed() { // Clear the pointer stored in wrapper. if (GetAllWebContents().Lookup(id_)) GetAllWebContents().Remove(id_); + content::RenderViewHost* host = web_contents()->GetRenderViewHost(); + if (host) + host->GetWidget()->RemoveInputEventObserver(this); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::HandleScope scope(isolate); v8::Local wrapper; @@ -3448,6 +3465,10 @@ void WebContents::SetImageAnimationPolicy(const std::string& new_policy) { web_contents()->OnWebPreferencesChanged(); } +void WebContents::OnInputEvent(const blink::WebInputEvent& event) { + Emit("input-event", event); +} + v8::Local WebContents::GetProcessMemoryInfo(v8::Isolate* isolate) { gin_helper::Promise promise(isolate); v8::Local handle = promise.GetHandle(); diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index 7ccc525f56096..693e9853edd14 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -103,6 +103,7 @@ class WebContents : public ExclusiveAccessContext, public gin_helper::CleanedUpAtExit, public content::WebContentsObserver, public content::WebContentsDelegate, + public content::RenderWidgetHost::InputEventObserver, public InspectableWebContentsDelegate, public InspectableWebContentsViewDelegate { public: @@ -431,6 +432,9 @@ class WebContents : public ExclusiveAccessContext, void SetImageAnimationPolicy(const std::string& new_policy); + // content::RenderWidgetHost::InputEventObserver: + void OnInputEvent(const blink::WebInputEvent& event) override; + // disable copy WebContents(const WebContents&) = delete; WebContents& operator=(const WebContents&) = delete; @@ -615,6 +619,8 @@ class WebContents : public ExclusiveAccessContext, content::RenderWidgetHost* render_widget_host) override; void OnWebContentsLostFocus( content::RenderWidgetHost* render_widget_host) override; + void RenderViewHostChanged(content::RenderViewHost* old_host, + content::RenderViewHost* new_host) override; // InspectableWebContentsDelegate: void DevToolsReloadPage() override; diff --git a/shell/browser/native_window.cc b/shell/browser/native_window.cc index 931e7759073cb..16a174a82e327 100644 --- a/shell/browser/native_window.cc +++ b/shell/browser/native_window.cc @@ -603,16 +603,6 @@ void NativeWindow::NotifyWindowEnterFullScreen() { observer.OnWindowEnterFullScreen(); } -void NativeWindow::NotifyWindowScrollTouchBegin() { - for (NativeWindowObserver& observer : observers_) - observer.OnWindowScrollTouchBegin(); -} - -void NativeWindow::NotifyWindowScrollTouchEnd() { - for (NativeWindowObserver& observer : observers_) - observer.OnWindowScrollTouchEnd(); -} - void NativeWindow::NotifyWindowSwipe(const std::string& direction) { for (NativeWindowObserver& observer : observers_) observer.OnWindowSwipe(direction); diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index 6568f03127bf3..e81da9619ee90 100644 --- a/shell/browser/native_window.h +++ b/shell/browser/native_window.h @@ -291,8 +291,6 @@ class NativeWindow : public base::SupportsUserData, void NotifyWindowResized(); void NotifyWindowWillMove(const gfx::Rect& new_bounds, bool* prevent_default); void NotifyWindowMoved(); - void NotifyWindowScrollTouchBegin(); - void NotifyWindowScrollTouchEnd(); void NotifyWindowSwipe(const std::string& direction); void NotifyWindowRotateGesture(float rotation); void NotifyWindowSheetBegin(); diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 2bb5e3a4c5064..41c3a28aa6f94 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -418,32 +418,6 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor); [window_ setDisableAutoHideCursor:disableAutoHideCursor]; - // Use an NSEvent monitor to listen for the wheel event. - BOOL __block began = NO; - wheel_event_monitor_ = [NSEvent - addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel - handler:^(NSEvent* event) { - if ([[event window] windowNumber] != - [window_ windowNumber]) - return event; - - if (!began && (([event phase] == - NSEventPhaseMayBegin) || - ([event phase] == - NSEventPhaseBegan))) { - this->NotifyWindowScrollTouchBegin(); - began = YES; - } else if (began && - (([event phase] == - NSEventPhaseEnded) || - ([event phase] == - NSEventPhaseCancelled))) { - this->NotifyWindowScrollTouchEnd(); - began = NO; - } - return event; - }]; - // Set maximizable state last to ensure zoom button does not get reset // by calls to other APIs. SetMaximizable(maximizable); diff --git a/shell/browser/native_window_observer.h b/shell/browser/native_window_observer.h index 6cbc941450642..2c24406375b4a 100644 --- a/shell/browser/native_window_observer.h +++ b/shell/browser/native_window_observer.h @@ -81,8 +81,6 @@ class NativeWindowObserver : public base::CheckedObserver { bool* prevent_default) {} virtual void OnWindowMove() {} virtual void OnWindowMoved() {} - virtual void OnWindowScrollTouchBegin() {} - virtual void OnWindowScrollTouchEnd() {} virtual void OnWindowSwipe(const std::string& direction) {} virtual void OnWindowRotateGesture(float rotation) {} virtual void OnWindowSheetBegin() {} diff --git a/shell/common/gin_converters/blink_converter.cc b/shell/common/gin_converters/blink_converter.cc index 68ba0307dc004..49028c2ada1da 100644 --- a/shell/common/gin_converters/blink_converter.cc +++ b/shell/common/gin_converters/blink_converter.cc @@ -11,6 +11,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "gin/converter.h" +#include "gin/data_object_builder.h" #include "shell/common/gin_converters/gfx_converter.h" #include "shell/common/gin_converters/gurl_converter.h" #include "shell/common/gin_converters/value_converter.h" @@ -56,43 +57,73 @@ struct Converter { } }; -template <> -struct Converter { - static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - blink::WebInputEvent::Type* out) { - std::string type = base::ToLowerASCII(gin::V8ToString(isolate, val)); - if (type == "mousedown") - *out = blink::WebInputEvent::Type::kMouseDown; - else if (type == "mouseup") - *out = blink::WebInputEvent::Type::kMouseUp; - else if (type == "mousemove") - *out = blink::WebInputEvent::Type::kMouseMove; - else if (type == "mouseenter") - *out = blink::WebInputEvent::Type::kMouseEnter; - else if (type == "mouseleave") - *out = blink::WebInputEvent::Type::kMouseLeave; - else if (type == "contextmenu") - *out = blink::WebInputEvent::Type::kContextMenu; - else if (type == "mousewheel") - *out = blink::WebInputEvent::Type::kMouseWheel; - else if (type == "keydown") - *out = blink::WebInputEvent::Type::kRawKeyDown; - else if (type == "keyup") - *out = blink::WebInputEvent::Type::kKeyUp; - else if (type == "char") - *out = blink::WebInputEvent::Type::kChar; - else if (type == "touchstart") - *out = blink::WebInputEvent::Type::kTouchStart; - else if (type == "touchmove") - *out = blink::WebInputEvent::Type::kTouchMove; - else if (type == "touchend") - *out = blink::WebInputEvent::Type::kTouchEnd; - else if (type == "touchcancel") - *out = blink::WebInputEvent::Type::kTouchCancel; - return true; +#define BLINK_EVENT_TYPES() \ + CASE_TYPE(kUndefined, "undefined") \ + CASE_TYPE(kMouseDown, "mousedown") \ + CASE_TYPE(kMouseUp, "mouseup") \ + CASE_TYPE(kMouseMove, "mousemove") \ + CASE_TYPE(kMouseEnter, "mouseenter") \ + CASE_TYPE(kMouseLeave, "mouseleave") \ + CASE_TYPE(kContextMenu, "contextmenu") \ + CASE_TYPE(kMouseWheel, "mousewheel") \ + CASE_TYPE(kRawKeyDown, "rawkeydown") \ + CASE_TYPE(kKeyDown, "keydown") \ + CASE_TYPE(kKeyUp, "keyup") \ + CASE_TYPE(kChar, "char") \ + CASE_TYPE(kGestureScrollBegin, "gesturescrollbegin") \ + CASE_TYPE(kGestureScrollEnd, "gesturescrollend") \ + CASE_TYPE(kGestureScrollUpdate, "gesturescrollupdate") \ + CASE_TYPE(kGestureFlingStart, "gestureflingstart") \ + CASE_TYPE(kGestureFlingCancel, "gestureflingcancel") \ + CASE_TYPE(kGesturePinchBegin, "gesturepinchbegin") \ + CASE_TYPE(kGesturePinchEnd, "gesturepinchend") \ + CASE_TYPE(kGesturePinchUpdate, "gesturepinchupdate") \ + CASE_TYPE(kGestureTapDown, "gesturetapdown") \ + CASE_TYPE(kGestureShowPress, "gestureshowpress") \ + CASE_TYPE(kGestureTap, "gesturetap") \ + CASE_TYPE(kGestureTapCancel, "gesturetapcancel") \ + CASE_TYPE(kGestureShortPress, "gestureshortpress") \ + CASE_TYPE(kGestureLongPress, "gesturelongpress") \ + CASE_TYPE(kGestureLongTap, "gesturelongtap") \ + CASE_TYPE(kGestureTwoFingerTap, "gesturetwofingertap") \ + CASE_TYPE(kGestureTapUnconfirmed, "gesturetapunconfirmed") \ + CASE_TYPE(kGestureDoubleTap, "gesturedoubletap") \ + CASE_TYPE(kTouchStart, "touchstart") \ + CASE_TYPE(kTouchMove, "touchmove") \ + CASE_TYPE(kTouchEnd, "touchend") \ + CASE_TYPE(kTouchCancel, "touchcancel") \ + CASE_TYPE(kTouchScrollStarted, "touchscrollstarted") \ + CASE_TYPE(kPointerDown, "pointerdown") \ + CASE_TYPE(kPointerUp, "pointerup") \ + CASE_TYPE(kPointerMove, "pointermove") \ + CASE_TYPE(kPointerRawUpdate, "pointerrawupdate") \ + CASE_TYPE(kPointerCancel, "pointercancel") \ + CASE_TYPE(kPointerCausedUaAction, "pointercauseduaaction") + +bool Converter::FromV8( + v8::Isolate* isolate, + v8::Handle val, + blink::WebInputEvent::Type* out) { + std::string type = base::ToLowerASCII(gin::V8ToString(isolate, val)); +#define CASE_TYPE(event_type, js_name) \ + if (type == js_name) { \ + *out = blink::WebInputEvent::Type::event_type; \ + return true; \ } -}; + BLINK_EVENT_TYPES() +#undef CASE_TYPE + return false; +} + +v8::Local Converter::ToV8( + v8::Isolate* isolate, + const blink::WebInputEvent::Type& in) { +#define CASE_TYPE(event_type, js_name) \ + case blink::WebInputEvent::Type::event_type: \ + return StringToV8(isolate, js_name); + switch (in) { BLINK_EVENT_TYPES() } +#undef CASE_TYPE +} template <> struct Converter { @@ -207,6 +238,19 @@ bool Converter::FromV8(v8::Isolate* isolate, return true; } +v8::Local Converter::ToV8( + v8::Isolate* isolate, + const blink::WebInputEvent& in) { + if (blink::WebInputEvent::IsKeyboardEventType(in.GetType())) + return gin::ConvertToV8(isolate, + *static_cast(&in)); + return gin::DataObjectBuilder(isolate) + .Set("type", in.GetType()) + .Set("modifiers", ModifiersToArray(in.GetModifiers())) + .Set("_modifiers", in.GetModifiers()) + .Build(); +} + bool Converter::FromV8(v8::Isolate* isolate, v8::Local val, blink::WebKeyboardEvent* out) { diff --git a/shell/common/gin_converters/blink_converter.h b/shell/common/gin_converters/blink_converter.h index 8ae85d7506005..38017310fb8f2 100644 --- a/shell/common/gin_converters/blink_converter.h +++ b/shell/common/gin_converters/blink_converter.h @@ -24,11 +24,22 @@ namespace gin { blink::WebInputEvent::Type GetWebInputEventType(v8::Isolate* isolate, v8::Local val); +template <> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + blink::WebInputEvent::Type* out); + static v8::Local ToV8(v8::Isolate* isolate, + const blink::WebInputEvent::Type& in); +}; + template <> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Local val, blink::WebInputEvent* out); + static v8::Local ToV8(v8::Isolate* isolate, + const blink::WebInputEvent& in); }; template <> From 68f5253585f87276b750c633b026521bc826aa53 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 31 Aug 2022 15:48:15 -0700 Subject: [PATCH 02/14] more docs --- docs/api/structures/input-event.md | 12 ++- docs/api/web-contents.md | 3 + lib/browser/api/browser-window.ts | 6 +- .../common/gin_converters/blink_converter.cc | 88 +++++++++---------- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/docs/api/structures/input-event.md b/docs/api/structures/input-event.md index bcaae8460ba57..a68a9304dfca1 100644 --- a/docs/api/structures/input-event.md +++ b/docs/api/structures/input-event.md @@ -1,6 +1,16 @@ # InputEvent Object -* `type` string - One of "undefined", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "contextmenu", "mousewheel", "rawkeydown", "keydown", "keyup", "char", "gesturescrollbegin", "gesturescrollend", "gesturescrollupdate", "gestureflingstart", "gestureflingcancel", "gesturepinchbegin", "gesturepinchend", "gesturepinchupdate", "gesturetapdown", "gestureshowpress", "gesturetap", "gesturetapcancel", "gestureshortpress", "gesturelongpress", "gesturelongtap", "gesturetwofingertap", "gesturetapunconfirmed", "gesturedoubletap", "touchstart", "touchmove", "touchend", "touchcancel", "touchscrollstarted", "pointerdown", "pointerup", "pointermove", "pointerrawupdate", "pointercancel", or "pointercauseduaaction". +* `type` string - Can be `undefined`, `mouseDown`, `mouseUp`, `mouseMove`, + `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`, `rawKeyDown`, + `keyDown`, `keyUp`, `char`, `gestureScrollBegin`, `gestureScrollEnd`, + `gestureScrollUpdate`, `gestureFlingStart`, `gestureFlingCancel`, + `gesturePinchBegin`, `gesturePinchEnd`, `gesturePinchUpdate`, + `gestureTapDown`, `gestureShowPress`, `gestureTap`, `gestureTapCancel`, + `gestureShortPress`, `gestureLongPress`, `gestureLongTap`, + `gestureTwoFingerTap`, `gestureTapUnconfirmed`, `gestureDoubleTap`, + `touchStart`, `touchMove`, `touchEnd`, `touchCancel`, `touchScrollStarted`, + `pointerDown`, `pointerUp`, `pointerMove`, `pointerRawUpdate`, + `pointerCancel` or `pointerCausedUaAction`. * `modifiers` string[] (optional) - An array of modifiers of the event, can be `shift`, `control`, `ctrl`, `alt`, `meta`, `command`, `cmd`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index be486f06e76b4..9ecc0b7cd37b4 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -403,6 +403,9 @@ Returns: * `event` Event * `inputEvent` [InputEvent](structures/input-event.md) +Emitted when an input event is sent to the WebContents. See +[InputEvent](structures/input-event.md) for details. + #### Event: 'before-input-event' Returns: diff --git a/lib/browser/api/browser-window.ts b/lib/browser/api/browser-window.ts index 638de4289bad8..ed8f26fa29339 100644 --- a/lib/browser/api/browser-window.ts +++ b/lib/browser/api/browser-window.ts @@ -47,17 +47,17 @@ BrowserWindow.prototype._init = function (this: BWT) { const warn = deprecate.warnOnceMessage('\'scroll-touch-{begin,end,edge}\' are deprecated and will be removed. Please use the WebContents \'input-event\' event instead.'); this.webContents.on('input-event', (_, e) => { - if (e.type === 'gesturescrollbegin') { + if (e.type === 'gestureScrollBegin') { if (this.listenerCount('scroll-touch-begin') !== 0) { warn(); this.emit('scroll-touch-begin'); } - } else if (e.type === 'gesturescrollupdate') { + } else if (e.type === 'gestureScrollUpdate') { if (this.listenerCount('scroll-touch-edge') !== 0) { warn(); this.emit('scroll-touch-edge'); } - } else if (e.type === 'gesturescrollend') { + } else if (e.type === 'gestureScrollEnd') { if (this.listenerCount('scroll-touch-end') !== 0) { warn(); this.emit('scroll-touch-end'); diff --git a/shell/common/gin_converters/blink_converter.cc b/shell/common/gin_converters/blink_converter.cc index 49028c2ada1da..d62ef3cec6b76 100644 --- a/shell/common/gin_converters/blink_converter.cc +++ b/shell/common/gin_converters/blink_converter.cc @@ -59,56 +59,56 @@ struct Converter { #define BLINK_EVENT_TYPES() \ CASE_TYPE(kUndefined, "undefined") \ - CASE_TYPE(kMouseDown, "mousedown") \ - CASE_TYPE(kMouseUp, "mouseup") \ - CASE_TYPE(kMouseMove, "mousemove") \ - CASE_TYPE(kMouseEnter, "mouseenter") \ - CASE_TYPE(kMouseLeave, "mouseleave") \ - CASE_TYPE(kContextMenu, "contextmenu") \ - CASE_TYPE(kMouseWheel, "mousewheel") \ - CASE_TYPE(kRawKeyDown, "rawkeydown") \ - CASE_TYPE(kKeyDown, "keydown") \ - CASE_TYPE(kKeyUp, "keyup") \ + CASE_TYPE(kMouseDown, "mouseDown") \ + CASE_TYPE(kMouseUp, "mouseUp") \ + CASE_TYPE(kMouseMove, "mouseMove") \ + CASE_TYPE(kMouseEnter, "mouseEnter") \ + CASE_TYPE(kMouseLeave, "mouseLeave") \ + CASE_TYPE(kContextMenu, "contextMenu") \ + CASE_TYPE(kMouseWheel, "mouseWheel") \ + CASE_TYPE(kRawKeyDown, "rawKeyDown") \ + CASE_TYPE(kKeyDown, "keyDown") \ + CASE_TYPE(kKeyUp, "keyUp") \ CASE_TYPE(kChar, "char") \ - CASE_TYPE(kGestureScrollBegin, "gesturescrollbegin") \ - CASE_TYPE(kGestureScrollEnd, "gesturescrollend") \ - CASE_TYPE(kGestureScrollUpdate, "gesturescrollupdate") \ - CASE_TYPE(kGestureFlingStart, "gestureflingstart") \ - CASE_TYPE(kGestureFlingCancel, "gestureflingcancel") \ - CASE_TYPE(kGesturePinchBegin, "gesturepinchbegin") \ - CASE_TYPE(kGesturePinchEnd, "gesturepinchend") \ - CASE_TYPE(kGesturePinchUpdate, "gesturepinchupdate") \ - CASE_TYPE(kGestureTapDown, "gesturetapdown") \ - CASE_TYPE(kGestureShowPress, "gestureshowpress") \ - CASE_TYPE(kGestureTap, "gesturetap") \ - CASE_TYPE(kGestureTapCancel, "gesturetapcancel") \ - CASE_TYPE(kGestureShortPress, "gestureshortpress") \ - CASE_TYPE(kGestureLongPress, "gesturelongpress") \ - CASE_TYPE(kGestureLongTap, "gesturelongtap") \ - CASE_TYPE(kGestureTwoFingerTap, "gesturetwofingertap") \ - CASE_TYPE(kGestureTapUnconfirmed, "gesturetapunconfirmed") \ - CASE_TYPE(kGestureDoubleTap, "gesturedoubletap") \ - CASE_TYPE(kTouchStart, "touchstart") \ - CASE_TYPE(kTouchMove, "touchmove") \ - CASE_TYPE(kTouchEnd, "touchend") \ - CASE_TYPE(kTouchCancel, "touchcancel") \ - CASE_TYPE(kTouchScrollStarted, "touchscrollstarted") \ - CASE_TYPE(kPointerDown, "pointerdown") \ - CASE_TYPE(kPointerUp, "pointerup") \ - CASE_TYPE(kPointerMove, "pointermove") \ - CASE_TYPE(kPointerRawUpdate, "pointerrawupdate") \ - CASE_TYPE(kPointerCancel, "pointercancel") \ - CASE_TYPE(kPointerCausedUaAction, "pointercauseduaaction") + CASE_TYPE(kGestureScrollBegin, "gestureScrollBegin") \ + CASE_TYPE(kGestureScrollEnd, "gestureScrollEnd") \ + CASE_TYPE(kGestureScrollUpdate, "gestureScrollUpdate") \ + CASE_TYPE(kGestureFlingStart, "gestureFlingStart") \ + CASE_TYPE(kGestureFlingCancel, "gestureFlingCancel") \ + CASE_TYPE(kGesturePinchBegin, "gesturePinchBegin") \ + CASE_TYPE(kGesturePinchEnd, "gesturePinchEnd") \ + CASE_TYPE(kGesturePinchUpdate, "gesturePinchUpdate") \ + CASE_TYPE(kGestureTapDown, "gestureTapDown") \ + CASE_TYPE(kGestureShowPress, "gestureShowPress") \ + CASE_TYPE(kGestureTap, "gestureTap") \ + CASE_TYPE(kGestureTapCancel, "gestureTapCancel") \ + CASE_TYPE(kGestureShortPress, "gestureShortPress") \ + CASE_TYPE(kGestureLongPress, "gestureLongPress") \ + CASE_TYPE(kGestureLongTap, "gestureLongTap") \ + CASE_TYPE(kGestureTwoFingerTap, "gestureTwoFingerTap") \ + CASE_TYPE(kGestureTapUnconfirmed, "gestureTapUnconfirmed") \ + CASE_TYPE(kGestureDoubleTap, "gestureDoubleTap") \ + CASE_TYPE(kTouchStart, "touchStart") \ + CASE_TYPE(kTouchMove, "touchMove") \ + CASE_TYPE(kTouchEnd, "touchEnd") \ + CASE_TYPE(kTouchCancel, "touchCancel") \ + CASE_TYPE(kTouchScrollStarted, "touchScrollStarted") \ + CASE_TYPE(kPointerDown, "pointerDown") \ + CASE_TYPE(kPointerUp, "pointerUp") \ + CASE_TYPE(kPointerMove, "pointerMove") \ + CASE_TYPE(kPointerRawUpdate, "pointerRawUpdate") \ + CASE_TYPE(kPointerCancel, "pointerCancel") \ + CASE_TYPE(kPointerCausedUaAction, "pointerCausedUaAction") bool Converter::FromV8( v8::Isolate* isolate, v8::Handle val, blink::WebInputEvent::Type* out) { - std::string type = base::ToLowerASCII(gin::V8ToString(isolate, val)); -#define CASE_TYPE(event_type, js_name) \ - if (type == js_name) { \ - *out = blink::WebInputEvent::Type::event_type; \ - return true; \ + std::string type = gin::V8ToString(isolate, val); +#define CASE_TYPE(event_type, js_name) \ + if (base::EqualsCaseInsensitiveASCII(type, js_name)) { \ + *out = blink::WebInputEvent::Type::event_type; \ + return true; \ } BLINK_EVENT_TYPES() #undef CASE_TYPE From eecd7243a9585c2def2cb7cec19c7b2465c7e6e2 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 31 Aug 2022 17:48:47 -0700 Subject: [PATCH 03/14] drop wheel_event_monitor_ --- shell/browser/native_window_mac.h | 3 --- shell/browser/native_window_mac.mm | 4 ---- 2 files changed, 7 deletions(-) diff --git a/shell/browser/native_window_mac.h b/shell/browser/native_window_mac.h index ef5ab1b10e12b..390c2997b2211 100644 --- a/shell/browser/native_window_mac.h +++ b/shell/browser/native_window_mac.h @@ -228,9 +228,6 @@ class NativeWindowMac : public NativeWindow, base::scoped_nsobject preview_item_; base::scoped_nsobject touch_bar_; - // Event monitor for scroll wheel event. - id wheel_event_monitor_; - // The NSView that used as contentView of window. // // For frameless window it would fill the whole window. diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 41c3a28aa6f94..e66745a547b70 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -1699,10 +1699,6 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { DCHECK(!IsClosed()); ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this); display::Screen::GetScreen()->RemoveObserver(this); - if (wheel_event_monitor_) { - [NSEvent removeMonitor:wheel_event_monitor_]; - wheel_event_monitor_ = nil; - } } void NativeWindowMac::OverrideNSWindowContentView() { From 13ab40040715a6a13a401490964b98aa08241353 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 31 Aug 2022 17:50:40 -0700 Subject: [PATCH 04/14] fix uaf --- shell/browser/api/electron_api_web_contents.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 305f19829ebf6..f25453a19a865 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -959,6 +959,12 @@ void WebContents::InitWithWebContents( } WebContents::~WebContents() { + if (web_contents()) { + content::RenderViewHost* host = web_contents()->GetRenderViewHost(); + if (host) + host->GetWidget()->RemoveInputEventObserver(this); + } + if (!inspectable_web_contents_) { WebContentsDestroyed(); return; @@ -2073,9 +2079,6 @@ void WebContents::WebContentsDestroyed() { // Clear the pointer stored in wrapper. if (GetAllWebContents().Lookup(id_)) GetAllWebContents().Remove(id_); - content::RenderViewHost* host = web_contents()->GetRenderViewHost(); - if (host) - host->GetWidget()->RemoveInputEventObserver(this); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::HandleScope scope(isolate); v8::Local wrapper; From 33c526ee8858a25ca03969cb7506ae0aed67dd57 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Thu, 8 Sep 2022 17:09:33 -0700 Subject: [PATCH 05/14] fix tests --- docs/api/structures/keyboard-input-event.md | 2 +- spec/api-web-contents-spec.ts | 6 +++--- spec/autofill-spec.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/api/structures/keyboard-input-event.md b/docs/api/structures/keyboard-input-event.md index de7bef2d770f6..3f8b4b5e8d3af 100644 --- a/docs/api/structures/keyboard-input-event.md +++ b/docs/api/structures/keyboard-input-event.md @@ -1,6 +1,6 @@ # KeyboardInputEvent Object extends `InputEvent` -* `type` string - The type of the event, can be `keyDown`, `keyUp` or `char`. +* `type` string - The type of the event, can be `rawKeyDown`, `keyDown`, `keyUp` or `char`. * `keyCode` string - The character that will be sent as the keyboard event. Should only use the valid key codes in [Accelerator](../accelerator.md). diff --git a/spec/api-web-contents-spec.ts b/spec/api-web-contents-spec.ts index 3ceb081c76c9b..73e57db19e011 100644 --- a/spec/api-web-contents-spec.ts +++ b/spec/api-web-contents-spec.ts @@ -590,8 +590,8 @@ describe('webContents module', () => { w.webContents.once('before-input-event', (event, input) => { if (input.key === 'a') event.preventDefault(); }); - w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'a' }); - w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'b' }); + w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'a' }); + w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'b' }); expect(await keyDown).to.equal('b'); }); @@ -624,7 +624,7 @@ describe('webContents module', () => { expect(input.meta).to.equal(opts.meta); }; await testBeforeInput({ - type: 'keyDown', + type: 'rawKeyDown', key: 'A', code: 'KeyA', keyCode: 'a', diff --git a/spec/autofill-spec.ts b/spec/autofill-spec.ts index 4ae39e29f53ad..07652fc1a0db6 100644 --- a/spec/autofill-spec.ts +++ b/spec/autofill-spec.ts @@ -12,15 +12,15 @@ describe('autofill', () => { it('can be selected via keyboard', async () => { const w = new BrowserWindow({ show: true }); await w.loadFile(path.join(fixturesPath, 'pages', 'datalist.html')); - w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Tab' }); + w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'Tab' }); const inputText = 'clap'; for (const keyCode of inputText) { w.webContents.sendInputEvent({ type: 'char', keyCode }); await delay(100); } - w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Down' }); - w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Enter' }); + w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'Down' }); + w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'Enter' }); const value = await w.webContents.executeJavaScript("document.querySelector('input').value"); expect(value).to.equal('Eric Clapton'); From 934da73ee06a5569b2e3d1edde2156180c3c8ed2 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Mon, 12 Sep 2022 14:22:45 -0700 Subject: [PATCH 06/14] fix WebKeyboardEvent::ToV8 --- shell/common/gin_converters/blink_converter.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/shell/common/gin_converters/blink_converter.cc b/shell/common/gin_converters/blink_converter.cc index d62ef3cec6b76..bda0113c05cd3 100644 --- a/shell/common/gin_converters/blink_converter.cc +++ b/shell/common/gin_converters/blink_converter.cc @@ -320,10 +320,7 @@ v8::Local Converter::ToV8( const blink::WebKeyboardEvent& in) { gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate); - if (in.GetType() == blink::WebInputEvent::Type::kRawKeyDown) - dict.Set("type", "keyDown"); - else if (in.GetType() == blink::WebInputEvent::Type::kKeyUp) - dict.Set("type", "keyUp"); + dict.Set("type", in.GetType()); dict.Set("key", ui::KeycodeConverter::DomKeyToKeyString(in.dom_key)); dict.Set("code", ui::KeycodeConverter::DomCodeToCodeString( static_cast(in.dom_code))); From ca15abc31d35f18211bae96b495ba450e5f2bc5d Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 14 Sep 2022 09:53:57 -0700 Subject: [PATCH 07/14] fix case in breaking-changes docs --- docs/breaking-changes.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index 319290bb8ce66..8759751b1dca7 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -43,11 +43,11 @@ win.on('scroll-touch-end', scrollTouchEnd) // Replace with win.webContents.on('input-event', (_, event) => { - if (event.type === 'gesturescrollbegin') { + if (event.type === 'gestureScrollBegin') { scrollTouchBegin() - } else if (event.type === 'gesturescrollupdate') { + } else if (event.type === 'gestureScrollUpdate') { scrollTouchEdge() - } else if (event.type === 'gesturescrollend') { + } else if (event.type === 'gestureScrollEnd') { scrollTouchEnd() } }) @@ -69,11 +69,11 @@ win.on('scroll-touch-end', scrollTouchEnd) // Replace with win.webContents.on('input-event', (_, event) => { - if (event.type === 'gesturescrollbegin') { + if (event.type === 'gestureScrollBegin') { scrollTouchBegin() - } else if (event.type === 'gesturescrollupdate') { + } else if (event.type === 'gestureScrollUpdate') { scrollTouchEdge() - } else if (event.type === 'gesturescrollend') { + } else if (event.type === 'gestureScrollEnd') { scrollTouchEnd() } }) From 8a915c8d74da420e9674590d07d7413967d82e38 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 14 Sep 2022 09:59:08 -0700 Subject: [PATCH 08/14] better links in deprecation docs --- docs/api/browser-window.md | 18 ++++++++++++++++++ docs/breaking-changes.md | 9 +++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 280c266f412c6..469d61723ce6b 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -656,14 +656,32 @@ The following app commands are explicitly supported on Linux: Emitted when scroll wheel event phase has begun. +> **Note** +> This event is deprecated beginning in Electron 21.0.0. See [Breaking +> Changes](breaking-changes.md#deprecated-browserwindow-scroll-touch--events) +> for details of how to migrate to using the [WebContents +> `input-event`](api/web-contents.md#event-input-event) event. + #### Event: 'scroll-touch-end' _macOS_ _Deprecated_ Emitted when scroll wheel event phase has ended. +> **Note** +> This event is deprecated beginning in Electron 21.0.0. See [Breaking +> Changes](breaking-changes.md#deprecated-browserwindow-scroll-touch--events) +> for details of how to migrate to using the [WebContents +> `input-event`](api/web-contents.md#event-input-event) event. + #### Event: 'scroll-touch-edge' _macOS_ _Deprecated_ Emitted when scroll wheel event phase filed upon reaching the edge of element. +> **Note** +> This event is deprecated beginning in Electron 21.0.0. See [Breaking +> Changes](breaking-changes.md#deprecated-browserwindow-scroll-touch--events) +> for details of how to migrate to using the [WebContents +> `input-event`](api/web-contents.md#event-input-event) event. + #### Event: 'swipe' _macOS_ Returns: diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index 8759751b1dca7..eb7dd09e8e24a 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -32,8 +32,9 @@ webContents.setWindowOpenHandler((details) => { ### Removed: BrowserWindow `scroll-touch-*` events -The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on -BrowserWindow have been removed. +The deprecated `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` +events on BrowserWindow have been removed. Instead, use the newly available +[`input-event` event](api/web-contents.md#event-input-event) on WebContents. ```js // Removed in Electron 22.0 @@ -58,8 +59,8 @@ win.webContents.on('input-event', (_, event) => { ### Deprecated: BrowserWindow `scroll-touch-*` events The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on -BrowserWindow are deprecated. Instead, use the newly available `input-event` -event on WebContents. +BrowserWindow are deprecated. Instead, use the newly available [`input-event` +event](api/web-contents.md#event-input-event) on WebContents. ```js // Deprecated From 3e7187f147b466e31db62f9726b50d3f8ea96bba Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 14 Sep 2022 10:01:06 -0700 Subject: [PATCH 09/14] update deprecation schedule for 22/23 --- docs/api/browser-window.md | 6 +++--- docs/breaking-changes.md | 36 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 469d61723ce6b..859b1876a1669 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -657,7 +657,7 @@ The following app commands are explicitly supported on Linux: Emitted when scroll wheel event phase has begun. > **Note** -> This event is deprecated beginning in Electron 21.0.0. See [Breaking +> This event is deprecated beginning in Electron 22.0.0. See [Breaking > Changes](breaking-changes.md#deprecated-browserwindow-scroll-touch--events) > for details of how to migrate to using the [WebContents > `input-event`](api/web-contents.md#event-input-event) event. @@ -667,7 +667,7 @@ Emitted when scroll wheel event phase has begun. Emitted when scroll wheel event phase has ended. > **Note** -> This event is deprecated beginning in Electron 21.0.0. See [Breaking +> This event is deprecated beginning in Electron 22.0.0. See [Breaking > Changes](breaking-changes.md#deprecated-browserwindow-scroll-touch--events) > for details of how to migrate to using the [WebContents > `input-event`](api/web-contents.md#event-input-event) event. @@ -677,7 +677,7 @@ Emitted when scroll wheel event phase has ended. Emitted when scroll wheel event phase filed upon reaching the edge of element. > **Note** -> This event is deprecated beginning in Electron 21.0.0. See [Breaking +> This event is deprecated beginning in Electron 22.0.0. See [Breaking > Changes](breaking-changes.md#deprecated-browserwindow-scroll-touch--events) > for details of how to migrate to using the [WebContents > `input-event`](api/web-contents.md#event-input-event) event. diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index eb7dd09e8e24a..cea192b4a6a4c 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -12,23 +12,7 @@ This document uses the following convention to categorize breaking changes: * **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release. * **Removed:** An API or feature was removed, and is no longer supported by Electron. -## Planned Breaking API Changes (22.0) - -### Removed: WebContents `new-window` event - -The `new-window` event of WebContents has been removed. It is replaced by [`webContents.setWindowOpenHandler()`](api/web-contents.md#contentssetwindowopenhandlerhandler). - -```js -// Removed in Electron 21 -webContents.on('new-window', (event) => { - event.preventDefault() -}) - -// Replace with -webContents.setWindowOpenHandler((details) => { - return { action: 'deny' } -}) -``` +## Planned Breaking API Changes (23.0) ### Removed: BrowserWindow `scroll-touch-*` events @@ -54,7 +38,23 @@ win.webContents.on('input-event', (_, event) => { }) ``` -## Planned Breaking API Changes (21.0) +## Planned Breaking API Changes (22.0) + +### Removed: WebContents `new-window` event + +The `new-window` event of WebContents has been removed. It is replaced by [`webContents.setWindowOpenHandler()`](api/web-contents.md#contentssetwindowopenhandlerhandler). + +```js +// Removed in Electron 21 +webContents.on('new-window', (event) => { + event.preventDefault() +}) + +// Replace with +webContents.setWindowOpenHandler((details) => { + return { action: 'deny' } +}) +``` ### Deprecated: BrowserWindow `scroll-touch-*` events From 9ab2c9be0911b47050bfb2f85138bfe10edc7227 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 14 Sep 2022 10:33:50 -0700 Subject: [PATCH 10/14] emit scroll-touch-edge on begin/end --- lib/browser/api/browser-window.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/browser/api/browser-window.ts b/lib/browser/api/browser-window.ts index ed8f26fa29339..6199d4a5d70df 100644 --- a/lib/browser/api/browser-window.ts +++ b/lib/browser/api/browser-window.ts @@ -50,6 +50,7 @@ BrowserWindow.prototype._init = function (this: BWT) { if (e.type === 'gestureScrollBegin') { if (this.listenerCount('scroll-touch-begin') !== 0) { warn(); + this.emit('scroll-touch-edge'); this.emit('scroll-touch-begin'); } } else if (e.type === 'gestureScrollUpdate') { @@ -60,6 +61,7 @@ BrowserWindow.prototype._init = function (this: BWT) { } else if (e.type === 'gestureScrollEnd') { if (this.listenerCount('scroll-touch-end') !== 0) { warn(); + this.emit('scroll-touch-edge'); this.emit('scroll-touch-end'); } } From f93d33d40a6156ac244131b4b38f11b623a12301 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 14 Sep 2022 10:49:01 -0700 Subject: [PATCH 11/14] convert keyDown<->rawKeyDown in sendInputEvent/before-input-event for back compat --- shell/browser/api/electron_api_web_contents.cc | 10 +++++++++- spec/api-web-contents-spec.ts | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 86e32830508d1..11b607bb4d260 100755 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1266,7 +1266,12 @@ content::KeyboardEventProcessingResult WebContents::PreHandleKeyboardEvent( if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown || event.GetType() == blink::WebInputEvent::Type::kKeyUp) { - bool prevent_default = Emit("before-input-event", event); + // For backwards compatibility, pretend that `kRawKeyDown` events are + // actually `kKeyDown`. + content::NativeWebKeyboardEvent tweaked_event(event); + if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown) + tweaked_event.SetType(blink::WebInputEvent::Type::kKeyDown); + bool prevent_default = Emit("before-input-event", tweaked_event); if (prevent_default) { return content::KeyboardEventProcessingResult::HANDLED; } @@ -3065,6 +3070,9 @@ void WebContents::SendInputEvent(v8::Isolate* isolate, blink::WebKeyboardEvent::Type::kRawKeyDown, blink::WebInputEvent::Modifiers::kNoModifiers, ui::EventTimeForNow()); if (gin::ConvertFromV8(isolate, input_event, &keyboard_event)) { + // For backwards compatibility, convert `kKeyDown` to `kRawKeyDown`. + if (keyboard_event.GetType() == blink::WebKeyboardEvent::Type::kKeyDown) + keyboard_event.SetType(blink::WebKeyboardEvent::Type::kRawKeyDown); rwh->ForwardKeyboardEvent(keyboard_event); return; } diff --git a/spec/api-web-contents-spec.ts b/spec/api-web-contents-spec.ts index 73e57db19e011..3ceb081c76c9b 100644 --- a/spec/api-web-contents-spec.ts +++ b/spec/api-web-contents-spec.ts @@ -590,8 +590,8 @@ describe('webContents module', () => { w.webContents.once('before-input-event', (event, input) => { if (input.key === 'a') event.preventDefault(); }); - w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'a' }); - w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'b' }); + w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'a' }); + w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'b' }); expect(await keyDown).to.equal('b'); }); @@ -624,7 +624,7 @@ describe('webContents module', () => { expect(input.meta).to.equal(opts.meta); }; await testBeforeInput({ - type: 'rawKeyDown', + type: 'keyDown', key: 'A', code: 'KeyA', keyCode: 'a', From a672df5bc4756d4d788fe419340159a8309dc356 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Mon, 26 Sep 2022 14:49:28 -0700 Subject: [PATCH 12/14] Update docs/breaking-changes.md Co-authored-by: Samuel Maddock --- docs/breaking-changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index cea192b4a6a4c..03d12a6232b08 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -21,7 +21,7 @@ events on BrowserWindow have been removed. Instead, use the newly available [`input-event` event](api/web-contents.md#event-input-event) on WebContents. ```js -// Removed in Electron 22.0 +// Removed in Electron 23.0 win.on('scroll-touch-begin', scrollTouchBegin) win.on('scroll-touch-edge', scrollTouchEdge) win.on('scroll-touch-end', scrollTouchEnd) From 77adee30ba5bc75baa7aec847f56596738bf1854 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Mon, 26 Sep 2022 14:49:55 -0700 Subject: [PATCH 13/14] undo changes to autofill spec --- spec/autofill-spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/autofill-spec.ts b/spec/autofill-spec.ts index 07652fc1a0db6..4ae39e29f53ad 100644 --- a/spec/autofill-spec.ts +++ b/spec/autofill-spec.ts @@ -12,15 +12,15 @@ describe('autofill', () => { it('can be selected via keyboard', async () => { const w = new BrowserWindow({ show: true }); await w.loadFile(path.join(fixturesPath, 'pages', 'datalist.html')); - w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'Tab' }); + w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Tab' }); const inputText = 'clap'; for (const keyCode of inputText) { w.webContents.sendInputEvent({ type: 'char', keyCode }); await delay(100); } - w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'Down' }); - w.webContents.sendInputEvent({ type: 'rawKeyDown', keyCode: 'Enter' }); + w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Down' }); + w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Enter' }); const value = await w.webContents.executeJavaScript("document.querySelector('input').value"); expect(value).to.equal('Eric Clapton'); From c01b9c9207cf4792cd4fe2954bac5dd4f80e6605 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Mon, 26 Sep 2022 15:02:51 -0700 Subject: [PATCH 14/14] Testing SSH signing