diff --git a/docs/api/base-window.md b/docs/api/base-window.md index 38a82de051b0..d23ced860c5b 100644 --- a/docs/api/base-window.md +++ b/docs/api/base-window.md @@ -342,12 +342,12 @@ Emitted when the window has closed a sheet. Emitted when the native new tab button is clicked. -#### Event: 'system-context-menu' _Windows_ +#### Event: 'system-context-menu' _Windows_ _Linux_ Returns: * `event` Event -* `point` [Point](structures/point.md) - The screen coordinates the context menu was triggered at +* `point` [Point](structures/point.md) - The screen coordinates where the context menu was triggered. Emitted when the system context menu is triggered on the window, this is normally only triggered when the user right clicks on the non-client area @@ -356,6 +356,8 @@ as `-webkit-app-region: drag` in a frameless window. Calling `event.preventDefault()` will prevent the menu from being displayed. +To convert `point` to DIP, use [`screen.screenToDipPoint(point)`](./screen.md#screenscreentodippointpoint-windows). + ### Static Methods The `BaseWindow` class has the following static methods: diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 46f3d0289edf..96ef6896ffbe 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -421,12 +421,12 @@ Emitted when the window has closed a sheet. Emitted when the native new tab button is clicked. -#### Event: 'system-context-menu' _Windows_ +#### Event: 'system-context-menu' _Windows_ _Linux_ Returns: * `event` Event -* `point` [Point](structures/point.md) - The screen coordinates the context menu was triggered at +* `point` [Point](structures/point.md) - The screen coordinates where the context menu was triggered. Emitted when the system context menu is triggered on the window, this is normally only triggered when the user right clicks on the non-client area @@ -435,6 +435,8 @@ as `-webkit-app-region: drag` in a frameless window. Calling `event.preventDefault()` will prevent the menu from being displayed. +To convert `point` to DIP, use [`screen.screenToDipPoint(point)`](./screen.md#screenscreentodippointpoint-windows). + ### Static Methods The `BrowserWindow` class has the following static methods: diff --git a/shell/browser/ui/electron_desktop_window_tree_host_linux.cc b/shell/browser/ui/electron_desktop_window_tree_host_linux.cc index eb8d61f7f6af..c58e7726e903 100644 --- a/shell/browser/ui/electron_desktop_window_tree_host_linux.cc +++ b/shell/browser/ui/electron_desktop_window_tree_host_linux.cc @@ -17,6 +17,9 @@ #include "shell/browser/native_window_views.h" #include "shell/browser/ui/views/client_frame_view_linux.h" #include "third_party/skia/include/core/SkRegion.h" +#include "ui/aura/window_delegate.h" +#include "ui/base/hit_test.h" +#include "ui/display/screen.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/skia_conversions.h" #include "ui/linux/linux_ui.h" @@ -262,13 +265,45 @@ void ElectronDesktopWindowTreeHostLinux::DispatchEvent(ui::Event* event) { is_mousedown && (mouse_event->IsRightMouseButton() || (mouse_event->IsLeftMouseButton() && mouse_event->IsControlDown())); - if (is_system_menu_trigger) { - electron::api::WebContents::SetDisableDraggableRegions(true); + + if (!is_system_menu_trigger) { views::DesktopWindowTreeHostLinux::DispatchEvent(event); - electron::api::WebContents::SetDisableDraggableRegions(false); return; } + + // Determine the non-client area and dispatch 'system-context-menu'. + if (GetContentWindow() && GetContentWindow()->delegate()) { + ui::LocatedEvent* located_event = event->AsLocatedEvent(); + gfx::PointF location = located_event->location_f(); + gfx::PointF location_in_dip = + GetRootTransform().InverseMapPoint(location).value_or(location); + int hit_test_code = GetContentWindow()->delegate()->GetNonClientComponent( + gfx::ToRoundedPoint(location_in_dip)); + if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE) { + bool prevent_default = false; + native_window_view_->NotifyWindowSystemContextMenu( + located_event->x(), located_event->y(), &prevent_default); + + // If |prevent_default| is true, then the user might want to show a + // custom menu - proceed propagation and emit context-menu in the + // renderer. Otherwise, show the native system window controls menu. + if (prevent_default) { + electron::api::WebContents::SetDisableDraggableRegions(true); + views::DesktopWindowTreeHostLinux::DispatchEvent(event); + electron::api::WebContents::SetDisableDraggableRegions(false); + } else { + if (ui::OzonePlatform::GetInstance() + ->GetPlatformRuntimeProperties() + .supports_server_window_menus) { + views::DesktopWindowTreeHostLinux::ShowWindowControlsMenu( + display::Screen::GetScreen()->GetCursorScreenPoint()); + } + } + return; + } + } } + views::DesktopWindowTreeHostLinux::DispatchEvent(event); }