changeset 15701:4a331e8d01df

Fix win32 docklet. This is pretty ugly - we'll force GTK+ 2.10 at some point and use GtkStatusIcon to avoid converting the stock images to HICONs directly.
author Daniel Atallah <daniel.atallah@gmail.com>
date Sun, 25 Feb 2007 18:41:53 +0000
parents 074ac986fae0
children 87e807f25b3c
files pidgin/Makefile.mingw pidgin/gtkdocklet.c pidgin/pixmaps/Makefile.am pidgin/pixmaps/animations/16/Makefile.am pidgin/pixmaps/gaim_16.ico pidgin/pixmaps/gaim_4bit_16.ico pidgin/pixmaps/gaim_away.ico pidgin/pixmaps/gaim_away_16.ico pidgin/pixmaps/gaim_away_4bit_16.ico pidgin/pixmaps/gaim_blank_4bit_16.ico pidgin/pixmaps/gaim_msgpend_16.ico pidgin/pixmaps/gaim_msgpend_4bit_16.ico pidgin/pixmaps/gaim_msgunread_16.ico pidgin/pixmaps/gaim_msgunread_4bit_16.ico pidgin/pixmaps/gaim_offline.ico pidgin/pixmaps/gaim_offline_16.ico pidgin/pixmaps/gaim_offline_4bit_16.ico pidgin/win32/gtkdocklet-win32.c pidgin/win32/pidgin_exe_rc.rc.in pidgin/win32/resource.h
diffstat 20 files changed, 397 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/Makefile.mingw	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/Makefile.mingw	Sun Feb 25 18:41:53 2007 +0000
@@ -123,7 +123,8 @@
 		-latk-1.0 \
 		-lpango-1.0 \
 		-lgdk-win32-2.0 \
-		-lgdk_pixbuf-2.0
+		-lgdk_pixbuf-2.0 \
+		-lgdi32
 
 include $(GAIM_COMMON_RULES)
 
--- a/pidgin/gtkdocklet.c	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/gtkdocklet.c	Sun Feb 25 18:41:53 2007 +0000
@@ -186,11 +186,11 @@
 		if (gaim_account_is_connecting(account))
 			connecting = TRUE;
 	}
-	
+
 	saved_status = gaim_savedstatus_get_current();
-        prim = gaim_savedstatus_get_type(saved_status);
+	prim = gaim_savedstatus_get_type(saved_status);
 	if (pending)
-		newstatus = DOCKLET_STATUS_PENDING;	
+		newstatus = DOCKLET_STATUS_PENDING;
 	else if (connecting)
 		newstatus = DOCKLET_STATUS_CONNECTING;
 	else if (prim == GAIM_STATUS_UNAVAILABLE)
@@ -198,12 +198,12 @@
 	else if (prim == GAIM_STATUS_AWAY)
 		newstatus = DOCKLET_STATUS_AWAY;
 	else if (prim == GAIM_STATUS_EXTENDED_AWAY)
-        	newstatus = DOCKLET_STATUS_XA;
-        else if (prim == GAIM_STATUS_OFFLINE)
-        	newstatus = DOCKLET_STATUS_OFFLINE;
+		newstatus = DOCKLET_STATUS_XA;
+	else if (prim == GAIM_STATUS_OFFLINE)
+		newstatus = DOCKLET_STATUS_OFFLINE;
 	else
 		newstatus = DOCKLET_STATUS_AVAILABLE;
