From 417e16cedd3b9aca22193848211960d37d655238 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 23:16:12 +0100 Subject: [PATCH] fix: missing badge text on Windows (#41629) https://chromium-review.googlesource.com/c/chromium/src/+/5053607 Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr --- shell/browser/browser_win.cc | 3 +- shell/browser/ui/win/taskbar_host.cc | 50 ++++++++++++++++++++++++++-- shell/browser/ui/win/taskbar_host.h | 2 +- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/shell/browser/browser_win.cc b/shell/browser/browser_win.cc index a7379fe921a..e6ac9b7fddf 100644 --- a/shell/browser/browser_win.cc +++ b/shell/browser/browser_win.cc @@ -40,6 +40,7 @@ #include "shell/common/gin_helper/dictionary.h" #include "shell/common/skia_util.h" #include "shell/common/thread_restrictions.h" +#include "skia/ext/font_utils.h" #include "skia/ext/legacy_display_globals.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkFont.h" @@ -591,7 +592,7 @@ void Browser::UpdateBadgeContents( paint.reset(); paint.setColor(kForegroundColor); - SkFont font; + SkFont font = skia::DefaultFont(); SkRect bounds; int text_size = kMaxTextSize; diff --git a/shell/browser/ui/win/taskbar_host.cc b/shell/browser/ui/win/taskbar_host.cc index e17a11fa7a9..1615663d8c5 100644 --- a/shell/browser/ui/win/taskbar_host.cc +++ b/shell/browser/ui/win/taskbar_host.cc @@ -11,7 +11,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/scoped_gdi_object.h" #include "shell/browser/native_window.h" +#include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkRRect.h" #include "ui/display/win/screen_win.h" #include "ui/gfx/icon_util.h" @@ -166,13 +169,56 @@ bool TaskbarHost::SetProgressBar(HWND window, return success; } +// Adapted from SetOverlayIcon in +// chrome/browser/taskbar/taskbar_decorator_win.cc. bool TaskbarHost::SetOverlayIcon(HWND window, - const SkBitmap& overlay, + const SkBitmap& bitmap, const std::string& text) { if (!InitializeTaskbar()) return false; - base::win::ScopedHICON icon(IconUtil::CreateHICONFromSkBitmap(overlay)); + base::win::ScopedGDIObject icon; + if (!bitmap.isNull()) { + DCHECK_GE(bitmap.width(), bitmap.height()); + + constexpr int kOverlayIconSize = 16; + + // Maintain aspect ratio on resize, but prefer more square. + // (We used to round down here, but rounding up produces nicer results.) + const int resized_height = + base::ClampCeil(kOverlayIconSize * + (static_cast(bitmap.height()) / bitmap.width())); + + DCHECK_GE(kOverlayIconSize, resized_height); + // Since the target size is so small, we use our best resizer. + SkBitmap sk_icon = skia::ImageOperations::Resize( + bitmap, skia::ImageOperations::RESIZE_LANCZOS3, kOverlayIconSize, + resized_height); + + // Paint the resized icon onto a 16x16 canvas otherwise Windows will badly + // hammer it to 16x16. We'll use a circular clip to be consistent with the + // way profile icons are rendered in the profile switcher. + SkBitmap offscreen_bitmap; + offscreen_bitmap.allocN32Pixels(kOverlayIconSize, kOverlayIconSize); + SkCanvas offscreen_canvas(offscreen_bitmap, SkSurfaceProps{}); + offscreen_canvas.clear(SK_ColorTRANSPARENT); + + static const SkRRect overlay_icon_clip = + SkRRect::MakeOval(SkRect::MakeWH(kOverlayIconSize, kOverlayIconSize)); + offscreen_canvas.clipRRect(overlay_icon_clip, true); + + // Note: the original code used kOverlayIconSize - resized_height, but in + // order to center the icon in the circle clip area, we're going to center + // it in the paintable region instead, rounding up to the closest pixel to + // avoid smearing. + const int y_offset = std::ceilf((kOverlayIconSize - resized_height) / 2.0f); + offscreen_canvas.drawImage(sk_icon.asImage(), 0, y_offset); + + icon = IconUtil::CreateHICONFromSkBitmap(offscreen_bitmap); + if (!icon.is_valid()) + return false; + } + return SUCCEEDED(taskbar_->SetOverlayIcon(window, icon.get(), base::UTF8ToWide(text).c_str())); } diff --git a/shell/browser/ui/win/taskbar_host.h b/shell/browser/ui/win/taskbar_host.h index ffcb309f556..73060b1cc4e 100644 --- a/shell/browser/ui/win/taskbar_host.h +++ b/shell/browser/ui/win/taskbar_host.h @@ -52,7 +52,7 @@ class TaskbarHost { // Set the overlay icon in taskbar. bool SetOverlayIcon(HWND window, - const SkBitmap& overlay, + const SkBitmap& bitmap, const std::string& text); // Set the region of the window to show as a thumbnail in taskbar.