| 19 * You should have received a copy of the GNU General Public License |
19 * You should have received a copy of the GNU General Public License |
| 20 * along with this program; if not, write to the Free Software |
20 * along with this program; if not, write to the Free Software |
| 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 22 * 02111-1301, USA. |
22 * 02111-1301, USA. |
| 23 */ |
23 */ |
| 24 |
24 #define _WIN32_IE 0x0500 |
| 25 #include <windows.h> |
25 #include <windows.h> |
| 26 #include <gdk/gdkwin32.h> |
26 #include <gdk/gdkwin32.h> |
| 27 #include <gdk/gdk.h> |
27 #include <gdk/gdk.h> |
| 28 |
28 |
| 29 #include "internal.h" |
29 #include "internal.h" |
| 49 static HICON cached_icons[PURPLE_STATUS_NUM_PRIMITIVES + 2]; |
49 static HICON cached_icons[PURPLE_STATUS_NUM_PRIMITIVES + 2]; |
| 50 static GtkWidget *image = NULL; |
50 static GtkWidget *image = NULL; |
| 51 /* This is used to trigger click events on so they appear to GTK+ as if they are triggered by input */ |
51 /* This is used to trigger click events on so they appear to GTK+ as if they are triggered by input */ |
| 52 static GtkWidget *dummy_button = NULL; |
52 static GtkWidget *dummy_button = NULL; |
| 53 static GtkWidget *dummy_window = NULL; |
53 static GtkWidget *dummy_window = NULL; |
| 54 static NOTIFYICONDATA _nicon_data; |
54 static NOTIFYICONDATAW _nicon_data; |
| 55 |
55 |
| 56 static gboolean dummy_button_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { |
56 static gboolean dummy_button_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { |
| 57 pidgin_docklet_clicked(event->button); |
57 pidgin_docklet_clicked(event->button); |
| 58 return TRUE; |
58 return TRUE; |
| 59 } |
59 } |
| 62 static UINT taskbarRestartMsg; /* static here means value is kept across multiple calls to this func */ |
62 static UINT taskbarRestartMsg; /* static here means value is kept across multiple calls to this func */ |
| 63 |
63 |
| 64 switch(msg) { |
64 switch(msg) { |
| 65 case WM_CREATE: |
65 case WM_CREATE: |
| 66 purple_debug_info("docklet", "WM_CREATE\n"); |
66 purple_debug_info("docklet", "WM_CREATE\n"); |
| 67 taskbarRestartMsg = RegisterWindowMessage("TaskbarCreated"); |
67 taskbarRestartMsg = RegisterWindowMessageW(L"TaskbarCreated"); |
| 68 break; |
68 break; |
| 69 |
69 |
| 70 case WM_TIMER: |
70 case WM_TIMER: |
| 71 purple_debug_info("docklet", "WM_TIMER\n"); |
71 purple_debug_info("docklet", "WM_TIMER\n"); |
| 72 break; |
72 break; |
| 112 } |
112 } |
| 113 default: |
113 default: |
| 114 if (msg == taskbarRestartMsg) { |
114 if (msg == taskbarRestartMsg) { |
| 115 /* explorer crashed and left us hanging... |
115 /* explorer crashed and left us hanging... |
| 116 This will put the systray icon back in it's place, when it restarts */ |
116 This will put the systray icon back in it's place, when it restarts */ |
| 117 Shell_NotifyIcon(NIM_ADD, &_nicon_data); |
117 Shell_NotifyIconW(NIM_ADD, &_nicon_data); |
| 118 } |
118 } |
| 119 break; |
119 break; |
| 120 }/* end switch */ |
120 }/* end switch */ |
| 121 |
121 |
| 122 return DefWindowProc(hwnd, msg, wparam, lparam); |
122 return DefWindowProc(hwnd, msg, wparam, lparam); |
| 123 } |
123 } |
| 124 |
124 |
| 125 /* Create hidden window to process systray messages */ |
125 /* Create hidden window to process systray messages */ |
| 126 static HWND systray_create_hiddenwin() { |
126 static HWND systray_create_hiddenwin() { |
| 127 WNDCLASSEX wcex; |
127 WNDCLASSEXW wcex; |
| 128 LPCTSTR wname; |
128 wchar_t *wname; |
| 129 |
129 |
| 130 wname = TEXT("WinpidginSystrayWinCls"); |
130 wname = L"WinpidginSystrayWinCls"; |
| 131 |
131 |
| 132 wcex.cbSize = sizeof(wcex); |
132 wcex.cbSize = sizeof(wcex); |
| 133 wcex.style = 0; |
133 wcex.style = 0; |
| 134 wcex.lpfnWndProc = systray_mainmsg_handler; |
134 wcex.lpfnWndProc = systray_mainmsg_handler; |
| 135 wcex.cbClsExtra = 0; |
135 wcex.cbClsExtra = 0; |
| 140 wcex.hbrBackground = NULL; |
140 wcex.hbrBackground = NULL; |
| 141 wcex.lpszMenuName = NULL; |
141 wcex.lpszMenuName = NULL; |
| 142 wcex.lpszClassName = wname; |
142 wcex.lpszClassName = wname; |
| 143 wcex.hIconSm = NULL; |
143 wcex.hIconSm = NULL; |
| 144 |
144 |
| 145 RegisterClassEx(&wcex); |
145 RegisterClassExW(&wcex); |
| 146 |
146 |
| 147 /* Create the window */ |
147 /* Create the window */ |
| 148 return (CreateWindow(wname, "", 0, 0, 0, 0, 0, GetDesktopWindow(), NULL, winpidgin_exe_hinstance(), 0)); |
148 return (CreateWindowW(wname, L"", 0, 0, 0, 0, 0, GetDesktopWindow(), NULL, winpidgin_exe_hinstance(), 0)); |
| 149 } |
149 } |
| 150 |
150 |
| 151 static void systray_init_icon(HWND hWnd) { |
151 static void systray_init_icon(HWND hWnd) { |
| |
152 wchar_t *w; |
| 152 ZeroMemory(&_nicon_data, sizeof(_nicon_data)); |
153 ZeroMemory(&_nicon_data, sizeof(_nicon_data)); |
| 153 _nicon_data.cbSize = sizeof(NOTIFYICONDATA); |
154 _nicon_data.cbSize = sizeof(NOTIFYICONDATAW); |
| 154 _nicon_data.hWnd = hWnd; |
155 _nicon_data.hWnd = hWnd; |
| 155 _nicon_data.uID = 0; |
156 _nicon_data.uID = 0; |
| 156 _nicon_data.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; |
157 _nicon_data.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; |
| 157 _nicon_data.uCallbackMessage = WM_TRAYMESSAGE; |
158 _nicon_data.uCallbackMessage = WM_TRAYMESSAGE; |
| 158 _nicon_data.hIcon = NULL; |
159 _nicon_data.hIcon = NULL; |
| 159 lstrcpy(_nicon_data.szTip, PIDGIN_NAME); |
160 w = g_utf8_to_utf16(PIDGIN_NAME, -1, NULL, NULL, NULL); |
| 160 Shell_NotifyIcon(NIM_ADD, &_nicon_data); |
161 wcsncpy(_nicon_data.szTip, w, sizeof(_nicon_data.szTip) / sizeof(wchar_t)); |
| |
162 g_free(w); |
| |
163 Shell_NotifyIconW(NIM_ADD, &_nicon_data); |
| 161 pidgin_docklet_embedded(); |
164 pidgin_docklet_embedded(); |
| 162 } |
165 } |
| 163 |
166 |
| 164 /* This is ganked from GTK+. |
167 /* This is ganked from GTK+. |
| 165 * When we can use GTK+ 2.10 and the GtkStatusIcon stuff, this will no longer be necesary */ |
168 * When we can use GTK+ 2.10 and the GtkStatusIcon stuff, this will no longer be necesary */ |
| 484 |
487 |
| 485 static void systray_change_icon(HICON hicon) { |
488 static void systray_change_icon(HICON hicon) { |
| 486 g_return_if_fail(hicon != NULL); |
489 g_return_if_fail(hicon != NULL); |
| 487 |
490 |
| 488 _nicon_data.hIcon = hicon; |
491 _nicon_data.hIcon = hicon; |
| 489 Shell_NotifyIcon(NIM_MODIFY, &_nicon_data); |
492 Shell_NotifyIconW(NIM_MODIFY, &_nicon_data); |
| 490 } |
493 } |
| 491 |
494 |
| 492 static void systray_remove_nid(void) { |
495 static void systray_remove_nid(void) { |
| 493 Shell_NotifyIcon(NIM_DELETE, &_nicon_data); |
496 Shell_NotifyIconW(NIM_DELETE, &_nicon_data); |
| 494 } |
497 } |
| 495 |
498 |
| 496 static void winpidgin_tray_update_icon(PurpleStatusPrimitive status, |
499 static void winpidgin_tray_update_icon(PurpleStatusPrimitive status, |
| 497 gboolean connecting, gboolean pending) { |
500 gboolean connecting, gboolean pending) { |
| 498 |
501 |
| 545 systray_change_icon(cached_icons[icon_index]); |
548 systray_change_icon(cached_icons[icon_index]); |
| 546 } |
549 } |
| 547 |
550 |
| 548 static void winpidgin_tray_blank_icon() { |
551 static void winpidgin_tray_blank_icon() { |
| 549 _nicon_data.hIcon = NULL; |
552 _nicon_data.hIcon = NULL; |
| 550 Shell_NotifyIcon(NIM_MODIFY, &_nicon_data); |
553 Shell_NotifyIconW(NIM_MODIFY, &_nicon_data); |
| 551 } |
554 } |
| 552 |
555 |
| 553 static void winpidgin_tray_set_tooltip(gchar *tooltip) { |
556 static void winpidgin_tray_set_tooltip(gchar *tooltip) { |
| 554 if (tooltip) { |
557 const char *value = tooltip; |
| 555 char *locenc = NULL; |
558 wchar_t *w; |
| 556 locenc = g_locale_from_utf8(tooltip, -1, NULL, NULL, NULL); |
559 if (value == NULL) { |
| 557 lstrcpyn(_nicon_data.szTip, locenc, sizeof(_nicon_data.szTip) / sizeof(TCHAR)); |
560 value = PIDGIN_NAME; |
| 558 g_free(locenc); |
561 } |
| 559 } else { |
562 w = g_utf8_to_utf16(value, -1, NULL, NULL, NULL); |
| 560 lstrcpy(_nicon_data.szTip, PIDGIN_NAME); |
563 wcsncpy(_nicon_data.szTip, w, sizeof(_nicon_data.szTip) / sizeof(wchar_t)); |
| 561 } |
564 g_free(w); |
| 562 Shell_NotifyIcon(NIM_MODIFY, &_nicon_data); |
565 Shell_NotifyIconW(NIM_MODIFY, &_nicon_data); |
| 563 } |
566 } |
| 564 |
567 |
| 565 static void winpidgin_tray_minimize(PidginBuddyList *gtkblist) { |
568 static void winpidgin_tray_minimize(PidginBuddyList *gtkblist) { |
| 566 MinimizeWndToTray(GDK_WINDOW_HWND(gtkblist->window->window)); |
569 MinimizeWndToTray(GDK_WINDOW_HWND(gtkblist->window->window)); |
| 567 } |
570 } |