-			      
+
 	/* update the icon if we changed status */
 	if (status != newstatus) {
 		status = newstatus;
--- a/pidgin/pixmaps/Makefile.am	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/pixmaps/Makefile.am	Sun Feb 25 18:41:53 2007 +0000
@@ -48,18 +48,7 @@
 		typing.png			\
 		Makefile.mingw			\
 		gaim-install.ico		\
-		gaim.ico			\
-		gaim_16.ico			\
-		gaim_4bit_16.ico		\
-		gaim_away_16.ico		\
-		gaim_away_4bit_16.ico		\
-		gaim_blank_4bit_16.ico		\
-		gaim_msgpend_16.ico		\
-		gaim_msgpend_4bit_16.ico	\
-		gaim_msgunread_16.ico		\
-		gaim_msgunread_4bit_16.ico	\
-		gaim_offline_16.ico		\
-		gaim_offline_4bit_16.ico
+		gaim.ico			
 
 
 gaimbuttonpixdir = $(datadir)/pixmaps/gaim/buttons
--- a/pidgin/pixmaps/animations/16/Makefile.am	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/pixmaps/animations/16/Makefile.am	Sun Feb 25 18:41:53 2007 +0000
@@ -6,7 +6,7 @@
 		connect5.png \
 		connect6.png \
 		connect7.png \
-		connect8.png
+		connect8.png \
 		typing0.png \
 		typing1.png \
 		typing2.png \
Binary file pidgin/pixmaps/gaim_16.ico has changed
Binary file pidgin/pixmaps/gaim_4bit_16.ico has changed
Binary file pidgin/pixmaps/gaim_away.ico has changed
Binary file pidgin/pixmaps/gaim_away_16.ico has changed
Binary file pidgin/pixmaps/gaim_away_4bit_16.ico has changed
Binary file pidgin/pixmaps/gaim_blank_4bit_16.ico has changed
Binary file pidgin/pixmaps/gaim_msgpend_16.ico has changed
Binary file pidgin/pixmaps/gaim_msgpend_4bit_16.ico has changed
Binary file pidgin/pixmaps/gaim_msgunread_16.ico has changed
Binary file pidgin/pixmaps/gaim_msgunread_4bit_16.ico has changed
Binary file pidgin/pixmaps/gaim_offline.ico has changed
Binary file pidgin/pixmaps/gaim_offline_16.ico has changed
Binary file pidgin/pixmaps/gaim_offline_4bit_16.ico has changed
--- a/pidgin/win32/gtkdocklet-win32.c	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/win32/gtkdocklet-win32.c	Sun Feb 25 18:41:53 2007 +0000
@@ -34,6 +34,7 @@
 #include "MinimizeToTray.h"
 #include "gtkwin32dep.h"
 #include "gtkdocklet.h"
+#include "gaimstock.h"
 
 /*
  *  DEFINES, MACROS & DATA TYPES
@@ -43,13 +44,10 @@
 /*
  *  LOCALS
  */
-static HWND systray_hwnd = 0;
-static HICON sysicon_disconn = 0;
-static HICON sysicon_conn = 0;
-static HICON sysicon_away = 0;
-static HICON sysicon_pend = 0;
-static HICON sysicon_awypend = 0;
-static HICON sysicon_blank = 0;
+static HWND systray_hwnd = NULL;
+static const char *prev_icon_name = NULL;
+static HICON prev_hicon = NULL;
+static GtkWidget *image = NULL;
 static NOTIFYICONDATA _nicon_data;
 
 static LRESULT CALLBACK systray_mainmsg_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
@@ -57,16 +55,16 @@
 
 	switch(msg) {
 	case WM_CREATE:
-		gaim_debug(GAIM_DEBUG_INFO, "docklet", "WM_CREATE\n");
+		gaim_debug_info("docklet", "WM_CREATE\n");
 		taskbarRestartMsg = RegisterWindowMessage("TaskbarCreated");
 		break;
-		
+
 	case WM_TIMER:
-		gaim_debug(GAIM_DEBUG_INFO, "docklet", "WM_TIMER\n");
+		gaim_debug_info("docklet", "WM_TIMER\n");
 		break;
 
 	case WM_DESTROY:
-		gaim_debug(GAIM_DEBUG_INFO, "docklet", "WM_DESTROY\n");
+		gaim_debug_info("docklet", "WM_DESTROY\n");
 		break;
 
 	case WM_TRAYMESSAGE:
@@ -105,7 +103,6 @@
 
 	wname = TEXT("WinpidginSystrayWinCls");
 
-
 	wcex.cbSize = sizeof(wcex);
 	wcex.style		= 0;
 	wcex.lpfnWndProc	= systray_mainmsg_handler;
@@ -125,22 +122,362 @@
 	return (CreateWindow(wname, "", 0, 0, 0, 0, 0, GetDesktopWindow(), NULL, winpidgin_hinstance(), 0));
 }
 
-static void systray_init_icon(HWND hWnd, HICON icon) {
+static void systray_init_icon(HWND hWnd) {
 	ZeroMemory(&_nicon_data, sizeof(_nicon_data));
 	_nicon_data.cbSize = sizeof(NOTIFYICONDATA);
 	_nicon_data.hWnd = hWnd;
 	_nicon_data.uID = 0;
 	_nicon_data.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
 	_nicon_data.uCallbackMessage = WM_TRAYMESSAGE;
-	_nicon_data.hIcon = icon;
+	_nicon_data.hIcon = NULL;
 	lstrcpy(_nicon_data.szTip, PIDGIN_NAME);
 	Shell_NotifyIcon(NIM_ADD, &_nicon_data);
 	pidgin_docklet_embedded();
 }
 
-static void systray_change_icon(HICON icon) {
-	_nicon_data.hIcon = icon;
+/* This is ganked from GTK+.
+ * When we can use GTK+ 2.10 and the GtkStatusIcon stuff, this will no longer be necesary */
+#define WIN32_GDI_FAILED(api) printf("GDI FAILED %s\n", api)
+
+static gboolean
+_gdk_win32_pixbuf_to_hicon_supports_alpha (void)
+{
+  static gboolean is_win_xp=FALSE, is_win_xp_checked=FALSE;
+
+  if (!is_win_xp_checked)
+    {
+      is_win_xp_checked = TRUE;
+
+      if (!G_WIN32_IS_NT_BASED ())
+	is_win_xp = FALSE;
+      else
+	{
+	  OSVERSIONINFO version;
+
+	  memset (&version, 0, sizeof (version));
+	  version.dwOSVersionInfoSize = sizeof (version);
+	  is_win_xp = GetVersionEx (&version)
+	    && version.dwPlatformId == VER_PLATFORM_WIN32_NT
+	    && (version.dwMajorVersion > 5
+		|| (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
+	}
+    }
+  return is_win_xp;
+}
+
+static HBITMAP
+create_alpha_bitmap (gint     size,
+		     guchar **outdata)
+{
+  BITMAPV5HEADER bi;
+  HDC hdc;
+  HBITMAP hBitmap;
+
+  ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
+  bi.bV5Size = sizeof (BITMAPV5HEADER);
+  bi.bV5Height = bi.bV5Width = size;
+  bi.bV5Planes = 1;
+  bi.bV5BitCount = 32;
+  bi.bV5Compression = BI_BITFIELDS;
+  /* The following mask specification specifies a supported 32 BPP
+   * alpha format for Windows XP (BGRA format).
+   */
+  bi.bV5RedMask   = 0x00FF0000;
+  bi.bV5GreenMask = 0x0000FF00;
+  bi.bV5BlueMask  = 0x000000FF;
+  bi.bV5AlphaMask = 0xFF000000;
+
+  /* Create the DIB section with an alpha channel. */
+  hdc = GetDC (NULL);
+  if (!hdc)
+    {
+      WIN32_GDI_FAILED ("GetDC");
+      return NULL;
+    }
+  hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
+			      (PVOID *) outdata, NULL, (DWORD)0);
+  if (hBitmap == NULL)
+    WIN32_GDI_FAILED ("CreateDIBSection");
+  ReleaseDC (NULL, hdc);
+
+  return hBitmap;
+}
+
+static HBITMAP
+create_color_bitmap (gint     size,
+		     guchar **outdata,
+		     gint     bits)
+{
+  struct {
+    BITMAPV4HEADER bmiHeader;
+    RGBQUAD bmiColors[2];
+  } bmi;
+  HDC hdc;
+  HBITMAP hBitmap;
+
+  ZeroMemory (&bmi, sizeof (bmi));
+  bmi.bmiHeader.bV4Size = sizeof (BITMAPV4HEADER);
+  bmi.bmiHeader.bV4Height = bmi.bmiHeader.bV4Width = size;
+  bmi.bmiHeader.bV4Planes = 1;
+  bmi.bmiHeader.bV4BitCount = bits;
+  bmi.bmiHeader.bV4V4Compression = BI_RGB;
+
+  /* when bits is 1, these will be used.
+   * bmiColors[0] already zeroed from ZeroMemory()
+   */
+  bmi.bmiColors[1].rgbBlue = 0xFF;
+  bmi.bmiColors[1].rgbGreen = 0xFF;
+  bmi.bmiColors[1].rgbRed = 0xFF;
+
+  hdc = GetDC (NULL);
+  if (!hdc)
+    {
+      WIN32_GDI_FAILED ("GetDC");
+      return NULL;
+    }
+  hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bmi, DIB_RGB_COLORS,
+			      (PVOID *) outdata, NULL, (DWORD)0);
+  if (hBitmap == NULL)
+    WIN32_GDI_FAILED ("CreateDIBSection");
+  ReleaseDC (NULL, hdc);
+
+  return hBitmap;
+}
+
+static gboolean
+pixbuf_to_hbitmaps_alpha_winxp (GdkPixbuf *pixbuf,
+				HBITMAP   *color,
+				HBITMAP   *mask)
+{
+  /* Based on code from
+   * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
+   */
+  HBITMAP hColorBitmap, hMaskBitmap;
+  guchar *indata, *inrow;
+  guchar *colordata, *colorrow, *maskdata, *maskbyte;
+  gint width, height, size, i, i_offset, j, j_offset, rowstride;
+  guint maskstride, mask_bit;
+
+  width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
+  height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
+
+  /* The bitmaps are created square */
+  size = MAX (width, height);
+
+  hColorBitmap = create_alpha_bitmap (size, &colordata);
+  if (!hColorBitmap)
+    return FALSE;
+  hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
+  if (!hMaskBitmap)
+    {
+      DeleteObject (hColorBitmap);
+      return FALSE;
+    }
+
+  /* MSDN says mask rows are aligned to "LONG" boundaries */
+  maskstride = (((size + 31) & ~31) >> 3);
+
+  indata = gdk_pixbuf_get_pixels (pixbuf);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+  if (width > height)
+    {
+      i_offset = 0;
+      j_offset = (width - height) / 2;
+    }
+  else
+    {
+      i_offset = (height - width) / 2;
+      j_offset = 0;
+    }
+
+  for (j = 0; j < height; j++)
+    {
+      colorrow = colordata + 4*(j+j_offset)*size + 4*i_offset;
+      maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
+      mask_bit = (0x80 >> (i_offset % 8));
+      inrow = indata + (height-j-1)*rowstride;
+      for (i = 0; i < width; i++)
+	{
+	  colorrow[4*i+0] = inrow[4*i+2];
+	  colorrow[4*i+1] = inrow[4*i+1];
+	  colorrow[4*i+2] = inrow[4*i+0];
+	  colorrow[4*i+3] = inrow[4*i+3];
+	  if (inrow[4*i+3] == 0)
+	    maskbyte[0] |= mask_bit;	/* turn ON bit */
+	  else
+	    maskbyte[0] &= ~mask_bit;	/* turn OFF bit */
+	  mask_bit >>= 1;
+	  if (mask_bit == 0)
+	    {
+	      mask_bit = 0x80;
+	      maskbyte++;
+	    }
+	}
+    }
+
+  *color = hColorBitmap;
+  *mask = hMaskBitmap;
+
+  return TRUE;
+}
+
+static gboolean
+pixbuf_to_hbitmaps_normal (GdkPixbuf *pixbuf,
+			   HBITMAP   *color,
+			   HBITMAP   *mask)
+{
+  /* Based on code from
+   * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
+   */
+  HBITMAP hColorBitmap, hMaskBitmap;
+  guchar *indata, *inrow;
+  guchar *colordata, *colorrow, *maskdata, *maskbyte;
+  gint width, height, size, i, i_offset, j, j_offset, rowstride, nc, bmstride;
+  gboolean has_alpha;
+  guint maskstride, mask_bit;
+
+  width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
+  height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
+
+  /* The bitmaps are created square */
+  size = MAX (width, height);
+
+  hColorBitmap = create_color_bitmap (size, &colordata, 24);
+  if (!hColorBitmap)
+    return FALSE;
+  hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
+  if (!hMaskBitmap)
+    {
+      DeleteObject (hColorBitmap);
+      return FALSE;
+    }
+
+  /* rows are always aligned on 4-byte boundarys */
+  bmstride = size * 3;
+  if (bmstride % 4 != 0)
+    bmstride += 4 - (bmstride % 4);
+
+  /* MSDN says mask rows are aligned to "LONG" boundaries */
+  maskstride = (((size + 31) & ~31) >> 3);
+
+  indata = gdk_pixbuf_get_pixels (pixbuf);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  nc = gdk_pixbuf_get_n_channels (pixbuf);
+  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+
+  if (width > height)
+    {
+      i_offset = 0;
+      j_offset = (width - height) / 2;
+    }
+  else
+    {
+      i_offset = (height - width) / 2;
+      j_offset = 0;
+    }
+
+  for (j = 0; j < height; j++)
+    {
+      colorrow = colordata + (j+j_offset)*bmstride + 3*i_offset;
+      maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
+      mask_bit = (0x80 >> (i_offset % 8));
+      inrow = indata + (height-j-1)*rowstride;
+      for (i = 0; i < width; i++)
+	{
+	  if (has_alpha && inrow[nc*i+3] < 128)
+	    {
+	      colorrow[3*i+0] = colorrow[3*i+1] = colorrow[3*i+2] = 0;
+	      maskbyte[0] |= mask_bit;	/* turn ON bit */
+	    }
+	  else
+	    {
+	      colorrow[3*i+0] = inrow[nc*i+2];
+	      colorrow[3*i+1] = inrow[nc*i+1];
+	      colorrow[3*i+2] = inrow[nc*i+0];
+	      maskbyte[0] &= ~mask_bit;	/* turn OFF bit */
+	    }
+	  mask_bit >>= 1;
+	  if (mask_bit == 0)
+	    {
+	      mask_bit = 0x80;
+	      maskbyte++;
+	    }
+	}
+    }
+
+  *color = hColorBitmap;
+  *mask = hMaskBitmap;
+
+  return TRUE;
+}
+
+static HICON
+pixbuf_to_hicon (GdkPixbuf *pixbuf)
+{
+  gint x = 0, y = 0;
+  gboolean is_icon = TRUE;
+  ICONINFO ii;
+  HICON icon;
+  gboolean success;
+
+  if (pixbuf == NULL)
+    return NULL;
+
+  if (_gdk_win32_pixbuf_to_hicon_supports_alpha() && gdk_pixbuf_get_has_alpha (pixbuf))
+    success = pixbuf_to_hbitmaps_alpha_winxp (pixbuf, &ii.hbmColor, &ii.hbmMask);
+  else
+    success = pixbuf_to_hbitmaps_normal (pixbuf, &ii.hbmColor, &ii.hbmMask);
+
+  if (!success)
+    return NULL;
+
+  ii.fIcon = is_icon;
+  ii.xHotspot = x;
+  ii.yHotspot = y;
+  icon = CreateIconIndirect (&ii);
+  DeleteObject (ii.hbmColor);
+  DeleteObject (ii.hbmMask);
+  return icon;
+}
+
+static HICON load_hicon_from_stock(const char *stock) {
+	HICON hicon = NULL;
+	GdkPixbuf *pixbuf = gtk_widget_render_icon(image, stock,
+		gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), NULL);
+
+	if (pixbuf) {
+		hicon = pixbuf_to_hicon(pixbuf);
+		g_object_unref(pixbuf);
+	} else
+		gaim_debug_error("Unable to load pixbuf for %s.\n", stock);
+
+	return hicon;
+}
+
+
+
+static void systray_change_icon(const char *icon_name) {
+	HICON hicon;
+
+	/* Avoid looking up the icon if it hasn't really changed.
+	 * This will happen when re-displaying the icon when blinking.  */
+	if (icon_name == prev_icon_name) {
+		hicon = prev_hicon;
+		prev_hicon = NULL;
+	} else
+		hicon = load_hicon_from_stock(icon_name);
+
+	g_return_if_fail(hicon != NULL);
+
+	_nicon_data.hIcon = hicon;
 	Shell_NotifyIcon(NIM_MODIFY, &_nicon_data);
+
+	if (prev_hicon)
+		DestroyIcon(prev_hicon);
+	prev_hicon = hicon;
+	prev_icon_name = icon_name;
+
 }
 
 static void systray_remove_nid(void) {
@@ -148,29 +485,41 @@
 }
 
 static void winpidgin_tray_update_icon(DockletStatus icon) {
+	const gchar *icon_name = NULL;
+
+	g_return_if_fail(image != NULL);
+
 	switch (icon) {
 		case DOCKLET_STATUS_OFFLINE:
-			systray_change_icon(sysicon_disconn);
+			icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
 			break;
 		case DOCKLET_STATUS_CONNECTING:
+			icon_name = PIDGIN_STOCK_TRAY_CONNECT;
 			break;
-		case DOCKLET_STATUS_ONLINE:
-			systray_change_icon(sysicon_conn);
+		case DOCKLET_STATUS_AVAILABLE:
+			icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
 			break;
-		case DOCKLET_STATUS_ONLINE_PENDING:
-			systray_change_icon(sysicon_pend);
+		case DOCKLET_STATUS_PENDING:
+			icon_name = PIDGIN_STOCK_TRAY_PENDING;
 			break;
 		case DOCKLET_STATUS_AWAY:
-			systray_change_icon(sysicon_away);
+			icon_name = PIDGIN_STOCK_TRAY_AWAY;
 			break;
-		case DOCKLET_STATUS_AWAY_PENDING:
-			systray_change_icon(sysicon_awypend);
+		case DOCKLET_STATUS_BUSY:
+			icon_name = PIDGIN_STOCK_TRAY_BUSY;
+			break;
+		case DOCKLET_STATUS_XA:
+			icon_name = PIDGIN_STOCK_TRAY_XA;
 			break;
 	}
+
+	if(icon_name)
+		systray_change_icon(icon_name);
 }
 
 static void winpidgin_tray_blank_icon() {
-	systray_change_icon(sysicon_blank);
+	_nicon_data.hIcon = NULL;
+	Shell_NotifyIcon(NIM_MODIFY, &_nicon_data);
 }
 
 static void winpidgin_tray_set_tooltip(gchar *tooltip) {
@@ -195,50 +544,35 @@
 
 
 static void winpidgin_tray_create() {
-	OSVERSIONINFO osinfo;
 	/* dummy window to process systray messages */
 	systray_hwnd = systray_create_hiddenwin();
 
-	osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-	GetVersionEx(&osinfo);
-
-	/* Load icons, and init systray notify icon
-	 * NOTE: Windows < XP only supports displaying 4-bit images in the Systray,
-	 *  2K and ME will use the highest color depth that the desktop will support,
-	 *  but will scale it back to 4-bits for display.
-	 * That is why we use custom 4-bit icons for pre XP Windowses */
-	if ((osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion > 0) ||
-		(osinfo.dwMajorVersion >= 6))
-	{
-		sysicon_disconn = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_OFFLINE_TRAY_ICON), IMAGE_ICON, 16, 16, 0);
-		sysicon_conn = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_TRAY_ICON), IMAGE_ICON, 16, 16, 0);
-		sysicon_away = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_AWAY_TRAY_ICON), IMAGE_ICON, 16, 16, 0);
-		sysicon_pend = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_PEND_TRAY_ICON), IMAGE_ICON, 16, 16, 0);
-		sysicon_awypend = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_AWAYPEND_TRAY_ICON), IMAGE_ICON, 16, 16, 0);
-	} else {
-		sysicon_disconn = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_OFFLINE_TRAY_ICON_4BIT), IMAGE_ICON, 16, 16, 0);
-		sysicon_conn = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_TRAY_ICON_4BIT), IMAGE_ICON, 16, 16, 0);
-		sysicon_away = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_AWAY_TRAY_ICON_4BIT), IMAGE_ICON, 16, 16, 0);
-		sysicon_pend = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_PEND_TRAY_ICON_4BIT), IMAGE_ICON, 16, 16, 0);
-		sysicon_awypend = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_AWAYPEND_TRAY_ICON_4BIT), IMAGE_ICON, 16, 16, 0);
-	}
-	sysicon_blank = (HICON)LoadImage(winpidgin_hinstance(), MAKEINTRESOURCE(GAIM_BLANK_TRAY_ICON), IMAGE_ICON, 16, 16, 0);
+	image = gtk_image_new();
+#if GLIB_CHECK_VERSION(2,10,0)
+	g_object_ref_sink(image);
+#else
+	g_object_ref(image);
+	gtk_object_sink(GTK_OBJECT(image));
+#endif
 
 	/* Create icon in systray */
