Browse Source

fix: Wayland general CSD fixes (#34955)

* fix: broken wayland window decorations due to botched chromium update

The `GetTitlebarBounds().height()` is obviously intended to be placed in
the `top` parameter, which used to be the second one before upstream
removed multi-parameter `gfx::Rect::Inset`, but it's the first parameter
for `gfx::Insets::TLBR`, which was intended to replace the removed
`Inset` function. However, whoever updated Chromium kept the parameter
unchanged, causing the title bar height to be passed to the `left`
parameter, causing the window title bar to be unclickable.

* fix: wayland window top bar buttons unclickable

Use NonClientFrameView::TargetForRect for the ClientFrameViewLinux
implementation because the default inherited from FramelessView blocks
any non-HTCLIENT events.

* fix: add maximized parameter to LinuxUI::GetWindowFrameProvider

* fix: pass frame_->IsMaximized() to GetWindowFrameProvider

This ensures that the toolkit renders the window decorations in maximized mode
while the window is maximized to ensure that there is no empty space around the window.
msizanoen1 2 years ago
parent
commit
7b8fb2b074

+ 1 - 0
patches/chromium/.patches

@@ -114,3 +114,4 @@ disable_freezing_flags_after_init_in_node.patch
 short-circuit_permissions_checks_in_mediastreamdevicescontroller.patch
 chore_add_electron_deps_to_gitignores.patch
 chore_allow_chromium_to_handle_synthetic_mouse_events_for_touch.patch
+add_maximized_parameter_to_linuxui_getwindowframeprovider.patch

+ 176 - 0
patches/chromium/add_maximized_parameter_to_linuxui_getwindowframeprovider.patch

@@ -0,0 +1,176 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: msizanoen1 <[email protected]>
+Date: Tue, 19 Jul 2022 05:11:06 +0200
+Subject: Add maximized parameter to LinuxUI::GetWindowFrameProvider
+
+This allows ClientFrameViewLinux to instruct the toolkit to draw the window
+decorations in maximized mode where needed, preventing empty space caused
+by decoration shadows and rounded titlebars around the window while maximized.
+
+diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc
+index 50c01fb42bc1a7350fae4773f1b549355c6cdc25..ab49a67e3b20cd240f532cfbf868533bb1f293d8 100644
+--- a/ui/gtk/gtk_ui.cc
++++ b/ui/gtk/gtk_ui.cc
+@@ -511,13 +511,15 @@ std::unique_ptr<ui::NavButtonProvider> GtkUi::CreateNavButtonProvider() {
+   return nullptr;
+ }
+ 
+-ui::WindowFrameProvider* GtkUi::GetWindowFrameProvider(bool solid_frame) {
++ui::WindowFrameProvider* GtkUi::GetWindowFrameProvider(bool solid_frame, bool maximized) {
+   if (!GtkCheckVersion(3, 14))
+     return nullptr;
+   auto& provider =
+-      solid_frame ? solid_frame_provider_ : transparent_frame_provider_;
++      maximized
++        ? (solid_frame ? solid_maximized_frame_provider_ : transparent_maximized_frame_provider_)
++        : (solid_frame ? solid_frame_provider_ : transparent_frame_provider_);
+   if (!provider)
+-    provider = std::make_unique<gtk::WindowFrameProviderGtk>(solid_frame);
++    provider = std::make_unique<gtk::WindowFrameProviderGtk>(solid_frame, maximized);
+   return provider.get();
+ }
+ 
+diff --git a/ui/gtk/gtk_ui.h b/ui/gtk/gtk_ui.h
+index 5206acf475346f50e0f31b7432d9b93afc3a8ad0..9f2b3cca2337b4528f9451c2fdec7c67021c949f 100644
+--- a/ui/gtk/gtk_ui.h
++++ b/ui/gtk/gtk_ui.h
+@@ -93,7 +93,7 @@ class GtkUi : public ui::LinuxUi {
+   bool PreferDarkTheme() const override;
+   bool AnimationsEnabled() const override;
+   std::unique_ptr<ui::NavButtonProvider> CreateNavButtonProvider() override;
+-  ui::WindowFrameProvider* GetWindowFrameProvider(bool solid_frame) override;
++  ui::WindowFrameProvider* GetWindowFrameProvider(bool solid_frame, bool maximized) override;
+   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
+   std::string GetCursorThemeName() override;
+   int GetCursorThemeSize() override;
+@@ -197,6 +197,8 @@ class GtkUi : public ui::LinuxUi {
+   // while Chrome is running.
+   std::unique_ptr<ui::WindowFrameProvider> solid_frame_provider_;
+   std::unique_ptr<ui::WindowFrameProvider> transparent_frame_provider_;
++  std::unique_ptr<ui::WindowFrameProvider> solid_maximized_frame_provider_;
++  std::unique_ptr<ui::WindowFrameProvider> transparent_maximized_frame_provider_;
+ };
+ 
+ }  // namespace gtk
+diff --git a/ui/gtk/window_frame_provider_gtk.cc b/ui/gtk/window_frame_provider_gtk.cc
+index e4dbdad327eb77994ffd7f068c67336a19897915..d3ae0636455489a7c7443df85cb769952c98aca2 100644
+--- a/ui/gtk/window_frame_provider_gtk.cc
++++ b/ui/gtk/window_frame_provider_gtk.cc
+@@ -38,16 +38,18 @@ std::string GetThemeName() {
+   return theme_string;
+ }
+ 
+-GtkCssContext WindowContext(bool solid_frame, bool focused) {
++GtkCssContext WindowContext(bool solid_frame, bool maximized, bool focused) {
+   std::string selector = "#window.background.";
+   selector += solid_frame ? "solid-csd" : "csd";
++  if (maximized)
++    selector += ".maximized";
+   if (!focused)
+     selector += ":inactive";
+   return AppendCssNodeToStyleContext({}, selector);
+ }
+ 
+-GtkCssContext DecorationContext(bool solid_frame, bool focused) {
+-  auto context = WindowContext(solid_frame, focused);
++GtkCssContext DecorationContext(bool solid_frame, bool maximized, bool focused) {
++  auto context = WindowContext(solid_frame, maximized, focused);
+   // GTK4 renders the decoration directly on the window.
+   if (!GtkCheckVersion(4))
+     context = AppendCssNodeToStyleContext(context, "#decoration");
+@@ -64,8 +66,8 @@ GtkCssContext DecorationContext(bool solid_frame, bool focused) {
+   return context;
+ }
+ 
+-GtkCssContext HeaderContext(bool solid_frame, bool focused) {
+-  auto context = WindowContext(solid_frame, focused);
++GtkCssContext HeaderContext(bool solid_frame, bool maximized, bool focused) {
++  auto context = WindowContext(solid_frame, maximized, focused);
+   context =
+       AppendCssNodeToStyleContext(context, "#headerbar.header-bar.titlebar");
+   if (!focused)
+@@ -110,8 +112,8 @@ int ComputeTopCornerRadius() {
+   // need to experimentally determine the corner radius by rendering a sample.
+   // Additionally, in GTK4, the headerbar corners get clipped by the window
+   // rather than the headerbar having its own rounded corners.
+-  auto context = GtkCheckVersion(4) ? DecorationContext(false, false)
+-                                    : HeaderContext(false, false);
++  auto context = GtkCheckVersion(4) ? DecorationContext(false, false, false)
++                                    : HeaderContext(false, false, false);
+   ApplyCssToContext(context, R"(window, headerbar {
+     background-image: none;
+     background-color: black;
+@@ -169,8 +171,8 @@ void WindowFrameProviderGtk::Asset::CloneFrom(
+   unfocused_bitmap = src.unfocused_bitmap;
+ }
+ 
+-WindowFrameProviderGtk::WindowFrameProviderGtk(bool solid_frame)
+-    : solid_frame_(solid_frame) {}
++WindowFrameProviderGtk::WindowFrameProviderGtk(bool solid_frame, bool maximized)
++    : solid_frame_(solid_frame), maximized_(maximized) {}
+ 
+ WindowFrameProviderGtk::~WindowFrameProviderGtk() = default;
+ 
+@@ -264,7 +266,7 @@ void WindowFrameProviderGtk::PaintWindowFrame(gfx::Canvas* canvas,
+       top_area_height_dip * scale - asset.frame_thickness_px.top();
+ 
+   auto header = PaintHeaderbar({client_bounds_px.width(), top_area_height_px},
+-                               HeaderContext(solid_frame_, focused), scale);
++                               HeaderContext(solid_frame_, maximized_, focused), scale);
+   image = gfx::ImageSkia::CreateFrom1xBitmap(header);
+   // In GTK4, the headerbar gets clipped by the window.
+   if (GtkCheckVersion(4)) {
+@@ -296,7 +298,7 @@ void WindowFrameProviderGtk::MaybeUpdateBitmaps(float scale) {
+ 
+   gfx::Rect frame_bounds_dip(kMaxFrameSizeDip, kMaxFrameSizeDip,
+                              2 * kMaxFrameSizeDip, 2 * kMaxFrameSizeDip);
+-  auto focused_context = DecorationContext(solid_frame_, true);
++  auto focused_context = DecorationContext(solid_frame_, maximized_, true);
+   frame_bounds_dip.Inset(-GtkStyleContextGetPadding(focused_context));
+   frame_bounds_dip.Inset(-GtkStyleContextGetBorder(focused_context));
+   gfx::Size bitmap_size(BitmapSizePx(asset), BitmapSizePx(asset));
+@@ -304,7 +306,7 @@ void WindowFrameProviderGtk::MaybeUpdateBitmaps(float scale) {
+       PaintBitmap(bitmap_size, frame_bounds_dip, focused_context, scale);
+   asset.unfocused_bitmap =
+       PaintBitmap(bitmap_size, frame_bounds_dip,
+-                  DecorationContext(solid_frame_, false), scale);
++                  DecorationContext(solid_frame_, maximized_, false), scale);
+ 
+   // In GTK4, there's no way to obtain the frame thickness from CSS values
+   // directly, so we must determine it experimentally based on the drawn
+diff --git a/ui/gtk/window_frame_provider_gtk.h b/ui/gtk/window_frame_provider_gtk.h
+index da0f7c33a260f8d98a73c126def30944589001df..a2999a6dcea30a9e468f974301b3a4f03dcb8aeb 100644
+--- a/ui/gtk/window_frame_provider_gtk.h
++++ b/ui/gtk/window_frame_provider_gtk.h
+@@ -14,7 +14,7 @@ namespace gtk {
+ 
+ class WindowFrameProviderGtk : public ui::WindowFrameProvider {
+  public:
+-  explicit WindowFrameProviderGtk(bool solid_frame);
++  explicit WindowFrameProviderGtk(bool solid_frame, bool maximized);
+ 
+   WindowFrameProviderGtk(const WindowFrameProviderGtk&) = delete;
+   WindowFrameProviderGtk& operator=(const WindowFrameProviderGtk&) = delete;
+@@ -69,6 +69,9 @@ class WindowFrameProviderGtk : public ui::WindowFrameProvider {
+ 
+   // Cached bitmaps and metrics.  The scale is rounded to percent.
+   base::flat_map<int, Asset> assets_;
++
++  // Whether to draw the window decorations as maximized.
++  bool maximized_;
+ };
+ 
+ }  // namespace gtk
+diff --git a/ui/linux/linux_ui.h b/ui/linux/linux_ui.h
+index 0cd8a0e101de186e11ead65526c7f0abc60c6577..7db580ce04a407877ca4108ec087120cdb9ce2ad 100644
+--- a/ui/linux/linux_ui.h
++++ b/ui/linux/linux_ui.h
+@@ -176,7 +176,7 @@ class COMPONENT_EXPORT(LINUX_UI) LinuxUi
+   // if transparency is unsupported and the frame should be rendered opaque.
+   // The returned object is not owned by the caller and will remain alive until
+   // the process ends.
+-  virtual WindowFrameProvider* GetWindowFrameProvider(bool solid_frame) = 0;
++  virtual WindowFrameProvider* GetWindowFrameProvider(bool solid_frame, bool maximized) = 0;
+ 
+   // Returns a map of KeyboardEvent code to KeyboardEvent key values.
+   virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0;

+ 10 - 2
shell/browser/ui/views/client_frame_view_linux.cc

@@ -131,7 +131,7 @@ void ClientFrameViewLinux::Init(NativeWindowViews* window,
   host_supports_client_frame_shadow_ = tree_host->SupportsClientFrameShadow();
 
   frame_provider_ = ui::LinuxUi::instance()->GetWindowFrameProvider(
-      !host_supports_client_frame_shadow_);
+      !host_supports_client_frame_shadow_, frame_->IsMaximized());
 
   UpdateWindowTitle();
 
@@ -202,7 +202,7 @@ gfx::Rect ClientFrameViewLinux::GetBoundsForClientView() const {
   if (!frame_->IsFullscreen()) {
     client_bounds.Inset(GetBorderDecorationInsets());
     client_bounds.Inset(
-        gfx::Insets::TLBR(0, GetTitlebarBounds().height(), 0, 0));
+        gfx::Insets::TLBR(GetTitlebarBounds().height(), 0, 0, 0));
   }
   return client_bounds;
 }
@@ -274,6 +274,9 @@ void ClientFrameViewLinux::Layout() {
     return;
   }
 
+  frame_provider_ = ui::LinuxUi::instance()->GetWindowFrameProvider(
+      !host_supports_client_frame_shadow_, frame_->IsMaximized());
+
   UpdateButtonImages();
   LayoutButtons();
 
@@ -485,4 +488,9 @@ gfx::Size ClientFrameViewLinux::SizeWithDecorations(gfx::Size size) const {
   return size;
 }
 
+views::View* ClientFrameViewLinux::TargetForRect(views::View* root,
+                                                 const gfx::Rect& rect) {
+  return views::NonClientFrameView::TargetForRect(root, rect);
+}
+
 }  // namespace electron

+ 3 - 0
shell/browser/ui/views/client_frame_view_linux.h

@@ -67,6 +67,9 @@ class ClientFrameViewLinux : public FramelessView,
   void OnPaint(gfx::Canvas* canvas) override;
   const char* GetClassName() const override;
 
+  // Overriden from views::ViewTargeterDelegate
+  views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override;
+
  private:
   static constexpr int kNavButtonCount = 4;