mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-06-10 17:00:18 +00:00
Compare commits
7 Commits
tray-iconi
...
windows-ta
| Author | SHA1 | Date | |
|---|---|---|---|
| b90614db6e | |||
| 220074bf11 | |||
| daa2ed4c42 | |||
| 6e72536e37 | |||
| b1d8f21f2b | |||
|
|
1b8e60c26d | ||
| 035dfdd332 |
@@ -30,6 +30,7 @@
|
||||
#include <windows.h>
|
||||
#include <dwmapi.h>
|
||||
#include <glib/gwin32.h>
|
||||
#include "../../win32/appusermodelid.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -140,7 +141,7 @@ win32_set_appusermodelid (void)
|
||||
if (!set_appid)
|
||||
return;
|
||||
|
||||
set_appid (L"ZoiteChat.Desktop.Notify");
|
||||
set_appid (ZOITECHAT_APPUSERMODELIDW);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1003,7 +1003,9 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
|
||||
menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
mg_win32_allow_autohide_taskbar (wid, event);
|
||||
if (event->changed_mask &
|
||||
(GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN))
|
||||
mg_win32_allow_autohide_taskbar (wid, event);
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
|
||||
@@ -91,6 +91,9 @@ zoitechat_gtk_ldflags = []
|
||||
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
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <roapi.h>
|
||||
#include <windows.ui.notifications.h>
|
||||
#include "../../../win32/appusermodelid.h"
|
||||
|
||||
using namespace Windows::UI::Notifications;
|
||||
using namespace Windows::Data::Xml::Dom;
|
||||
@@ -84,13 +85,20 @@ extern "C"
|
||||
__declspec (dllexport) int
|
||||
notification_backend_init (const char **error)
|
||||
{
|
||||
if (FAILED (Windows::Foundation::Initialize (RO_INIT_SINGLETHREADED)))
|
||||
{
|
||||
*error = "Error initializing Windows::Foundation.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!notifier)
|
||||
notifier = ToastNotificationManager::CreateToastNotifier (L"ZoiteChat.Desktop.Notify");
|
||||
notifier = ToastNotificationManager::CreateToastNotifier (ZOITECHAT_APPUSERMODELIDW);
|
||||
}
|
||||
catch (Platform::Exception ^ ex)
|
||||
{
|
||||
Windows::Foundation::Uninitialize ();
|
||||
static char exc_message[1024];
|
||||
std::string tmp = narrow(std::wstring(ex->Message->Data()));
|
||||
if (SUCCEEDED(StringCchPrintfA(exc_message, _countof(exc_message), "Error (0x%x): %s", ex->HResult, tmp.c_str())))
|
||||
@@ -101,16 +109,11 @@ extern "C"
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Windows::Foundation::Uninitialize ();
|
||||
*error = "Generic c++ exception.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FAILED (Windows::Foundation::Initialize (RO_INIT_SINGLETHREADED)))
|
||||
{
|
||||
*error = "Error initializing Windows::Foundation.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
#include "gtkutil.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <shobjidl.h>
|
||||
#include <gdk/gdkwin32.h>
|
||||
#endif
|
||||
#if defined(GTK_DISABLE_DEPRECATED)
|
||||
typedef struct _GtkStatusIcon GtkStatusIcon;
|
||||
#endif
|
||||
@@ -117,6 +123,7 @@ gboolean gtk_status_icon_is_embedded (GtkStatusIcon *status_icon);
|
||||
|
||||
void tray_apply_setup (void);
|
||||
static gboolean tray_menu_try_restore (void);
|
||||
static gboolean tray_toggle_visibility_from_input (gboolean force_hide, gboolean direct_input);
|
||||
static void tray_cleanup (void);
|
||||
static void tray_init (void);
|
||||
static void tray_set_icon_state (TrayIcon icon, TrayIconState state);
|
||||
@@ -125,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;
|
||||
@@ -149,6 +157,16 @@ static GtkWidget *tray_menu;
|
||||
#if !HAVE_APPINDICATOR_BACKEND
|
||||
static GtkStatusIcon *tray_status_icon;
|
||||
#endif
|
||||
#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;
|
||||
static const GUID tray_win32_guid = { 0xf79ad3d9, 0xc92f, 0x49eb, { 0x9d, 0xd2, 0xe1, 0xad, 0xad, 0xa8, 0x1c, 0xd3 } };
|
||||
#endif
|
||||
static gboolean tray_backend_active = FALSE;
|
||||
|
||||
static gint flash_tag;
|
||||
@@ -510,6 +528,447 @@ tray_status_icon_init (void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static HICON
|
||||
tray_win32_pixbuf_to_hicon (GdkPixbuf *pixbuf)
|
||||
{
|
||||
BITMAPV5HEADER bi;
|
||||
ICONINFO ii;
|
||||
HBITMAP color;
|
||||
HBITMAP mask;
|
||||
HDC dc;
|
||||
HICON icon;
|
||||
guchar *pixels;
|
||||
guchar *src;
|
||||
guchar *dst;
|
||||
void *bits;
|
||||
int width;
|
||||
int height;
|
||||
int rowstride;
|
||||
int channels;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
if (!pixbuf)
|
||||
return NULL;
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
channels = gdk_pixbuf_get_n_channels (pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
|
||||
ZeroMemory (&bi, sizeof (bi));
|
||||
bi.bV5Size = sizeof (bi);
|
||||
bi.bV5Width = width;
|
||||
bi.bV5Height = -height;
|
||||
bi.bV5Planes = 1;
|
||||
bi.bV5BitCount = 32;
|
||||
bi.bV5Compression = BI_BITFIELDS;
|
||||
bi.bV5RedMask = 0x00ff0000;
|
||||
bi.bV5GreenMask = 0x0000ff00;
|
||||
bi.bV5BlueMask = 0x000000ff;
|
||||
bi.bV5AlphaMask = 0xff000000;
|
||||
|
||||
dc = GetDC (NULL);
|
||||
color = CreateDIBSection (dc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||
ReleaseDC (NULL, dc);
|
||||
if (!color)
|
||||
return NULL;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = pixels + y * rowstride;
|
||||
dst = (guchar *)bits + y * width * 4;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
guchar alpha = channels >= 4 ? src[3] : 255;
|
||||
dst[0] = src[2] * alpha / 255;
|
||||
dst[1] = src[1] * alpha / 255;
|
||||
dst[2] = src[0] * alpha / 255;
|
||||
dst[3] = alpha;
|
||||
src += channels;
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
|
||||
mask = CreateBitmap (width, height, 1, 1, NULL);
|
||||
if (!mask)
|
||||
{
|
||||
DeleteObject (color);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMemory (&ii, sizeof (ii));
|
||||
ii.fIcon = TRUE;
|
||||
ii.hbmColor = color;
|
||||
ii.hbmMask = mask;
|
||||
icon = CreateIconIndirect (&ii);
|
||||
DeleteObject (mask);
|
||||
DeleteObject (color);
|
||||
|
||||
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)
|
||||
{
|
||||
ZeroMemory (nid, sizeof (*nid));
|
||||
nid->cbSize = sizeof (*nid);
|
||||
nid->hWnd = tray_win32_hwnd;
|
||||
nid->uID = 1;
|
||||
nid->uFlags = NIF_GUID;
|
||||
nid->guidItem = tray_win32_guid;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tray_win32_add (void)
|
||||
{
|
||||
NOTIFYICONDATAW nid;
|
||||
|
||||
tray_win32_init_data (&nid);
|
||||
nid.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
|
||||
nid.uCallbackMessage = tray_win32_callback_msg;
|
||||
nid.hIcon = tray_win32_icon;
|
||||
wcsncpy (nid.szTip, L"ZoiteChat", G_N_ELEMENTS (nid.szTip) - 1);
|
||||
|
||||
if (!Shell_NotifyIconW (NIM_ADD, &nid))
|
||||
return FALSE;
|
||||
|
||||
tray_win32_init_data (&nid);
|
||||
nid.uVersion = NOTIFYICON_VERSION_4;
|
||||
Shell_NotifyIconW (NIM_SETVERSION, &nid);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
tray_win32_set_icon (TrayIcon icon)
|
||||
{
|
||||
NOTIFYICONDATAW nid;
|
||||
HICON hicon;
|
||||
|
||||
if (!tray_win32_active)
|
||||
return;
|
||||
|
||||
hicon = tray_win32_pixbuf_to_hicon (icon);
|
||||
if (!hicon)
|
||||
return;
|
||||
|
||||
tray_win32_init_data (&nid);
|
||||
nid.uFlags |= NIF_ICON;
|
||||
nid.hIcon = hicon;
|
||||
if (Shell_NotifyIconW (NIM_MODIFY, &nid))
|
||||
{
|
||||
if (tray_win32_icon)
|
||||
DestroyIcon (tray_win32_icon);
|
||||
tray_win32_icon = hicon;
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyIcon (hicon);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tray_win32_set_tooltip (const char *text)
|
||||
{
|
||||
NOTIFYICONDATAW nid;
|
||||
wchar_t *wide;
|
||||
|
||||
if (!tray_win32_active)
|
||||
return;
|
||||
|
||||
wide = g_utf8_to_utf16 (text ? text : "", -1, NULL, NULL, NULL);
|
||||
tray_win32_init_data (&nid);
|
||||
nid.uFlags |= NIF_TIP;
|
||||
if (wide)
|
||||
{
|
||||
wcsncpy (nid.szTip, wide, G_N_ELEMENTS (nid.szTip) - 1);
|
||||
g_free (wide);
|
||||
}
|
||||
Shell_NotifyIconW (NIM_MODIFY, &nid);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tray_win32_is_embedded (void)
|
||||
{
|
||||
return tray_win32_active;
|
||||
}
|
||||
|
||||
static void
|
||||
tray_win32_cleanup (void)
|
||||
{
|
||||
NOTIFYICONDATAW nid;
|
||||
|
||||
if (tray_win32_active)
|
||||
{
|
||||
tray_win32_init_data (&nid);
|
||||
Shell_NotifyIconW (NIM_DELETE, &nid);
|
||||
tray_win32_active = FALSE;
|
||||
}
|
||||
|
||||
if (tray_win32_icon)
|
||||
{
|
||||
DestroyIcon (tray_win32_icon);
|
||||
tray_win32_icon = NULL;
|
||||
}
|
||||
|
||||
tray_win32_release_attention ();
|
||||
|
||||
if (tray_win32_hwnd)
|
||||
{
|
||||
DestroyWindow (tray_win32_hwnd);
|
||||
tray_win32_hwnd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
tray_win32_wndproc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
(void)wparam;
|
||||
|
||||
if (msg == tray_win32_taskbar_created && tray_win32_icon)
|
||||
{
|
||||
tray_win32_add ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg == tray_win32_callback_msg)
|
||||
{
|
||||
switch (LOWORD (lparam))
|
||||
{
|
||||
case NIN_SELECT:
|
||||
case NIN_KEYSELECT:
|
||||
case WM_LBUTTONUP:
|
||||
tray_menu_restore_cb (NULL, NULL);
|
||||
return 0;
|
||||
case WM_CONTEXTMENU:
|
||||
case WM_RBUTTONUP:
|
||||
SetForegroundWindow (hwnd);
|
||||
tray_menu_cb (NULL, 3, GetTickCount (), NULL);
|
||||
PostMessage (hwnd, WM_NULL, 0, 0);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProcW (hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tray_win32_init (void)
|
||||
{
|
||||
WNDCLASSW wc;
|
||||
|
||||
tray_win32_taskbar_created = RegisterWindowMessageW (L"TaskbarCreated");
|
||||
tray_win32_icon = tray_win32_pixbuf_to_hicon (ICON_NORMAL);
|
||||
if (!tray_win32_icon)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory (&wc, sizeof (wc));
|
||||
wc.lpfnWndProc = tray_win32_wndproc;
|
||||
wc.hInstance = GetModuleHandleW (NULL);
|
||||
wc.lpszClassName = L"ZoiteChatTrayWindow";
|
||||
RegisterClassW (&wc);
|
||||
|
||||
tray_win32_hwnd = CreateWindowExW (0, wc.lpszClassName, L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wc.hInstance, NULL);
|
||||
if (!tray_win32_hwnd)
|
||||
{
|
||||
tray_win32_cleanup ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!tray_win32_add ())
|
||||
{
|
||||
tray_win32_cleanup ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tray_win32_active = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tray_win32_or_status_icon_init (void)
|
||||
{
|
||||
if (tray_win32_init ())
|
||||
return TRUE;
|
||||
|
||||
return tray_status_icon_init ();
|
||||
}
|
||||
|
||||
static void
|
||||
tray_win32_or_status_icon_set_icon (TrayIcon icon)
|
||||
{
|
||||
if (tray_win32_active)
|
||||
tray_win32_set_icon (icon);
|
||||
else
|
||||
tray_status_icon_set_icon (icon);
|
||||
}
|
||||
|
||||
static void
|
||||
tray_win32_or_status_icon_set_tooltip (const char *text)
|
||||
{
|
||||
if (tray_win32_active)
|
||||
tray_win32_set_tooltip (text);
|
||||
else
|
||||
tray_status_icon_set_tooltip (text);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tray_win32_or_status_icon_is_embedded (void)
|
||||
{
|
||||
if (tray_win32_active)
|
||||
return tray_win32_is_embedded ();
|
||||
|
||||
return tray_status_icon_is_embedded ();
|
||||
}
|
||||
|
||||
static void
|
||||
tray_win32_or_status_icon_cleanup (void)
|
||||
{
|
||||
if (tray_win32_active || tray_win32_hwnd || tray_win32_icon)
|
||||
tray_win32_cleanup ();
|
||||
else
|
||||
tray_status_icon_cleanup ();
|
||||
}
|
||||
|
||||
static const TrayBackendOps tray_backend_ops = {
|
||||
tray_win32_or_status_icon_init,
|
||||
tray_win32_or_status_icon_set_icon,
|
||||
tray_win32_or_status_icon_set_tooltip,
|
||||
tray_win32_or_status_icon_is_embedded,
|
||||
tray_win32_or_status_icon_cleanup
|
||||
};
|
||||
#else
|
||||
static const TrayBackendOps tray_backend_ops = {
|
||||
tray_status_icon_init,
|
||||
tray_status_icon_set_icon,
|
||||
@@ -518,6 +977,7 @@ static const TrayBackendOps tray_backend_ops = {
|
||||
tray_status_icon_cleanup
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
tray_backend_init (void)
|
||||
@@ -697,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);
|
||||
@@ -847,8 +1311,8 @@ fe_tray_set_file (const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
tray_toggle_visibility (gboolean force_hide)
|
||||
static gboolean
|
||||
tray_toggle_visibility_from_input (gboolean force_hide, gboolean direct_input)
|
||||
{
|
||||
static int x, y;
|
||||
static GdkScreen *screen;
|
||||
@@ -890,9 +1354,29 @@ tray_toggle_visibility (gboolean force_hide)
|
||||
gtk_window_maximize (win);
|
||||
if (fullscreen)
|
||||
gtk_window_fullscreen (win);
|
||||
#ifdef WIN32
|
||||
{
|
||||
GdkWindow *gdk_window;
|
||||
HWND hwnd = NULL;
|
||||
|
||||
gdk_window = gtk_widget_get_window (GTK_WIDGET (win));
|
||||
if (gdk_window)
|
||||
hwnd = gdk_win32_window_get_handle (gdk_window);
|
||||
|
||||
if (hwnd && IsIconic (hwnd))
|
||||
ShowWindow (hwnd, SW_RESTORE);
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (win));
|
||||
gtk_window_present (win);
|
||||
|
||||
if (direct_input && hwnd)
|
||||
SetForegroundWindow (hwnd);
|
||||
}
|
||||
#else
|
||||
gtk_widget_show (GTK_WIDGET (win));
|
||||
gtk_window_deiconify (win);
|
||||
gtk_window_present (win);
|
||||
#endif
|
||||
}
|
||||
|
||||
tray_update_toggle_item_label ();
|
||||
@@ -900,13 +1384,19 @@ tray_toggle_visibility (gboolean force_hide)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tray_toggle_visibility (gboolean force_hide)
|
||||
{
|
||||
return tray_toggle_visibility_from_input (force_hide, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
tray_menu_restore_cb (GtkWidget *item, gpointer userdata)
|
||||
{
|
||||
(void)item;
|
||||
(void)userdata;
|
||||
|
||||
tray_toggle_visibility (FALSE);
|
||||
tray_toggle_visibility_from_input (FALSE, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1042,7 +1532,11 @@ tray_menu_destroy (GtkWidget *menu, gpointer userdata)
|
||||
if (G_IS_OBJECT (menu))
|
||||
g_object_unref (menu);
|
||||
#ifdef WIN32
|
||||
g_source_remove (tray_menu_timer);
|
||||
if (tray_menu_timer)
|
||||
{
|
||||
g_source_remove (tray_menu_timer);
|
||||
tray_menu_timer = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -1283,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++;
|
||||
@@ -1334,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)
|
||||
@@ -1405,6 +1905,9 @@ tray_cleanup (void)
|
||||
|
||||
if (tray_backend_active)
|
||||
tray_backend_cleanup ();
|
||||
#ifdef WIN32
|
||||
tray_win32_release_attention ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1417,7 +1920,7 @@ tray_apply_setup (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if HAVE_APPINDICATOR_BACKEND
|
||||
#if HAVE_APPINDICATOR_BACKEND || defined(WIN32)
|
||||
if (prefs.hex_gui_tray)
|
||||
tray_init ();
|
||||
#else
|
||||
@@ -1471,7 +1974,7 @@ tray_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name,
|
||||
G_CALLBACK (tray_window_visibility_cb), NULL);
|
||||
}
|
||||
|
||||
#if HAVE_APPINDICATOR_BACKEND
|
||||
#if HAVE_APPINDICATOR_BACKEND || defined(WIN32)
|
||||
if (prefs.hex_gui_tray)
|
||||
#else
|
||||
if (prefs.hex_gui_tray && gtkutil_tray_icon_supported (window))
|
||||
|
||||
4
win32/appusermodelid.h
Normal file
4
win32/appusermodelid.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#define ZOITECHAT_APPUSERMODELID "ZoiteChat.Desktop.Notify"
|
||||
#ifdef _WIN32
|
||||
#define ZOITECHAT_APPUSERMODELIDW L"ZoiteChat.Desktop.Notify"
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#define APPNAM "ZoiteChat"
|
||||
#define APPVER "<#= [string]::Join('.', $versionParts) #>"
|
||||
#include "..\appusermodelid.h"
|
||||
; These are defined by our installer project at build time
|
||||
;#define APPARCH "x64"
|
||||
;#define PROJECTDIR "C:\...\zoitechat\win32\installer\"
|
||||
@@ -76,11 +77,14 @@ Root: HKCR; Subkey: "irc"; ValueType: string; ValueName: "URL Protocol"; ValueDa
|
||||
Root: HKCR; Subkey: "irc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\zoitechat.exe,0"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "irc\shell"; ValueType: string; ValueName: ""; ValueData: "open"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "irc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\zoitechat.exe --url=""%1"""; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "irc\Application"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#ZOITECHAT_APPUSERMODELID}"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: ".zct"; ValueType: string; ValueName: ""; ValueData: "ZoiteChat.Theme"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: ".hct"; ValueType: string; ValueName: ""; ValueData: "ZoiteChat.Theme"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "ZoiteChat.Theme"; ValueType: string; ValueName: ""; ValueData: "ZoiteChat Theme"; Flags: uninsdeletekey; Tasks: not portable
|
||||
Root: HKCR; Subkey: "ZoiteChat.Theme\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\zoitechat.exe,0"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "ZoiteChat.Theme\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\zoitechat.exe"" ""%1"""; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "ZoiteChat.Theme\Application"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#ZOITECHAT_APPUSERMODELID}"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
Root: HKCR; Subkey: "Applications\zoitechat.exe\Application"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#ZOITECHAT_APPUSERMODELID}"; Flags: uninsdeletevalue; Tasks: not portable
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\zoitechat.exe"; Description: "Run ZoiteChat after closing the Wizard"; Flags: nowait postinstall skipifsilent
|
||||
@@ -188,15 +192,15 @@ Source: "zoitechat.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: lib
|
||||
Source: "zoitechat-text.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xctext
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "ZoiteChat.Desktop.Notify"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat Safe Mode"; Filename: "{app}\zoitechat.exe"; Parameters: "--no-auto --no-plugins"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat Config Folder"; Filename: "%APPDATA%\ZoiteChat\"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat-Text"; Filename: "{app}\zoitechat-text.exe"; Components: xctext; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\Uninstall ZoiteChat"; Filename: "{uninstallexe}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{commondesktop}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "ZoiteChat.Desktop.Notify"; Components: icons\desktopicon; Tasks: not portable
|
||||
Name: "{commonappdata}\Microsoft\Internet Explorer\Quick Launch\ZoiteChat"; Filename: "{app}\zoitechat.exe"; Components: icons\quicklaunchicon; Tasks: not portable
|
||||
Name: "{group}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat Safe Mode"; Filename: "{app}\zoitechat.exe"; Parameters: "--no-auto --no-plugins"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat Config Folder"; Filename: "%APPDATA%\ZoiteChat\"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\ZoiteChat-Text"; Filename: "{app}\zoitechat-text.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Components: xctext; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{group}\Uninstall ZoiteChat"; Filename: "{uninstallexe}"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Tasks: not portable; Check: not WizardNoIcons
|
||||
Name: "{commondesktop}\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Components: icons\desktopicon; Tasks: not portable
|
||||
Name: "{commonappdata}\Microsoft\Internet Explorer\Quick Launch\ZoiteChat"; Filename: "{app}\zoitechat.exe"; AppUserModelID: "{#ZOITECHAT_APPUSERMODELID}"; Components: icons\quicklaunchicon; Tasks: not portable
|
||||
|
||||
[Messages]
|
||||
BeveledLabel= {#APPNAM}
|
||||
|
||||
Reference in New Issue
Block a user