-	systray_init_icon(systray_hwnd, sysicon_disconn);
+	systray_init_icon(systray_hwnd);
 
 	gaim_signal_connect(pidgin_blist_get_handle(), "gtkblist-hiding",
 			pidgin_docklet_get_handle(), GAIM_CALLBACK(winpidgin_tray_minimize), NULL);
 	gaim_signal_connect(pidgin_blist_get_handle(), "gtkblist-unhiding",
 			pidgin_docklet_get_handle(), GAIM_CALLBACK(winpidgin_tray_maximize), NULL);
 
-	gaim_debug(GAIM_DEBUG_INFO, "docklet", "created\n");
+	gaim_debug_info("docklet", "created\n");
 }
 
 static void winpidgin_tray_destroy() {
 	systray_remove_nid();
 	DestroyWindow(systray_hwnd);
 	pidgin_docklet_remove();
+
+	g_object_unref(image);
+	image = NULL;
 }
 
 static struct docklet_ui_ops winpidgin_tray_ops =
--- a/pidgin/win32/pidgin_exe_rc.rc.in	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/win32/pidgin_exe_rc.rc.in	Sun Feb 25 18:41:53 2007 +0000
@@ -34,14 +34,3 @@
   END
 
 GAIM_ICON			ICON PIXMAPDIR "gaim.ico"
