From 3c973f1554208e019e17a3332bc0372588279d3f Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 29 Mar 2022 20:30:37 +0900 Subject: [PATCH] fix: calling of X11 functions when running under Wayland Backports https://github.com/electron/electron/pull/33355 --- BUILD.gn | 1 - filenames.gni | 2 - patches/chromium/.patches | 3 +- ...tform_electron_can_call_x11_property.patch | 37 +++ patches/chromium/ui_gtk_public_header.patch | 20 +- shell/browser/electron_browser_main_parts.h | 6 - shell/browser/native_window.cc | 2 +- shell/browser/native_window_views.cc | 253 ++++++++++-------- shell/browser/native_window_views.h | 15 +- ...electron_desktop_window_tree_host_linux.cc | 73 ++++- .../electron_desktop_window_tree_host_linux.h | 3 + shell/browser/ui/file_dialog_gtk.cc | 18 +- shell/browser/ui/gtk/menu_util.cc | 30 ++- shell/browser/ui/message_box_gtk.cc | 16 +- shell/browser/ui/x/window_state_watcher.cc | 82 ------ shell/browser/ui/x/window_state_watcher.h | 45 ---- 16 files changed, 300 insertions(+), 306 deletions(-) create mode 100644 patches/chromium/introduce_ozoneplatform_electron_can_call_x11_property.patch delete mode 100644 shell/browser/ui/x/window_state_watcher.cc delete mode 100644 shell/browser/ui/x/window_state_watcher.h diff --git a/BUILD.gn b/BUILD.gn index a2d9691301c2e..aeda48b30702d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -556,7 +556,6 @@ source_set("electron_lib") { defines += [ # Disable warnings for g_settings_list_schemas. "GLIB_DISABLE_DEPRECATION_WARNINGS", - "USE_X11=1", ] sources += [ diff --git a/filenames.gni b/filenames.gni index cec29303da18f..03184a576a651 100644 --- a/filenames.gni +++ b/filenames.gni @@ -53,8 +53,6 @@ filenames = { "shell/browser/ui/views/global_menu_bar_x11.h", "shell/browser/ui/x/event_disabler.cc", "shell/browser/ui/x/event_disabler.h", - "shell/browser/ui/x/window_state_watcher.cc", - "shell/browser/ui/x/window_state_watcher.h", "shell/browser/ui/x/x_window_utils.cc", "shell/browser/ui/x/x_window_utils.h", ] diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 59887026a6c99..7a653575675da 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -67,7 +67,6 @@ feat_enable_offscreen_rendering_with_viz_compositor.patch gpu_notify_when_dxdiag_request_fails.patch feat_allow_embedders_to_add_observers_on_created_hunspell.patch feat_add_onclose_to_messageport.patch -ui_gtk_public_header.patch allow_in-process_windows_to_have_different_web_prefs.patch refactor_expose_cursor_changes_to_the_webcontentsobserver.patch crash_allow_setting_more_options.patch @@ -118,3 +117,5 @@ build_disable_partition_alloc_on_mac.patch fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch remove_incorrect_width_height_adjustments.patch set_dpi_correctly_during_main_window_creation.patch +ui_gtk_public_header.patch +introduce_ozoneplatform_electron_can_call_x11_property.patch diff --git a/patches/chromium/introduce_ozoneplatform_electron_can_call_x11_property.patch b/patches/chromium/introduce_ozoneplatform_electron_can_call_x11_property.patch new file mode 100644 index 0000000000000..38a58c4e645fa --- /dev/null +++ b/patches/chromium/introduce_ozoneplatform_electron_can_call_x11_property.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Marek Rusinowski +Date: Wed, 23 Mar 2022 21:09:37 +0100 +Subject: introduce OzonePlatform::electron_can_call_x11 property + +We expose this additonal property in the OzonePlatform to be able to easily +determine whatever we can call X11 functions without crashing the application +at rutime. It would be best if eventually all usages of this property were +replaced with clean ozone native implementations. + +diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc +index 013abeeea0bb9c52bb52cb6bf3972f78d21eef9a..88668a14e38b4391a7951ed16072b4c85a2cb6cb 100644 +--- a/ui/ozone/platform/x11/ozone_platform_x11.cc ++++ b/ui/ozone/platform/x11/ozone_platform_x11.cc +@@ -200,6 +200,7 @@ class OzonePlatformX11 : public OzonePlatform, + properties->supports_vulkan_swap_chain = true; + properties->uses_external_vulkan_image_factory = true; + properties->skia_can_fall_back_to_x11 = true; ++ properties->electron_can_call_x11 = true; + properties->platform_shows_drag_image = false; + properties->supports_global_application_menus = true; + properties->app_modal_dialogs_use_event_blocker = true; +diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h +index 4af0f65265b6402031f0f6a25660cb850b9ec1ed..a425243b7c67fbec28a5704b5e953b417fbdfa0f 100644 +--- a/ui/ozone/public/ozone_platform.h ++++ b/ui/ozone/public/ozone_platform.h +@@ -132,6 +132,10 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform { + // Linux only: determines if Skia can fall back to the X11 output device. + bool skia_can_fall_back_to_x11 = false; + ++ // Linux only: determines is Electron can call selected X11 functions while ++ // it migrates to pure ozone abstractions. ++ bool electron_can_call_x11 = false; ++ + // Wayland only: determines whether BufferQueue needs a background image to + // be stacked below an AcceleratedWidget to make a widget opaque. + bool needs_background_image = false; diff --git a/patches/chromium/ui_gtk_public_header.patch b/patches/chromium/ui_gtk_public_header.patch index 62922abc391ad..8a98d1669ca39 100644 --- a/patches/chromium/ui_gtk_public_header.patch +++ b/patches/chromium/ui_gtk_public_header.patch @@ -1,24 +1,32 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: deepak1556 -Date: Fri, 10 Apr 2020 17:47:18 -0700 +Date: Tue, 29 Mar 2022 20:17:54 +0900 Subject: ui_gtk_public_header.patch -Allow electron to depend on //ui/gtk/gtk_util.h +Allow electron to depend on gtk_util.h and gtk_ui.h from //ui/gtk/ diff --git a/ui/gtk/BUILD.gn b/ui/gtk/BUILD.gn -index db29cdca6f02fb8ca9dd0f25e13ed902589adc25..6fa1496b4d529ccf7e4e543579462f990aae5ede 100644 +index db29cdca6f02fb8ca9dd0f25e13ed902589adc25..48f19e145cb81f4e4d2fdd6f3bd1cc72128358a7 100644 --- a/ui/gtk/BUILD.gn +++ b/ui/gtk/BUILD.gn -@@ -39,7 +39,7 @@ generate_stubs("gtk_stubs") { +@@ -39,7 +39,11 @@ generate_stubs("gtk_stubs") { } component("gtk") { - public = [ "gtk_ui_factory.h" ] -+ public = [ "gtk_ui_factory.h", "gtk_util.h" ] ++ public = [ ++ "gtk_ui.h", ++ "gtk_ui_factory.h", ++ "gtk_util.h", ++ ] sources = [ "gtk_color_mixers.cc", -@@ -53,7 +53,6 @@ component("gtk") { +@@ -49,11 +53,9 @@ component("gtk") { + "gtk_key_bindings_handler.cc", + "gtk_key_bindings_handler.h", + "gtk_ui.cc", +- "gtk_ui.h", "gtk_ui_factory.cc", "gtk_ui_platform.h", "gtk_util.cc", diff --git a/shell/browser/electron_browser_main_parts.h b/shell/browser/electron_browser_main_parts.h index 321949ee7e89e..9fe5f2b4f033f 100644 --- a/shell/browser/electron_browser_main_parts.h +++ b/shell/browser/electron_browser_main_parts.h @@ -36,12 +36,6 @@ class Screen; } #endif -#if defined(USE_X11) -namespace ui { -class GtkUiPlatform; -} -#endif - namespace device { class GeolocationManager; } diff --git a/shell/browser/native_window.cc b/shell/browser/native_window.cc index 538755af60291..65436f7b5b877 100644 --- a/shell/browser/native_window.cc +++ b/shell/browser/native_window.cc @@ -25,7 +25,7 @@ #include "ui/display/win/screen_win.h" #endif -#if defined(USE_OZONE) || defined(USE_X11) +#if defined(USE_OZONE) #include "ui/base/ui_base_features.h" #include "ui/ozone/public/ozone_platform.h" #endif diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index 0312b393536c3..6e3dd91b23ed6 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -19,7 +19,6 @@ #include "content/public/browser/desktop_media_id.h" #include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/native_browser_view_views.h" -#include "shell/browser/native_window_features.h" #include "shell/browser/ui/drag_util.h" #include "shell/browser/ui/inspectable_web_contents.h" #include "shell/browser/ui/inspectable_web_contents_view.h" @@ -55,20 +54,16 @@ #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" #include "ui/views/window/native_frame_view.h" -#if defined(USE_X11) +#if defined(USE_OZONE) #include "shell/browser/ui/views/global_menu_bar_x11.h" #include "shell/browser/ui/x/event_disabler.h" -#include "shell/browser/ui/x/window_state_watcher.h" #include "shell/browser/ui/x/x_window_utils.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/x/shape.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/xproto.h" #include "ui/gfx/x/xproto_util.h" -#endif - -#if defined(USE_OZONE) || defined(USE_X11) -#include "ui/base/ui_base_features.h" +#include "ui/ozone/public/ozone_platform.h" #endif #elif defined(OS_WIN) @@ -130,6 +125,26 @@ gfx::Rect DIPToScreenRect(HWND hwnd, const gfx::Rect& pixel_bounds) { #endif +#if defined(USE_OZONE) + +bool CreateGlobalMenuBar() { + return ui::OzonePlatform::GetInstance() + ->GetPlatformProperties() + .supports_global_application_menus; +} + +#endif + +#if defined(USE_OZONE_PLATFORM_X11) + +bool IsX11() { + return ui::OzonePlatform::GetInstance() + ->GetPlatformProperties() + .electron_can_call_x11; +} + +#endif + class NativeWindowClientView : public views::ClientView { public: NativeWindowClientView(views::Widget* widget, @@ -257,12 +272,10 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options, params.wm_class_name = base::ToLowerASCII(name); params.wm_class_class = name; - if (base::FeatureList::IsEnabled(features::kWaylandWindowDecorations)) { - auto* native_widget = new views::DesktopNativeWidgetAura(widget()); - params.native_widget = native_widget; - params.desktop_window_tree_host = - new ElectronDesktopWindowTreeHostLinux(this, native_widget); - } + auto* native_widget = new views::DesktopNativeWidgetAura(widget()); + params.native_widget = native_widget; + params.desktop_window_tree_host = + new ElectronDesktopWindowTreeHostLinux(this, native_widget); #endif widget()->Init(std::move(params)); @@ -274,54 +287,51 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options, std::string window_type; options.Get(options::kType, &window_type); -#if defined(USE_X11) - // Start monitoring window states. - window_state_watcher_ = std::make_unique(this); - +#if defined(OS_LINUX) // Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set. bool use_dark_theme = false; if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) { SetGTKDarkThemeEnabled(use_dark_theme); } -#endif -#if defined(OS_LINUX) if (parent) SetParentWindow(parent); #endif -#if defined(USE_X11) - // Before the window is mapped the SetWMSpecState can not work, so we have - // to manually set the _NET_WM_STATE. - std::vector state_atom_list; - bool skip_taskbar = false; - if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) { - state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); - } +#if defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) { + // Before the window is mapped the SetWMSpecState can not work, so we have + // to manually set the _NET_WM_STATE. + std::vector state_atom_list; + bool skip_taskbar = false; + if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) { + state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); + } - // Before the window is mapped, there is no SHOW_FULLSCREEN_STATE. - if (fullscreen) { - state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_FULLSCREEN")); - } + // Before the window is mapped, there is no SHOW_FULLSCREEN_STATE. + if (fullscreen) { + state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_FULLSCREEN")); + } - if (parent) { - // Force using dialog type for child window. - window_type = "dialog"; + if (parent) { + // Force using dialog type for child window. + window_type = "dialog"; - // Modal window needs the _NET_WM_STATE_MODAL hint. - if (is_modal()) - state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_MODAL")); - } + // Modal window needs the _NET_WM_STATE_MODAL hint. + if (is_modal()) + state_atom_list.push_back(x11::GetAtom("_NET_WM_STATE_MODAL")); + } - if (!state_atom_list.empty()) - SetArrayProperty(static_cast(GetAcceleratedWidget()), - x11::GetAtom("_NET_WM_STATE"), x11::Atom::ATOM, - state_atom_list); + if (!state_atom_list.empty()) + SetArrayProperty(static_cast(GetAcceleratedWidget()), + x11::GetAtom("_NET_WM_STATE"), x11::Atom::ATOM, + state_atom_list); - // Set the _NET_WM_WINDOW_TYPE. - if (!window_type.empty()) - SetWindowType(static_cast(GetAcceleratedWidget()), - window_type); + // Set the _NET_WM_WINDOW_TYPE. + if (!window_type.empty()) + SetWindowType(static_cast(GetAcceleratedWidget()), + window_type); + } #endif #if defined(OS_WIN) @@ -418,11 +428,13 @@ NativeWindowViews::~NativeWindowViews() { } void NativeWindowViews::SetGTKDarkThemeEnabled(bool use_dark_theme) { -#if defined(USE_X11) - const std::string color = use_dark_theme ? "dark" : "light"; - x11::SetStringProperty(static_cast(GetAcceleratedWidget()), - x11::GetAtom("_GTK_THEME_VARIANT"), - x11::GetAtom("UTF8_STRING"), color); +#if defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) { + const std::string color = use_dark_theme ? "dark" : "light"; + x11::SetStringProperty(static_cast(GetAcceleratedWidget()), + x11::GetAtom("_GTK_THEME_VARIANT"), + x11::GetAtom("UTF8_STRING"), color); + } #endif } @@ -477,7 +489,7 @@ void NativeWindowViews::Show() { NotifyWindowShow(); -#if defined(USE_X11) +#if defined(USE_OZONE) if (global_menu_bar_) global_menu_bar_->OnWindowMapped(); #endif @@ -488,7 +500,7 @@ void NativeWindowViews::ShowInactive() { NotifyWindowShow(); -#if defined(USE_X11) +#if defined(USE_OZONE) if (global_menu_bar_) global_menu_bar_->OnWindowMapped(); #endif @@ -502,7 +514,7 @@ void NativeWindowViews::Hide() { NotifyWindowHide(); -#if defined(USE_X11) +#if defined(USE_OZONE) if (global_menu_bar_) global_menu_bar_->OnWindowUnmapped(); #endif @@ -524,8 +536,9 @@ bool NativeWindowViews::IsEnabled() { #if defined(OS_WIN) return ::IsWindowEnabled(GetAcceleratedWidget()); #elif defined(OS_LINUX) -#if defined(USE_X11) - return !event_disabler_.get(); +#if defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) + return !event_disabler_.get(); #endif NOTIMPLEMENTED(); return true; @@ -564,16 +577,18 @@ void NativeWindowViews::SetEnabledInternal(bool enable) { #if defined(OS_WIN) ::EnableWindow(GetAcceleratedWidget(), enable); -#elif defined(USE_X11) - views::DesktopWindowTreeHostPlatform* tree_host = - views::DesktopWindowTreeHostLinux::GetHostForWidget( - GetAcceleratedWidget()); - if (enable) { - tree_host->RemoveEventRewriter(event_disabler_.get()); - event_disabler_.reset(); - } else { - event_disabler_ = std::make_unique(); - tree_host->AddEventRewriter(event_disabler_.get()); +#elif defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) { + views::DesktopWindowTreeHostPlatform* tree_host = + views::DesktopWindowTreeHostLinux::GetHostForWidget( + GetAcceleratedWidget()); + if (enable) { + tree_host->RemoveEventRewriter(event_disabler_.get()); + event_disabler_.reset(); + } else { + event_disabler_ = std::make_unique(); + tree_host->AddEventRewriter(event_disabler_.get()); + } } #endif } @@ -790,12 +805,14 @@ bool NativeWindowViews::MoveAbove(const std::string& sourceId) { ::SetWindowPos(GetAcceleratedWidget(), GetWindow(otherWindow, GW_HWNDPREV), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); -#elif defined(USE_X11) - if (!IsWindowValid(static_cast(id.id))) - return false; +#elif defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) { + if (!IsWindowValid(static_cast(id.id))) + return false; - electron::MoveWindowAbove(static_cast(GetAcceleratedWidget()), - static_cast(id.id)); + electron::MoveWindowAbove(static_cast(GetAcceleratedWidget()), + static_cast(id.id)); + } #endif return true; @@ -810,9 +827,10 @@ void NativeWindowViews::MoveTop() { ::SetWindowPos(GetAcceleratedWidget(), HWND_TOP, pos.x(), pos.y(), size.width(), size.height(), SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); -#elif defined(USE_X11) - electron::MoveWindowToForeground( - static_cast(GetAcceleratedWidget())); +#elif defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) + electron::MoveWindowToForeground( + static_cast(GetAcceleratedWidget())); #endif } @@ -994,9 +1012,10 @@ void NativeWindowViews::SetSkipTaskbar(bool skip) { taskbar->AddTab(GetAcceleratedWidget()); taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget()); } -#elif defined(USE_X11) - SetWMSpecState(static_cast(GetAcceleratedWidget()), skip, - x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); +#elif defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) + SetWMSpecState(static_cast(GetAcceleratedWidget()), skip, + x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); #endif } @@ -1096,24 +1115,28 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) { } else { SetForwardMouseMessages(forward); } -#elif defined(USE_X11) - auto* connection = x11::Connection::Get(); - if (ignore) { - x11::Rectangle r{0, 0, 1, 1}; - connection->shape().Rectangles({ - .operation = x11::Shape::So::Set, - .destination_kind = x11::Shape::Sk::Input, - .ordering = x11::ClipOrdering::YXBanded, - .destination_window = static_cast(GetAcceleratedWidget()), - .rectangles = {r}, - }); - } else { - connection->shape().Mask({ - .operation = x11::Shape::So::Set, - .destination_kind = x11::Shape::Sk::Input, - .destination_window = static_cast(GetAcceleratedWidget()), - .source_bitmap = x11::Pixmap::None, - }); +#elif defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) { + auto* connection = x11::Connection::Get(); + if (ignore) { + x11::Rectangle r{0, 0, 1, 1}; + connection->shape().Rectangles({ + .operation = x11::Shape::So::Set, + .destination_kind = x11::Shape::Sk::Input, + .ordering = x11::ClipOrdering::YXBanded, + .destination_window = + static_cast(GetAcceleratedWidget()), + .rectangles = {r}, + }); + } else { + connection->shape().Mask({ + .operation = x11::Shape::So::Set, + .destination_kind = x11::Shape::Sk::Input, + .destination_window = + static_cast(GetAcceleratedWidget()), + .source_bitmap = x11::Pixmap::None, + }); + } } #endif } @@ -1160,7 +1183,7 @@ bool NativeWindowViews::IsFocusable() { } void NativeWindowViews::SetMenu(ElectronMenuModel* menu_model) { -#if defined(USE_X11) +#if defined(USE_OZONE) // Remove global menu bar. if (global_menu_bar_ && menu_model == nullptr) { global_menu_bar_.reset(); @@ -1169,7 +1192,7 @@ void NativeWindowViews::SetMenu(ElectronMenuModel* menu_model) { } // Use global application menu bar when possible. - if (ShouldUseGlobalMenuBar()) { + if (CreateGlobalMenuBar() && ShouldUseGlobalMenuBar()) { if (!global_menu_bar_) global_menu_bar_ = std::make_unique(this); if (global_menu_bar_->IsServerStarted()) { @@ -1256,12 +1279,13 @@ void NativeWindowViews::SetTopBrowserView(NativeBrowserView* view) { void NativeWindowViews::SetParentWindow(NativeWindow* parent) { NativeWindow::SetParentWindow(parent); -#if defined(USE_X11) - x11::SetProperty( - static_cast(GetAcceleratedWidget()), - x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW, - parent ? static_cast(parent->GetAcceleratedWidget()) - : ui::GetX11RootWindow()); +#if defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) + x11::SetProperty( + static_cast(GetAcceleratedWidget()), + x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW, + parent ? static_cast(parent->GetAcceleratedWidget()) + : ui::GetX11RootWindow()); #elif defined(OS_WIN) // To set parentship between windows into Windows is better to play with the // owner instead of the parent, as Windows natively seems to do if a parent @@ -1339,18 +1363,19 @@ void NativeWindowViews::SetVisibleOnAllWorkspaces( } bool NativeWindowViews::IsVisibleOnAllWorkspaces() { -#if defined(USE_X11) - // Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to - // determine whether the current window is visible on all workspaces. - x11::Atom sticky_atom = x11::GetAtom("_NET_WM_STATE_STICKY"); - std::vector wm_states; - GetArrayProperty(static_cast(GetAcceleratedWidget()), - x11::GetAtom("_NET_WM_STATE"), &wm_states); - return std::find(wm_states.begin(), wm_states.end(), sticky_atom) != - wm_states.end(); -#else - return false; +#if defined(USE_OZONE_PLATFORM_X11) + if (IsX11()) { + // Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to + // determine whether the current window is visible on all workspaces. + x11::Atom sticky_atom = x11::GetAtom("_NET_WM_STATE_STICKY"); + std::vector wm_states; + GetArrayProperty(static_cast(GetAcceleratedWidget()), + x11::GetAtom("_NET_WM_STATE"), &wm_states); + return std::find(wm_states.begin(), wm_states.end(), sticky_atom) != + wm_states.end(); + } #endif + return false; } content::DesktopMediaID NativeWindowViews::GetDesktopMediaID() const { diff --git a/shell/browser/native_window_views.h b/shell/browser/native_window_views.h index caaa690da917a..1be0da6dcbf74 100644 --- a/shell/browser/native_window_views.h +++ b/shell/browser/native_window_views.h @@ -15,6 +15,13 @@ #include "shell/common/api/api.mojom.h" #include "ui/views/widget/widget_observer.h" +#if defined(USE_OZONE) +#include "ui/ozone/buildflags.h" +#if BUILDFLAG(OZONE_PLATFORM_X11) +#define USE_OZONE_PLATFORM_X11 +#endif +#endif + #if defined(OS_WIN) #include "base/win/scoped_gdi_object.h" #include "shell/browser/ui/win/taskbar_host.h" @@ -31,7 +38,7 @@ class GlobalMenuBarX11; class RootView; class WindowStateWatcher; -#if defined(USE_X11) +#if defined(USE_OZONE_PLATFORM_X11) class EventDisabler; #endif @@ -252,12 +259,12 @@ class NativeWindowViews : public NativeWindow, // events from resizing the window. extensions::SizeConstraints old_size_constraints_; -#if defined(USE_X11) +#if defined(USE_OZONE) std::unique_ptr global_menu_bar_; - // Handles window state events. - std::unique_ptr window_state_watcher_; +#endif +#if defined(USE_OZONE_PLATFORM_X11) // To disable the mouse events. std::unique_ptr event_disabler_; #endif 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 f763c13dca689..045e7d9dcff9e 100644 --- a/shell/browser/ui/electron_desktop_window_tree_host_linux.cc +++ b/shell/browser/ui/electron_desktop_window_tree_host_linux.cc @@ -10,7 +10,9 @@ #include +#include "base/feature_list.h" #include "base/i18n/rtl.h" +#include "shell/browser/native_window_features.h" #include "shell/browser/ui/views/client_frame_view_linux.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/skia_conversions.h" @@ -20,6 +22,14 @@ #include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h" #include "ui/views/window/non_client_view.h" +#if defined(USE_OZONE) +#include "ui/ozone/buildflags.h" +#if BUILDFLAG(OZONE_PLATFORM_X11) +#define USE_OZONE_PLATFORM_X11 +#endif +#include "ui/ozone/public/ozone_platform.h" +#endif + namespace electron { ElectronDesktopWindowTreeHostLinux::ElectronDesktopWindowTreeHostLinux( @@ -46,6 +56,18 @@ void ElectronDesktopWindowTreeHostLinux::OnBoundsChanged( const BoundsChange& change) { views::DesktopWindowTreeHostLinux::OnBoundsChanged(change); UpdateFrameHints(); + +#if defined(USE_OZONE_PLATFORM_X11) + if (ui::OzonePlatform::GetInstance() + ->GetPlatformProperties() + .electron_can_call_x11) { + // The OnWindowStateChanged should receive all updates but currently under + // X11 it doesn't receive changes to the fullscreen status because chromium + // is handling the fullscreen state changes synchronously, see + // X11Window::ToggleFullscreen in ui/ozone/platform/x11/x11_window.cc. + UpdateWindowState(platform_window()->GetPlatformWindowState()); + } +#endif } void ElectronDesktopWindowTreeHostLinux::OnWindowStateChanged( @@ -53,6 +75,43 @@ void ElectronDesktopWindowTreeHostLinux::OnWindowStateChanged( ui::PlatformWindowState new_state) { views::DesktopWindowTreeHostLinux::OnWindowStateChanged(old_state, new_state); UpdateFrameHints(); + UpdateWindowState(new_state); +} + +void ElectronDesktopWindowTreeHostLinux::UpdateWindowState( + ui::PlatformWindowState new_state) { + if (window_state_ == new_state) + return; + + switch (window_state_) { + case ui::PlatformWindowState::kMinimized: + native_window_view_->NotifyWindowRestore(); + break; + case ui::PlatformWindowState::kMaximized: + native_window_view_->NotifyWindowUnmaximize(); + break; + case ui::PlatformWindowState::kFullScreen: + native_window_view_->NotifyWindowLeaveFullScreen(); + break; + case ui::PlatformWindowState::kUnknown: + case ui::PlatformWindowState::kNormal: + break; + } + switch (new_state) { + case ui::PlatformWindowState::kMinimized: + native_window_view_->NotifyWindowMinimize(); + break; + case ui::PlatformWindowState::kMaximized: + native_window_view_->NotifyWindowMaximize(); + break; + case ui::PlatformWindowState::kFullScreen: + native_window_view_->NotifyWindowEnterFullScreen(); + break; + case ui::PlatformWindowState::kUnknown: + case ui::PlatformWindowState::kNormal: + break; + } + window_state_ = new_state; } void ElectronDesktopWindowTreeHostLinux::OnNativeThemeUpdated( @@ -65,13 +124,15 @@ void ElectronDesktopWindowTreeHostLinux::OnDeviceScaleFactorChanged() { } void ElectronDesktopWindowTreeHostLinux::UpdateFrameHints() { - if (SupportsClientFrameShadow() && native_window_view_->has_frame() && - native_window_view_->has_client_frame()) { - UpdateClientDecorationHints(static_cast( - native_window_view_->widget()->non_client_view()->frame_view())); - } + if (base::FeatureList::IsEnabled(features::kWaylandWindowDecorations)) { + if (SupportsClientFrameShadow() && native_window_view_->has_frame() && + native_window_view_->has_client_frame()) { + UpdateClientDecorationHints(static_cast( + native_window_view_->widget()->non_client_view()->frame_view())); + } - SizeConstraintsChanged(); + SizeConstraintsChanged(); + } } void ElectronDesktopWindowTreeHostLinux::UpdateClientDecorationHints( diff --git a/shell/browser/ui/electron_desktop_window_tree_host_linux.h b/shell/browser/ui/electron_desktop_window_tree_host_linux.h index bbf5782dcb38a..4560af4f41df7 100644 --- a/shell/browser/ui/electron_desktop_window_tree_host_linux.h +++ b/shell/browser/ui/electron_desktop_window_tree_host_linux.h @@ -13,6 +13,7 @@ #include "shell/browser/native_window_views.h" #include "shell/browser/ui/views/client_frame_view_linux.h" #include "ui/native_theme/native_theme_observer.h" +#include "ui/platform_window/platform_window.h" #include "ui/views/linux_ui/device_scale_factor_observer.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h" @@ -54,6 +55,7 @@ class ElectronDesktopWindowTreeHostLinux private: void UpdateFrameHints(); void UpdateClientDecorationHints(ClientFrameViewLinux* view); + void UpdateWindowState(ui::PlatformWindowState new_state); NativeWindowViews* native_window_view_; // weak ref @@ -64,6 +66,7 @@ class ElectronDesktopWindowTreeHostLinux &views::LinuxUI::AddDeviceScaleFactorObserver, &views::LinuxUI::RemoveDeviceScaleFactorObserver> scale_observation_{this}; + ui::PlatformWindowState window_state_ = ui::PlatformWindowState::kUnknown; }; } // namespace electron diff --git a/shell/browser/ui/file_dialog_gtk.cc b/shell/browser/ui/file_dialog_gtk.cc index 6f2141ada00fe..440c06823cea3 100644 --- a/shell/browser/ui/file_dialog_gtk.cc +++ b/shell/browser/ui/file_dialog_gtk.cc @@ -18,16 +18,9 @@ #include "shell/browser/unresponsive_suppressor.h" #include "shell/common/gin_converters/file_path_converter.h" #include "ui/base/glib/glib_signal.h" +#include "ui/gtk/gtk_ui.h" #include "ui/gtk/gtk_util.h" -#if defined(USE_X11) -#include "ui/events/platform/x11/x11_event_source.h" -#endif - -#if defined(USE_OZONE) || defined(USE_X11) -#include "ui/base/ui_base_features.h" -#endif - namespace file_dialog { static GModule* gtk_module; @@ -247,14 +240,7 @@ class FileChooserDialog { dl_gtk_native_dialog_show(static_cast(dialog_)); } else { gtk_widget_show_all(GTK_WIDGET(dialog_)); - -#if defined(USE_X11) - // We need to call gtk_window_present after making the widgets visible - // to make sure window gets correctly raised and gets focus. - x11::Time time = ui::X11EventSource::GetInstance()->GetTimestamp(); - gtk_window_present_with_time(GTK_WINDOW(dialog_), - static_cast(time)); -#endif + gtk::GtkUi::GetPlatform()->ShowGtkWindow(GTK_WINDOW(dialog_)); } } diff --git a/shell/browser/ui/gtk/menu_util.cc b/shell/browser/ui/gtk/menu_util.cc index 08f2a5544b8e3..fb1c0e63e91ac 100644 --- a/shell/browser/ui/gtk/menu_util.cc +++ b/shell/browser/ui/gtk/menu_util.cc @@ -22,8 +22,12 @@ #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_code_conversion_x.h" -#if defined(USE_OZONE) || defined(USE_X11) -#include "ui/base/ui_base_features.h" +#if defined(USE_OZONE) +#include "ui/ozone/buildflags.h" +#if BUILDFLAG(OZONE_PLATFORM_X11) +#define USE_OZONE_PLATFORM_X11 +#endif +#include "ui/ozone/public/ozone_platform.h" #endif namespace electron { @@ -45,6 +49,8 @@ int EventFlagsFromGdkState(guint state) { return flags; } +#if defined(USE_OZONE_PLATFORM_X11) + guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator) { // The second parameter is false because accelerator keys are expressed in // terms of the non-shift-modified key. @@ -64,6 +70,8 @@ GdkModifierType GetGdkModifierForAccelerator( return static_cast(modifier); } +#endif + } // namespace GtkWidget* BuildMenuItemWithImage(const std::string& label, GtkWidget* image) { @@ -225,13 +233,17 @@ void BuildSubmenuFromModel(ui::MenuModel* model, connect_to_activate = false; } -#if defined(USE_X11) - ui::Accelerator accelerator; - if (model->GetAcceleratorAt(i, &accelerator)) { - gtk_widget_add_accelerator(menu_item, "activate", nullptr, - GetGdkKeyCodeForAccelerator(accelerator), - GetGdkModifierForAccelerator(accelerator), - GTK_ACCEL_VISIBLE); +#if defined(USE_OZONE_PLATFORM_X11) + if (ui::OzonePlatform::GetInstance() + ->GetPlatformProperties() + .electron_can_call_x11) { + ui::Accelerator accelerator; + if (model->GetAcceleratorAt(i, &accelerator)) { + gtk_widget_add_accelerator(menu_item, "activate", nullptr, + GetGdkKeyCodeForAccelerator(accelerator), + GetGdkModifierForAccelerator(accelerator), + GTK_ACCEL_VISIBLE); + } } #endif diff --git a/shell/browser/ui/message_box_gtk.cc b/shell/browser/ui/message_box_gtk.cc index 6945214920d12..28b332d6f8adf 100644 --- a/shell/browser/ui/message_box_gtk.cc +++ b/shell/browser/ui/message_box_gtk.cc @@ -18,13 +18,10 @@ #include "shell/browser/unresponsive_suppressor.h" #include "ui/base/glib/glib_signal.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gtk/gtk_ui.h" #include "ui/gtk/gtk_util.h" -#if defined(USE_X11) -#include "ui/events/platform/x11/x11_event_source.h" -#endif - -#if defined(USE_OZONE) || defined(USE_X11) +#if defined(USE_OZONE) #include "ui/base/ui_base_features.h" #endif @@ -161,14 +158,7 @@ class GtkMessageBox : public NativeWindowObserver { void Show() { gtk_widget_show(dialog_); - -#if defined(USE_X11) - // We need to call gtk_window_present after making the widgets visible to - // make sure window gets correctly raised and gets focus. - x11::Time time = ui::X11EventSource::GetInstance()->GetTimestamp(); - gtk_window_present_with_time(GTK_WINDOW(dialog_), - static_cast(time)); -#endif + gtk::GtkUi::GetPlatform()->ShowGtkWindow(GTK_WINDOW(dialog_)); } int RunSynchronous() { diff --git a/shell/browser/ui/x/window_state_watcher.cc b/shell/browser/ui/x/window_state_watcher.cc deleted file mode 100644 index 42e553b45e0cb..0000000000000 --- a/shell/browser/ui/x/window_state_watcher.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "shell/browser/ui/x/window_state_watcher.h" - -#include - -#include "ui/base/x/x11_util.h" -#include "ui/gfx/x/x11_atom_cache.h" -#include "ui/gfx/x/xproto_util.h" - -namespace electron { - -WindowStateWatcher::WindowStateWatcher(NativeWindowViews* window) - : window_(window), - widget_(window->GetAcceleratedWidget()), - net_wm_state_atom_(x11::GetAtom("_NET_WM_STATE")), - net_wm_state_hidden_atom_(x11::GetAtom("_NET_WM_STATE_HIDDEN")), - net_wm_state_maximized_vert_atom_( - x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")), - net_wm_state_maximized_horz_atom_( - x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")), - net_wm_state_fullscreen_atom_(x11::GetAtom("_NET_WM_STATE_FULLSCREEN")), - was_minimized_(window_->IsMinimized()), - was_maximized_(window_->IsMaximized()) { - ui::X11EventSource::GetInstance()->connection()->AddEventObserver(this); -} - -WindowStateWatcher::~WindowStateWatcher() { - ui::X11EventSource::GetInstance()->connection()->RemoveEventObserver(this); -} - -void WindowStateWatcher::OnEvent(const x11::Event& x11_event) { - if (IsWindowStateEvent(x11_event)) { - std::vector wm_states; - if (GetArrayProperty( - static_cast(window_->GetAcceleratedWidget()), - net_wm_state_atom_, &wm_states)) { - const auto props = - base::flat_set(std::begin(wm_states), std::end(wm_states)); - const bool is_minimized = props.contains(net_wm_state_hidden_atom_); - const bool is_maximized = - props.contains(net_wm_state_maximized_vert_atom_) && - props.contains(net_wm_state_maximized_horz_atom_); - const bool is_fullscreen = props.contains(net_wm_state_fullscreen_atom_); - - if (is_minimized != was_minimized_) { - if (is_minimized) - window_->NotifyWindowMinimize(); - else - window_->NotifyWindowRestore(); - } else if (is_maximized != was_maximized_) { - if (is_maximized) - window_->NotifyWindowMaximize(); - else - window_->NotifyWindowUnmaximize(); - } else { - // If this is neither a "maximize" or "minimize" event, then we think it - // is a "fullscreen" event. - // The "IsFullscreen()" becomes true immediately before "OnEvent" - // is called, so we can not handle this like "maximize" and "minimize" - // by watching whether they have changed. - if (is_fullscreen) - window_->NotifyWindowEnterFullScreen(); - else - window_->NotifyWindowLeaveFullScreen(); - } - - was_minimized_ = is_minimized; - was_maximized_ = is_maximized; - } - } -} - -bool WindowStateWatcher::IsWindowStateEvent(const x11::Event& x11_event) const { - auto* property = x11_event.As(); - return (property && property->atom == net_wm_state_atom_ && - static_cast(property->window) == widget_); -} - -} // namespace electron diff --git a/shell/browser/ui/x/window_state_watcher.h b/shell/browser/ui/x/window_state_watcher.h deleted file mode 100644 index 81b1117579c84..0000000000000 --- a/shell/browser/ui/x/window_state_watcher.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ELECTRON_SHELL_BROWSER_UI_X_WINDOW_STATE_WATCHER_H_ -#define ELECTRON_SHELL_BROWSER_UI_X_WINDOW_STATE_WATCHER_H_ - -#include "ui/events/platform/x11/x11_event_source.h" -#include "ui/gfx/x/event.h" - -#include "shell/browser/native_window_views.h" - -namespace electron { - -class WindowStateWatcher : public x11::EventObserver { - public: - explicit WindowStateWatcher(NativeWindowViews* window); - ~WindowStateWatcher() override; - - // disable copy - WindowStateWatcher(const WindowStateWatcher&) = delete; - WindowStateWatcher& operator=(const WindowStateWatcher&) = delete; - - protected: - // x11::EventObserver: - void OnEvent(const x11::Event& x11_event) override; - - private: - bool IsWindowStateEvent(const x11::Event& x11_event) const; - - NativeWindowViews* window_; - gfx::AcceleratedWidget widget_; - const x11::Atom net_wm_state_atom_; - const x11::Atom net_wm_state_hidden_atom_; - const x11::Atom net_wm_state_maximized_vert_atom_; - const x11::Atom net_wm_state_maximized_horz_atom_; - const x11::Atom net_wm_state_fullscreen_atom_; - - bool was_minimized_ = false; - bool was_maximized_ = false; -}; - -} // namespace electron - -#endif // ELECTRON_SHELL_BROWSER_UI_X_WINDOW_STATE_WATCHER_H_