fix: calling of X11 functions when running under Wayland (#33355)
* fix: don't call X11 functions in file dialog and message box * refactor: remove unused GtkUiPlatform declaration * fix: set gtk darktheme only when running under X11 * fix: replace X11 window state watcher with implementation using ozone * fix: make sure global menu barr is used only when supported * fix: don't call X11 function in native window views under wayland * style: fix lint issues * fix: use GtkUiPlatform::ShowGtkWindow instead of gtk_window_present directly * refactor: extract CreateGlobalMenuBar into separate function * refactor: move checking for WaylandWindowDecorations inside class * fix: check if we run under X11 only in ozone build * refactor: drop including unused ui/base/ui_base_features.h header * fix: modify ui_gtk_public_header.patch to also export gtk_ui.h * fix: refactor guarding of X11 calls - Introduce patch exposing new electron_can_call_x11 property - Replace defined(USE_OZONE) with BUILDFLAG(OZONE_PLATFORM_X11) flags * fix: remove the last remaining usage of USE_X11 * fix: usage of BUILDFLAG(OZONE_PLATFORM_X11) not building on non ozone * fix: call UpdateWindowState from OnBoundsChanged only under X11
This commit is contained in:
parent
1153a5ce5a
commit
cdf2b3f4e4
16 changed files with 305 additions and 309 deletions
|
@ -10,7 +10,9 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#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<ClientFrameViewLinux*>(
|
||||
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<ClientFrameViewLinux*>(
|
||||
native_window_view_->widget()->non_client_view()->frame_view()));
|
||||
}
|
||||
|
||||
SizeConstraintsChanged();
|
||||
SizeConstraintsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ElectronDesktopWindowTreeHostLinux::UpdateClientDecorationHints(
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "shell/browser/ui/views/client_frame_view_linux.h"
|
||||
#include "third_party/skia/include/core/SkRRect.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"
|
||||
|
||||
|
@ -55,6 +56,7 @@ class ElectronDesktopWindowTreeHostLinux
|
|||
private:
|
||||
void UpdateFrameHints();
|
||||
void UpdateClientDecorationHints(ClientFrameViewLinux* view);
|
||||
void UpdateWindowState(ui::PlatformWindowState new_state);
|
||||
|
||||
NativeWindowViews* native_window_view_; // weak ref
|
||||
|
||||
|
@ -65,6 +67,7 @@ class ElectronDesktopWindowTreeHostLinux
|
|||
&views::LinuxUI::AddDeviceScaleFactorObserver,
|
||||
&views::LinuxUI::RemoveDeviceScaleFactorObserver>
|
||||
scale_observation_{this};
|
||||
ui::PlatformWindowState window_state_ = ui::PlatformWindowState::kUnknown;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
|
|
@ -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<void*>(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<uint32_t>(time));
|
||||
#endif
|
||||
gtk::GtkUi::GetPlatform()->ShowGtkWindow(GTK_WINDOW(dialog_));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<GdkModifierType>(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
|
||||
|
||||
|
|
|
@ -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<uint32_t>(time));
|
||||
#endif
|
||||
gtk::GtkUi::GetPlatform()->ShowGtkWindow(GTK_WINDOW(dialog_));
|
||||
}
|
||||
|
||||
int RunSynchronous() {
|
||||
|
|
|
@ -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 <vector>
|
||||
|
||||
#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<x11::Atom> wm_states;
|
||||
if (GetArrayProperty(
|
||||
static_cast<x11::Window>(window_->GetAcceleratedWidget()),
|
||||
net_wm_state_atom_, &wm_states)) {
|
||||
const auto props =
|
||||
base::flat_set<x11::Atom>(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<x11::PropertyNotifyEvent>();
|
||||
return (property && property->atom == net_wm_state_atom_ &&
|
||||
static_cast<uint32_t>(property->window) == widget_);
|
||||
}
|
||||
|
||||
} // namespace electron
|
|
@ -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_
|
Loading…
Add table
Add a link
Reference in a new issue