-GAIM_TRAY_ICON			ICON PIXMAPDIR "gaim_16.ico"
-GAIM_OFFLINE_TRAY_ICON		ICON PIXMAPDIR "gaim_offline_16.ico"
-GAIM_AWAY_TRAY_ICON		ICON PIXMAPDIR "gaim_away_16.ico"
-GAIM_PEND_TRAY_ICON		ICON PIXMAPDIR "gaim_msgunread_16.ico"
-GAIM_AWAYPEND_TRAY_ICON 	ICON PIXMAPDIR "gaim_msgpend_16.ico"
-GAIM_BLANK_TRAY_ICON		ICON PIXMAPDIR "gaim_blank_4bit_16.ico"
-GAIM_TRAY_ICON_4BIT		ICON PIXMAPDIR "gaim_4bit_16.ico"
-GAIM_OFFLINE_TRAY_ICON_4BIT	ICON PIXMAPDIR "gaim_offline_4bit_16.ico"
-GAIM_AWAY_TRAY_ICON_4BIT	ICON PIXMAPDIR "gaim_away_4bit_16.ico"
-GAIM_PEND_TRAY_ICON_4BIT	ICON PIXMAPDIR "gaim_msgunread_4bit_16.ico"
-GAIM_AWAYPEND_TRAY_ICON_4BIT	ICON PIXMAPDIR "gaim_msgpend_4bit_16.ico"
--- a/pidgin/win32/resource.h	Sun Feb 25 10:32:34 2007 +0000
+++ b/pidgin/win32/resource.h	Sun Feb 25 18:41:53 2007 +0000
@@ -1,14 +1,1 @@
 #define GAIM_ICON                       104
-#define GAIM_OFFLINE_ICON               105
-#define GAIM_AWAY_ICON                  106
-#define GAIM_TRAY_ICON                  107
-#define GAIM_OFFLINE_TRAY_ICON          108
-#define GAIM_AWAY_TRAY_ICON             109
-#define GAIM_PEND_TRAY_ICON             110
-#define GAIM_AWAYPEND_TRAY_ICON         111
-#define GAIM_BLANK_TRAY_ICON            112
-#define GAIM_TRAY_ICON_4BIT             113
-#define GAIM_OFFLINE_TRAY_ICON_4BIT     114
-#define GAIM_AWAY_TRAY_ICON_4BIT        115
-#define GAIM_PEND_TRAY_ICON_4BIT        116
-#define GAIM_AWAYPEND_TRAY_ICON_4BIT    117