Repository: electron/electron (language: cpp)

Issue:
Drag and Drop not showing icon when leaving electron window
### Preflight Checklist

- [x] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [x] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [x] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

34.0.1

### What operating system(s) are you using?

Windows

### Operating System Version

Windows 10 19045.5371

### What arch are you using?

x64

### Last Known Working Electron version

33.3.0

### Expected Behavior

When using the drag and drop code provided in the example section, the icon is shown when dragging out of the electron window

### Actual Behavior

It looks like this 

![Image](https://github.com/user-attachments/assets/b293933c-5d5a-4180-879b-792a992ef432)

### Testcase Gist URL

https://gist.github.com/IslandRhythms/da503bd1d495f0aa1252e7360b6340f9

### Additional Information

_No response_


Discussion / hints:
Great found. 
It is introduced by a change in the upstream. Will consider how to fix it.
Bisected this to having been introduced in v34.0.0-beta.9 / v35.0.0-nightly.20241120
yes. it's introduced in Chromium 132.0.6834.32
> yes. it's introduced in Chromium 132.0.6834.32

It was introduced in the jump to 132.0.6834.32, but that's just the latest possible version it could have been introduced in. I've bisected it back to being introduced in 132.0.6834.17, and specifically https://chromium-review.googlesource.com/c/chromium/src/+/6039278.

It looks like that change also broke drag icons in upstream Chromium (specifically dragging a downloaded file) so I'll pursue an upstream fix for this issue.
Reported as an upstream issue: https://issues.chromium.org/issues/394380766

Fix patch:
diff --git a/patches/chromium/.patches b/patches/chromium/.patches
index 0abbd2861984e..8c08876b796a8 100644
--- a/patches/chromium/.patches
+++ b/patches/chromium/.patches
@@ -140,3 +140,4 @@ ignore_parse_errors_for_pkey_appusermodel_toastactivatorclsid.patch
 feat_add_signals_when_embedder_cleanup_callbacks_run_for.patch
 feat_separate_content_settings_callback_for_sync_and_async_clipboard.patch
 fix_win32_synchronous_spellcheck.patch
+fix_drag_and_drop_icons_on_windows.patch
diff --git a/patches/chromium/fix_drag_and_drop_icons_on_windows.patch b/patches/chromium/fix_drag_and_drop_icons_on_windows.patch
new file mode 100644
index 0000000000000..dd5b9697e7000
--- /dev/null
+++ b/patches/chromium/fix_drag_and_drop_icons_on_windows.patch
@@ -0,0 +1,162 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: David Sanders <dsanders11@ucsbalum.com>
+Date: Fri, 21 Feb 2025 00:46:48 -0800
+Subject: fix: drag and drop icons on Windows
+
+This is a backport from Chromium of
+https://chromium-review.googlesource.com/c/chromium/src/+/6279834
+
+Change-Id: Ic642228f3a0a073b9b45fbec68de37be6cfd3934
+
+diff --git a/chrome/browser/ui/views/tabs/tab_close_button.cc b/chrome/browser/ui/views/tabs/tab_close_button.cc
+index 281d6c6fcccbf3bfc3396056e495ee8d19424f5a..ac335a68f3fd0e3931cb37c915de51e410734850 100644
+--- a/chrome/browser/ui/views/tabs/tab_close_button.cc
++++ b/chrome/browser/ui/views/tabs/tab_close_button.cc
+@@ -18,7 +18,6 @@
+ #include "ui/base/l10n/l10n_util.h"
+ #include "ui/base/metadata/metadata_impl_macros.h"
+ #include "ui/base/pointer/touch_ui_controller.h"
+-#include "ui/compositor/layer.h"
+ #include "ui/gfx/canvas.h"
+ #include "ui/gfx/color_utils.h"
+ #include "ui/gfx/geometry/insets.h"
+@@ -63,8 +62,6 @@ TabCloseButton::TabCloseButton(PressedCallback pressed_callback,
+   views::InkDrop::Get(this)->GetInkDrop()->SetHoverHighlightFadeDuration(
+       base::TimeDelta());
+ 
+-  image_container_view()->DestroyLayer();
+-
+   // The ink drop highlight path is the same as the focus ring highlight path,
+   // but needs to be explicitly mirrored for RTL.
+   // TODO(http://crbug.com/1056490): Make ink drops in RTL work the same way as
+@@ -145,20 +142,6 @@ void TabCloseButton::OnGestureEvent(ui::GestureEvent* event) {
+   event->SetHandled();
+ }
+ 
+-void TabCloseButton::AddLayerToRegion(ui::Layer* new_layer,
+-                                      views::LayerRegion region) {
+-  image_container_view()->SetPaintToLayer();
+-  image_container_view()->layer()->SetFillsBoundsOpaquely(false);
+-  ink_drop_container()->SetVisible(true);
+-  ink_drop_container()->AddLayerToRegion(new_layer, region);
+-}
+-
+-void TabCloseButton::RemoveLayerFromRegions(ui::Layer* old_layer) {
+-  ink_drop_container()->RemoveLayerFromRegions(old_layer);
+-  ink_drop_container()->SetVisible(false);
+-  image_container_view()->DestroyLayer();
+-}
+-
+ gfx::Size TabCloseButton::CalculatePreferredSize(
+     const views::SizeBounds& available_size) const {
+   return kButtonSize;
+diff --git a/chrome/browser/ui/views/tabs/tab_close_button.h b/chrome/browser/ui/views/tabs/tab_close_button.h
+index f23bf862d987d8d6ba59aef781c51034e9a3debe..f688214ef883994d09b7a428b8af9b7f14c93af9 100644
+--- a/chrome/browser/ui/views/tabs/tab_close_button.h
++++ b/chrome/browser/ui/views/tabs/tab_close_button.h
+@@ -46,9 +46,6 @@ class TabCloseButton : public views::LabelButton,
+   void OnMouseReleased(const ui::MouseEvent& event) override;
+   void OnMouseMoved(const ui::MouseEvent& event) override;
+   void OnGestureEvent(ui::GestureEvent* event) override;
+-  void AddLayerToRegion(ui::Layer* new_layer,
+-                        views::LayerRegion region) override;
+-  void RemoveLayerFromRegions(ui::Layer* old_layer) override;
+ 
+  protected:
+   // Set/reset the image models for the icon with new colors.
+diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
+index 9dc31a69ab252c2f71061b01aad878930bb6e4d5..116ba2220f0148c9799948e170fe51e5c235008d 100644
+--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
++++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
+@@ -124,6 +124,13 @@ ToolbarButton::ToolbarButton(PressedCallback callback,
+ 
+   SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
+   views::FocusRing::Get(this)->SetOutsetFocusRingDisabled(true);
++
++#if BUILDFLAG(IS_WIN)
++  // Paint image(s) to a layer so that the canvas is snapped to pixel
++  // boundaries.
++  image_container_view()->SetPaintToLayer();
++  image_container_view()->layer()->SetFillsBoundsOpaquely(false);
++#endif
+ }
+ 
+ ToolbarButton::~ToolbarButton() = default;
+@@ -753,6 +760,24 @@ ToolbarButton::GetActionViewInterface() {
+   return std::make_unique<ToolbarButtonActionViewInterface>(this);
+ }
+ 
++void ToolbarButton::AddLayerToRegion(ui::Layer* new_layer,
++                                     views::LayerRegion region) {
++#if !BUILDFLAG(IS_WIN)
++  image_container_view()->SetPaintToLayer();
++  image_container_view()->layer()->SetFillsBoundsOpaquely(false);
++#endif
++  ink_drop_container()->SetVisible(true);
++  ink_drop_container()->AddLayerToRegion(new_layer, region);
++}
++
++void ToolbarButton::RemoveLayerFromRegions(ui::Layer* old_layer) {
++  ink_drop_container()->RemoveLayerFromRegions(old_layer);
++  ink_drop_container()->SetVisible(false);
++#if !BUILDFLAG(IS_WIN)
++  image_container_view()->DestroyLayer();
++#endif
++}
++
+ ToolbarButtonActionViewInterface::ToolbarButtonActionViewInterface(
+     ToolbarButton* action_view)
+     : views::LabelButtonActionViewInterface(action_view),
+diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
+index a6957be675eadd39707c0586ce79f7909cfbd675..4d9d985fe0a989555105b487a43669bbf025eb19 100644
+--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
++++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
+@@ -131,6 +131,9 @@ class ToolbarButton : public views::LabelButton,
+   void OnMouseExited(const ui::MouseEvent& event) override;
+   void OnGestureEvent(ui::GestureEvent* event) override;
+   std::unique_ptr<views::ActionViewInterface> GetActionViewInterface() override;
++  void AddLayerToRegion(ui::Layer* new_layer,
++                        views::LayerRegion region) override;
++  void RemoveLayerFromRegions(ui::Layer* old_layer) override;
+ 
+   // When IPH is showing we suppress the tooltip text. This means that we must
+   // provide an alternative accessible name, when this is the case. This is
+diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
+index 10256f53f4f158150daa2fda406dceea9d171f07..74e63d3d0d35d3b72228f262b3557ed9b7ce5b95 100644
+--- a/ui/views/controls/button/label_button.cc
++++ b/ui/views/controls/button/label_button.cc
+@@ -79,13 +79,6 @@ LabelButton::LabelButton(
+   SetTextInternal(text);
+   SetLayoutManager(std::make_unique<DelegatingLayoutManager>(this));
+   GetViewAccessibility().SetIsDefault(is_default_);
+-
+-#if BUILDFLAG(IS_WIN)
+-  // Paint image(s) to a layer so that the canvas is snapped to pixel
+-  // boundaries.
+-  image_container_view()->SetPaintToLayer();
+-  image_container_view()->layer()->SetFillsBoundsOpaquely(false);
+-#endif
+ }
+ 
+ LabelButton::~LabelButton() {
+@@ -540,10 +533,8 @@ void LabelButton::UpdateImage() {
+ 
+ void LabelButton::AddLayerToRegion(ui::Layer* new_layer,
+                                    views::LayerRegion region) {
+-#if !BUILDFLAG(IS_WIN)
+   image_container_view()->SetPaintToLayer();
+   image_container_view()->layer()->SetFillsBoundsOpaquely(false);
+-#endif
+   ink_drop_container()->SetVisible(true);
+   ink_drop_container()->AddLayerToRegion(new_layer, region);
+ }
+@@ -551,9 +542,7 @@ void LabelButton::AddLayerToRegion(ui::Layer* new_layer,
+ void LabelButton::RemoveLayerFromRegions(ui::Layer* old_layer) {
+   ink_drop_container()->RemoveLayerFromRegions(old_layer);
+   ink_drop_container()->SetVisible(false);
+-#if !BUILDFLAG(IS_WIN)
+   image_container_view()->DestroyLayer();
+-#endif
+ }
+ 
+ std::unique_ptr<ActionViewInterface> LabelButton::GetActionViewInterface() {


Test patch: