2
/* Ekiga -- A VoIP and Video-Conferencing application
3
* Copyright (C) 2000-2006 Damien Sandras
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20
* Ekiga is licensed under the GPL license and as a special exception,
21
* you have permission to link or otherwise combine this program with the
22
* programs OPAL, OpenH323 and PWLIB, and distribute the combination,
23
* without applying the requirements of the GNU GPL to the OPAL, OpenH323
24
* and PWLIB programs, as long as you do follow the requirements of the
25
* GNU GPL for all the rest of the software thus combined.
29
* Authors: Julien Puydt <jpuydt@free.fr>
33
* gmtray-win32.c - description
34
* ------------------------
35
* begin : Sat Jan 7 2002
36
* copyright : (C) 2000-2006 by Damien Sandras
37
* description : Win32 implementation of the tray
40
#define __GMTRAY_IMPLEMENTATION__
42
#include "../../../config.h"
46
#include "gmtray-internal.h"
48
#include "pixbuf_to_hicon.h"
50
struct _GmTraySpecific
52
NOTIFYICONDATA nid; /* this is the windows tray */
53
GtkWidget *stupid_platform; /* we need this widget we never show to render
54
* the icons in it... */
58
/* helper functions */
60
/* this function will hide the popup menu when triggered by a timer
61
* (this is because on win32, GTK+ doesn't hide a menu when the user goes
62
* away -- thanks to the gaim project for that nice workaround !)
65
popup_menu_hider (gpointer data)
67
g_return_val_if_fail (GTK_IS_MENU (data), FALSE);
69
gtk_menu_popdown (GTK_MENU (data));
75
/* this function checks if we leave/enter the popup menu, and decides to hide
76
* it after some time if needed (this is because on win32, GTK+ doesn't hide a
77
* menu when the user goes away -- thanks to the gaim project for that nice
81
popup_menu_leave_enter_callback (GtkWidget *menu,
82
GdkEventCrossing *event,
85
static guint timer = 0;
87
if (event->type == GDK_LEAVE_NOTIFY
88
&& event->detail == GDK_NOTIFY_ANCESTOR) {
90
/* user is going away ! */
92
timer = g_timeout_add (500, popup_menu_hider, (gpointer)menu);
94
} else if (event->type == GDK_ENTER_NOTIFY
95
&& event->detail == GDK_NOTIFY_ANCESTOR) {
97
/* wait ! Finally the user comes back ! */
100
(void)g_source_remove (timer);
106
/* this function receives events on the tray, and decides whether to call
107
* the click callback, show the menu or ignore
109
static LRESULT CALLBACK
110
message_handler (HWND hwnd,
117
tray = (GmTray *)wparam;
119
if (msg == WM_USER) {
121
if (lparam == WM_LBUTTONDOWN) {
123
if (tray->left_clicked_callback)
124
tray->left_clicked_callback (tray->left_clicked_callback_data);
125
} else if (lparam == WM_MBUTTONDOWN) {
127
if (tray->middle_clicked_callback)
128
tray->middle_clicked_callback (tray->middle_clicked_callback_data);
129
} else if (lparam == WM_RBUTTONDOWN) {
136
return DefWindowProc (hwnd, msg, wparam, lparam);
140
/* creates a sort of win32 event box, associated with
141
* our message callback function
144
create_message_window ()
148
HINSTANCE hmodule = GetModuleHandle (NULL);
150
memset (&wclass, 0, sizeof (WNDCLASS));
151
wclass.lpszClassName = PACKAGE_NAME "-tray";
152
wclass.lpfnWndProc = message_handler;
154
klass = RegisterClass (&wclass);
156
return CreateWindow (MAKEINTRESOURCE (klass), NULL, WS_POPUP,
157
0, 0, 1, 1, NULL, NULL,
163
/* public api implementation */
167
gmtray_new (const gchar *image)
169
GmTray *result = NULL;
170
GdkPixbuf *pixbuf = NULL;
171
GtkWidget *stupid = NULL;
173
stupid = gtk_label_new ("");
174
pixbuf = gtk_widget_render_icon (stupid, image,
175
GTK_ICON_SIZE_MENU, NULL);
177
result = gmtray_new_common (image);
179
result->specific = g_new (GmTraySpecific, 1);
181
result->specific->stupid_platform = stupid;
183
memset (&result->specific->nid, 0, sizeof (result->specific->nid));
184
result->specific->nid.hWnd = create_message_window ();
185
result->specific->nid.uID = GPOINTER_TO_UINT (result);
186
result->specific->nid.uCallbackMessage = WM_USER;
187
result->specific->nid.uFlags = NIF_ICON | NIF_MESSAGE;
188
result->specific->nid.hIcon = _gdk_win32_pixbuf_to_hicon (pixbuf);
190
Shell_NotifyIcon (NIM_ADD, &result->specific->nid);
192
g_object_unref (pixbuf);
199
gmtray_delete (GmTray *tray)
201
g_return_if_fail (tray != NULL);
203
gtk_widget_destroy (tray->specific->stupid_platform);
204
Shell_NotifyIcon (NIM_DELETE, &tray->specific->nid);
205
g_free (tray->specific);
206
gmtray_delete_common (tray);
211
gmtray_show_image (GmTray *tray,
214
GdkPixbuf *pixbuf = NULL;
216
g_return_if_fail (tray != NULL);
218
pixbuf = gtk_widget_render_icon (tray->specific->stupid_platform,
219
image, GTK_ICON_SIZE_MENU, NULL);
221
tray->specific->nid.hIcon = _gdk_win32_pixbuf_to_hicon (pixbuf);
222
tray->specific->nid.uFlags |= NIF_ICON;
224
Shell_NotifyIcon (NIM_MODIFY, &tray->specific->nid);
226
g_object_unref (pixbuf);
231
gmtray_menu (GmTray *tray)
233
GtkMenu *menu = NULL;
235
g_return_if_fail (tray != NULL);
237
if (tray->menu_callback == NULL)
240
menu = tray->menu_callback (tray->menu_callback_data);
242
gtk_widget_show_all (GTK_WIDGET (menu));
244
g_signal_connect (menu, "leave-notify-event",
245
G_CALLBACK(popup_menu_leave_enter_callback), NULL);
246
g_signal_connect (menu, "enter-notify-event",
247
G_CALLBACK(popup_menu_leave_enter_callback), NULL);
249
gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
250
0, gtk_get_current_event_time ());