mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-19 02:13:03 +08:00
[fix] improve Windows taskbar icon clarity at small sizes
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include "platform/windows/gui/slint_backend.h"
|
#include "platform/windows/gui/slint_backend.h"
|
||||||
#include "platform/windows/gui/tray/win_tray.h"
|
#include "platform/windows/gui/tray/win_tray.h"
|
||||||
|
#include "platform/windows/gui/window_icons.h"
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include "platform/macos/gui/tray/mac_tray.h"
|
#include "platform/macos/gui/tray/mac_tray.h"
|
||||||
#include "platform/window_drag.h"
|
#include "platform/window_drag.h"
|
||||||
@@ -1013,6 +1014,9 @@ int GuiApplication::Run() {
|
|||||||
// when deciding whether the last hidden window should stop the event loop.
|
// when deciding whether the last hidden window should stop the event loop.
|
||||||
// Keep the loop alive until the tray's explicit Exit action requests quit.
|
// Keep the loop alive until the tray's explicit Exit action requests quit.
|
||||||
ui_->main->show();
|
ui_->main->show();
|
||||||
|
#if _WIN32
|
||||||
|
ConfigureWindowsWindowIcons(ui_->main->window().win32_hwnd());
|
||||||
|
#endif
|
||||||
slint::run_event_loop(slint::EventLoopMode::RunUntilQuit);
|
slint::run_event_loop(slint::EventLoopMode::RunUntilQuit);
|
||||||
Cleanup();
|
Cleanup();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1155,6 +1159,9 @@ void GuiApplication::InitializeSystemTray() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ui_->main->show();
|
ui_->main->show();
|
||||||
|
#if _WIN32
|
||||||
|
ConfigureWindowsWindowIcons(ui_->main->window().win32_hwnd());
|
||||||
|
#endif
|
||||||
ui_->main->window().set_minimized(false);
|
ui_->main->window().set_minimized(false);
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
MacActivateWindow(ui_->main->window().appkit_view());
|
MacActivateWindow(ui_->main->window().appkit_view());
|
||||||
@@ -2162,6 +2169,9 @@ void GuiApplication::SyncMainWindow() {
|
|||||||
if (!ui_) {
|
if (!ui_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if _WIN32
|
||||||
|
ConfigureWindowsWindowIcons(ui_->main->window().win32_hwnd());
|
||||||
|
#endif
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
if (ui_->main_native_titlebar_attempts > 0) {
|
if (ui_->main_native_titlebar_attempts > 0) {
|
||||||
if (HideDisabledMainWindowZoomButton()) {
|
if (HideDisabledMainWindowZoomButton()) {
|
||||||
@@ -2451,6 +2461,9 @@ void GuiApplication::SyncStreamWindow() {
|
|||||||
if (!ui_->stream) {
|
if (!ui_->stream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if _WIN32
|
||||||
|
ConfigureWindowsWindowIcons((*ui_->stream)->window().win32_hwnd());
|
||||||
|
#endif
|
||||||
(*ui_->stream)->set_window_maximized((*ui_->stream)->window().is_maximized());
|
(*ui_->stream)->set_window_maximized((*ui_->stream)->window().is_maximized());
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
if (ui_->stream_live_resize_configuration_attempts > 0) {
|
if (ui_->stream_live_resize_configuration_attempts > 0) {
|
||||||
@@ -2895,6 +2908,10 @@ void GuiApplication::SyncServerWindow() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
ConfigureWindowsWindowIcons((*ui_->server)->window().win32_hwnd());
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<ui::ControllerEntry> controllers;
|
std::vector<ui::ControllerEntry> controllers;
|
||||||
std::vector<slint::SharedString> names;
|
std::vector<slint::SharedString> names;
|
||||||
ui_->controller_ids.clear();
|
ui_->controller_ids.clear();
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
#include "window_icons.h"
|
||||||
|
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr UINT_PTR kIconSubclassId = 1;
|
||||||
|
|
||||||
|
struct WindowIcons {
|
||||||
|
HICON small_icon = nullptr;
|
||||||
|
HICON large_icon = nullptr;
|
||||||
|
|
||||||
|
~WindowIcons() {
|
||||||
|
if (small_icon) DestroyIcon(small_icon);
|
||||||
|
if (large_icon) DestroyIcon(large_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Load(UINT dpi) {
|
||||||
|
const HMODULE module = GetModuleHandleW(nullptr);
|
||||||
|
small_icon = static_cast<HICON>(LoadImageW(
|
||||||
|
module, L"IDI_ICON1", IMAGE_ICON,
|
||||||
|
GetSystemMetricsForDpi(SM_CXSMICON, dpi),
|
||||||
|
GetSystemMetricsForDpi(SM_CYSMICON, dpi), 0));
|
||||||
|
large_icon = static_cast<HICON>(LoadImageW(
|
||||||
|
module, L"IDI_ICON1", IMAGE_ICON,
|
||||||
|
GetSystemMetricsForDpi(SM_CXICON, dpi),
|
||||||
|
GetSystemMetricsForDpi(SM_CYICON, dpi), 0));
|
||||||
|
return small_icon && large_icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Apply(HWND window) const {
|
||||||
|
// Do not destroy the replaced handles: Slint/winit owns those images.
|
||||||
|
SendMessageW(window, WM_SETICON, ICON_SMALL,
|
||||||
|
reinterpret_cast<LPARAM>(small_icon));
|
||||||
|
SendMessageW(window, WM_SETICON, ICON_BIG,
|
||||||
|
reinterpret_cast<LPARAM>(large_icon));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LRESULT CALLBACK IconSubclassProc(HWND window, UINT message, WPARAM wparam,
|
||||||
|
LPARAM lparam, UINT_PTR subclass_id,
|
||||||
|
DWORD_PTR reference_data) {
|
||||||
|
auto* icons = reinterpret_cast<WindowIcons*>(reference_data);
|
||||||
|
if (message == WM_SETICON) {
|
||||||
|
// Slint supplies the same PNG for both sizes, including during deferred
|
||||||
|
// window initialization. Keep using the matching frames from our ICO.
|
||||||
|
if (wparam == ICON_SMALL) {
|
||||||
|
lparam = reinterpret_cast<LPARAM>(icons->small_icon);
|
||||||
|
} else if (wparam == ICON_BIG) {
|
||||||
|
lparam = reinterpret_cast<LPARAM>(icons->large_icon);
|
||||||
|
}
|
||||||
|
return DefSubclassProc(window, message, wparam, lparam);
|
||||||
|
}
|
||||||
|
if (message == WM_DPICHANGED) {
|
||||||
|
WindowIcons next;
|
||||||
|
if (next.Load(HIWORD(wparam))) {
|
||||||
|
std::swap(icons->small_icon, next.small_icon);
|
||||||
|
std::swap(icons->large_icon, next.large_icon);
|
||||||
|
icons->Apply(window);
|
||||||
|
// 'next' releases the previous pair only after both were replaced.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (message == WM_NCDESTROY) {
|
||||||
|
const LRESULT result = DefSubclassProc(window, message, wparam, lparam);
|
||||||
|
RemoveWindowSubclass(window, IconSubclassProc, subclass_id);
|
||||||
|
delete icons;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return DefSubclassProc(window, message, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool ConfigureWindowsWindowIcons(HWND window) {
|
||||||
|
if (!window) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DWORD_PTR existing = 0;
|
||||||
|
if (GetWindowSubclass(window, IconSubclassProc, kIconSubclassId, &existing)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto icons = std::make_unique<WindowIcons>();
|
||||||
|
const UINT dpi = GetDpiForWindow(window);
|
||||||
|
if (!dpi || !icons->Load(dpi) ||
|
||||||
|
!SetWindowSubclass(window, IconSubclassProc, kIconSubclassId,
|
||||||
|
reinterpret_cast<DWORD_PTR>(icons.get()))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// The subclass owns the pair until WM_NCDESTROY, even if Slint hides and
|
||||||
|
// recreates its native window while the component itself stays alive.
|
||||||
|
auto* installed = icons.release();
|
||||||
|
installed->Apply(window);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef CROSSDESK_WINDOWS_WINDOW_ICONS_H_
|
||||||
|
#define CROSSDESK_WINDOWS_WINDOW_ICONS_H_
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
|
// Call on the window's UI thread once its native handle exists. Repeated calls
|
||||||
|
// are harmless. Icons follow DPI changes and are released with the window.
|
||||||
|
bool ConfigureWindowsWindowIcons(HWND window);
|
||||||
|
|
||||||
|
} // namespace crossdesk
|
||||||
|
|
||||||
|
#endif // CROSSDESK_WINDOWS_WINDOW_ICONS_H_
|
||||||
@@ -399,8 +399,10 @@ function setup_targets()
|
|||||||
if is_os("windows") then
|
if is_os("windows") then
|
||||||
add_cxxflags("/bigobj")
|
add_cxxflags("/bigobj")
|
||||||
add_links("opengl32")
|
add_links("opengl32")
|
||||||
|
add_syslinks("Comctl32", {public = true})
|
||||||
add_files("apps/desktop/src/platform/windows/gui/tray/win_tray.cpp",
|
add_files("apps/desktop/src/platform/windows/gui/tray/win_tray.cpp",
|
||||||
"apps/desktop/src/platform/windows/gui/slint_backend.cpp",
|
"apps/desktop/src/platform/windows/gui/slint_backend.cpp",
|
||||||
|
"apps/desktop/src/platform/windows/gui/window_icons.cpp",
|
||||||
"apps/desktop/src/platform/windows/gui/slint_renderer_probe.cpp",
|
"apps/desktop/src/platform/windows/gui/slint_renderer_probe.cpp",
|
||||||
"apps/desktop/src/platform/common/gui/opengl_video_renderer.cpp",
|
"apps/desktop/src/platform/common/gui/opengl_video_renderer.cpp",
|
||||||
"apps/desktop/src/platform/common/gui/cuda_driver.cpp",
|
"apps/desktop/src/platform/common/gui/cuda_driver.cpp",
|
||||||
|
|||||||
Reference in New Issue
Block a user