Add Win32 taskbar attention alerts for highlights/PMs

This commit is contained in:
2026-06-10 10:45:17 -06:00
parent 220074bf11
commit b90614db6e
3 changed files with 148 additions and 1 deletions

View File

@@ -31,7 +31,7 @@
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(ArchiveLibDir);$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>$(DepLibs);$(ZoiteChatLib)common.lib;wbemuuid.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(DepLibs);$(ZoiteChatLib)common.lib;wbemuuid.lib;dwmapi.lib;ole32.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>

View File

@@ -92,6 +92,8 @@ if host_machine.system() == 'windows'
zoitechat_gtk_sources += 'notifications/notification-windows.c'
zoitechat_gtk_deps += cc.find_library('dwmapi', required: true)
zoitechat_gtk_deps += cc.find_library('shell32', required: true)
zoitechat_gtk_deps += cc.find_library('ole32', required: true)
zoitechat_gtk_deps += cc.find_library('uuid', required: true)
zoitechat_theme_deps += cc.find_library('dwmapi', required: true)
else

View File

@@ -35,6 +35,7 @@
#ifdef WIN32
#include <windows.h>
#include <shellapi.h>
#include <shobjidl.h>
#include <gdk/gdkwin32.h>
#endif
#if defined(GTK_DISABLE_DEPRECATED)
@@ -131,6 +132,7 @@ static void tray_menu_notify_cb (GObject *tray, GParamSpec *pspec, gpointer user
static void tray_update_toggle_item_label (void);
static gboolean tray_window_state_cb (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata);
static void tray_window_visibility_cb (GtkWidget *widget, gpointer userdata);
static WinStatus tray_get_window_status (void);
static void tray_toggle_item_destroy_cb (GtkWidget *widget, gpointer userdata);
#if HAVE_APPINDICATOR_BACKEND
static void tray_menu_show_cb (GtkWidget *menu, gpointer userdata) G_GNUC_UNUSED;
@@ -158,6 +160,8 @@ static GtkStatusIcon *tray_status_icon;
#ifdef WIN32
static HWND tray_win32_hwnd;
static HICON tray_win32_icon;
static HICON tray_win32_overlay_icon;
static ITaskbarList3 *tray_win32_taskbar;
static gboolean tray_win32_active;
static UINT tray_win32_taskbar_created;
static const UINT tray_win32_callback_msg = WM_APP + 42;
@@ -606,6 +610,132 @@ tray_win32_pixbuf_to_hicon (GdkPixbuf *pixbuf)
return icon;
}
static HWND
tray_win32_get_main_hwnd (void)
{
GtkWindow *win;
GdkWindow *gdk_window;
win = GTK_WINDOW (zoitechat_get_info (ph, "gtkwin_ptr"));
if (!win)
return NULL;
gdk_window = gtk_widget_get_window (GTK_WIDGET (win));
if (!gdk_window)
return NULL;
return gdk_win32_window_get_handle (gdk_window);
}
static ITaskbarList3 *
tray_win32_get_taskbar (void)
{
HRESULT hr;
if (tray_win32_taskbar)
return tray_win32_taskbar;
hr = CoCreateInstance (&CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
&IID_ITaskbarList3, (void **)&tray_win32_taskbar);
if (FAILED (hr))
return NULL;
hr = tray_win32_taskbar->lpVtbl->HrInit (tray_win32_taskbar);
if (FAILED (hr))
{
tray_win32_taskbar->lpVtbl->Release (tray_win32_taskbar);
tray_win32_taskbar = NULL;
return NULL;
}
return tray_win32_taskbar;
}
static void
tray_win32_release_attention (void)
{
if (tray_win32_overlay_icon)
{
DestroyIcon (tray_win32_overlay_icon);
tray_win32_overlay_icon = NULL;
}
if (tray_win32_taskbar)
{
tray_win32_taskbar->lpVtbl->Release (tray_win32_taskbar);
tray_win32_taskbar = NULL;
}
}
static void
tray_win32_clear_attention (void)
{
FLASHWINFO flash;
ITaskbarList3 *taskbar;
HWND hwnd;
hwnd = tray_win32_get_main_hwnd ();
if (!hwnd)
return;
ZeroMemory (&flash, sizeof (flash));
flash.cbSize = sizeof (flash);
flash.hwnd = hwnd;
flash.dwFlags = FLASHW_STOP;
FlashWindowEx (&flash);
taskbar = tray_win32_get_taskbar ();
if (taskbar)
taskbar->lpVtbl->SetOverlayIcon (taskbar, hwnd, NULL, L"");
if (tray_win32_overlay_icon)
{
DestroyIcon (tray_win32_overlay_icon);
tray_win32_overlay_icon = NULL;
}
}
static void
tray_win32_set_attention (TrayIcon icon)
{
FLASHWINFO flash;
ITaskbarList3 *taskbar;
HICON hicon;
HWND hwnd;
if (tray_get_window_status () == WS_FOCUSED)
return;
hwnd = tray_win32_get_main_hwnd ();
if (!hwnd)
return;
ZeroMemory (&flash, sizeof (flash));
flash.cbSize = sizeof (flash);
flash.hwnd = hwnd;
flash.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
FlashWindowEx (&flash);
taskbar = tray_win32_get_taskbar ();
if (!taskbar)
return;
hicon = tray_win32_pixbuf_to_hicon (icon);
if (!hicon)
return;
if (SUCCEEDED (taskbar->lpVtbl->SetOverlayIcon (taskbar, hwnd, hicon, L"")))
{
if (tray_win32_overlay_icon)
DestroyIcon (tray_win32_overlay_icon);
tray_win32_overlay_icon = hicon;
}
else
{
DestroyIcon (hicon);
}
}
static void
tray_win32_init_data (NOTIFYICONDATAW *nid)
{
@@ -710,6 +840,8 @@ tray_win32_cleanup (void)
tray_win32_icon = NULL;
}
tray_win32_release_attention ();
if (tray_win32_hwnd)
{
DestroyWindow (tray_win32_hwnd);
@@ -1025,6 +1157,10 @@ tray_stop_flash (void)
flash_tag = 0;
}
#ifdef WIN32
tray_win32_clear_attention ();
#endif
if (tray_backend_active)
{
tray_set_icon_state (ICON_NORMAL, TRAY_ICON_NORMAL);
@@ -1641,6 +1777,9 @@ tray_hilight_cb (char *word[], void *userdata)
if (prefs.hex_input_tray_hilight)
{
tray_set_flash (ICON_HILIGHT, TRAY_ICON_HIGHLIGHT);
#ifdef WIN32
tray_win32_set_attention (ICON_HILIGHT);
#endif
/* FIXME: hides any previous private messages */
tray_hilight_count++;
@@ -1692,6 +1831,9 @@ tray_priv (char *from, char *text)
if (prefs.hex_input_tray_priv)
{
tray_set_flash (ICON_MSG, TRAY_ICON_MESSAGE);
#ifdef WIN32
tray_win32_set_attention (ICON_MSG);
#endif
tray_priv_count++;
if (tray_priv_count == 1)
@@ -1763,6 +1905,9 @@ tray_cleanup (void)
if (tray_backend_active)
tray_backend_cleanup ();
#ifdef WIN32
tray_win32_release_attention ();
#endif
}
void