Repository: electron/electron
Pull request: fix: make toplevel icon Wayland protocol work

#### Description of Change

Fixes https://github.com/electron/electron/issues/49285

When an Electron window gets hidden (no icon on taskbar) on Wayland, the icon for toplevel-icon protocol doesn't exist anymore. Override the `DesktopWindowTreeHostLinux::SetWindowIcons` and `DesktopWindowTreeHostLinux::Show` methods to save and use the icon.

---

Before PR

<img width="1171" height="907" alt="17676350283315396058002198480807" src="https://github.com/user-attachments/assets/7c1ecb6b-38e5-4cc3-a14c-721981b01668" />

---

After PR

<img width="1167" height="901" alt="1767635063050740171516800877481" src="https://github.com/user-attachments/assets/c68f9cc5-bcda-48b1-aeca-216dedc8846c" />

<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Make toplevel icon Wayland protocol work.


Changed files:
filename: shell/browser/ui/electron_desktop_window_tree_host_linux.cc
patch: @@ -25,6 +25,7 @@
 #include "ui/gfx/geometry/skia_conversions.h"
 #include "ui/linux/linux_ui.h"
 #include "ui/ozone/public/ozone_platform.h"
+#include "ui/platform_window/extensions/wayland_extension.h"
 #include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
@@ -58,6 +59,24 @@ bool ElectronDesktopWindowTreeHostLinux::IsShowingFrame() const {
          !native_window_view_->IsMinimized();
 }
 
+void ElectronDesktopWindowTreeHostLinux::SetWindowIcons(
+    const gfx::ImageSkia& window_icon,
+    const gfx::ImageSkia& app_icon) {
+  DesktopWindowTreeHostLinux::SetWindowIcons(window_icon, app_icon);
+
+  if (ui::GetWaylandToplevelExtension(*platform_window()))
+    saved_window_icon_ = window_icon;
+}
+
+void ElectronDesktopWindowTreeHostLinux::Show(
+    ui::mojom::WindowShowState show_state,
+    const gfx::Rect& restore_bounds) {
+  DesktopWindowTreeHostLinux::Show(show_state, restore_bounds);
+
+  if (!saved_window_icon_.isNull())
+    DesktopWindowTreeHostLinux::SetWindowIcons(saved_window_icon_, {});
+}
+
 gfx::Insets ElectronDesktopWindowTreeHostLinux::CalculateInsetsInDIP(
     ui::PlatformWindowState window_state) const {
   // If we are not showing frame, the insets should be zero.

filename: shell/browser/ui/electron_desktop_window_tree_host_linux.h
patch: @@ -11,6 +11,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/scoped_observation.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/linux/device_scale_factor_observer.h"
 #include "ui/linux/linux_ui.h"
 #include "ui/native_theme/native_theme_observer.h"
@@ -44,6 +45,10 @@ class ElectronDesktopWindowTreeHostLinux
  protected:
   // views::DesktopWindowTreeHostLinuxImpl:
   void OnWidgetInitDone() override;
+  void SetWindowIcons(const gfx::ImageSkia& window_icon,
+                      const gfx::ImageSkia& app_icon) override;
+  void Show(ui::mojom::WindowShowState show_state,
+            const gfx::Rect& restore_bounds) override;
 
   // ui::PlatformWindowDelegate
   gfx::Insets CalculateInsetsInDIP(
@@ -71,6 +76,8 @@ class ElectronDesktopWindowTreeHostLinux
 
   bool IsShowingFrame() const;
 
+  gfx::ImageSkia saved_window_icon_;
+
   raw_ptr<NativeWindowViews> native_window_view_;  // weak ref
 
   base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>