comparison pidgin/pidgintooltip.c @ 21947:c6b408d16011

merge of '791803b6696dd26a5193ad76f80dbc7c6cb2687a' and 'e7dd3b30ece9f95dd95249583812659312c457e6'
author Stu Tomlinson <stu@nosnilmot.com>
date Fri, 28 Dec 2007 02:49:23 +0000
parents 3fc5862b834a
children c38d72677c8a
comparison
equal deleted inserted replaced
21923:1981f277ab01 21947:c6b408d16011
41 41
42 typedef struct 42 typedef struct
43 { 43 {
44 GtkWidget *widget; 44 GtkWidget *widget;
45 gpointer userdata; 45 gpointer userdata;
46 PidginTooltipCreateForTree create_tooltip;
47 PidginTooltipPaint paint_tooltip; 46 PidginTooltipPaint paint_tooltip;
48 GtkTreePath *path; 47 union {
48 struct {
49 PidginTooltipCreateForTree create_tooltip;
50 GtkTreePath *path;
51 } treeview;
52 struct {
53 PidginTooltipCreate create_tooltip;
54 } widget;
55 } common;
49 } PidginTooltipData; 56 } PidginTooltipData;
50 57
51 static void 58 static void
52 destroy_tooltip_data(PidginTooltipData *data) 59 destroy_tooltip_data(PidginTooltipData *data)
53 { 60 {
54 gtk_tree_path_free(data->path); 61 gtk_tree_path_free(data->common.treeview.path);
55 g_free(data); 62 g_free(data);
56 } 63 }
57 64
58 void pidgin_tooltip_destroy() 65 void pidgin_tooltip_destroy()
59 { 66 {
68 } 75 }
69 76
70 static gboolean 77 static gboolean
71 pidgin_tooltip_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) 78 pidgin_tooltip_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
72 { 79 {
73 if (pidgin_tooltip.paint_tooltip) 80 if (pidgin_tooltip.paint_tooltip) {
81 gtk_paint_flat_box(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
82 NULL, widget, "tooltip", 0, 0, -1, -1);
74 pidgin_tooltip.paint_tooltip(widget, data); 83 pidgin_tooltip.paint_tooltip(widget, data);
84 }
75 return FALSE; 85 return FALSE;
76 } 86 }
77 87
78 static GtkWidget* 88 static GtkWidget*
79 setup_tooltip_window() 89 setup_tooltip_window()
182 } 192 }
183 193
184 static void 194 static void
185 reset_data_treepath(PidginTooltipData *data) 195 reset_data_treepath(PidginTooltipData *data)
186 { 196 {
187 gtk_tree_path_free(data->path); 197 gtk_tree_path_free(data->common.treeview.path);
188 data->path = NULL; 198 data->common.treeview.path = NULL;
189 } 199 }
190 200
191 static void 201 static void
192 pidgin_tooltip_draw(PidginTooltipData *data) 202 pidgin_tooltip_draw(PidginTooltipData *data)
203 {
204 GtkWidget *tipwindow;
205 int w, h;
206
207 pidgin_tooltip_destroy();
208
209 pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget);
210 pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window();
211 pidgin_tooltip.paint_tooltip = data->paint_tooltip;
212
213 if (!data->common.widget.create_tooltip(tipwindow, data->userdata, &w, &h)) {
214 if (tipwindow == pidgin_tooltip.tipwindow)
215 pidgin_tooltip_destroy();
216 return;
217 }
218
219 setup_tooltip_window_position(data->userdata, w, h);
220 }
221
222 static void
223 pidgin_tooltip_draw_tree(PidginTooltipData *data)
193 { 224 {
194 GtkWidget *tipwindow; 225 GtkWidget *tipwindow;
195 GtkTreePath *path = NULL; 226 GtkTreePath *path = NULL;
196 int w, h; 227 int w, h;
197 228
201 &path, NULL, NULL, NULL)) { 232 &path, NULL, NULL, NULL)) {
202 pidgin_tooltip_destroy(); 233 pidgin_tooltip_destroy();
203 return; 234 return;
204 } 235 }
205 236
206 if (data->path) { 237 if (data->common.treeview.path) {
207 if (gtk_tree_path_compare(data->path, path) == 0) { 238 if (gtk_tree_path_compare(data->common.treeview.path, path) == 0) {
208 gtk_tree_path_free(path); 239 gtk_tree_path_free(path);
209 return; 240 return;
210 } 241 }
211 gtk_tree_path_free(data->path); 242 gtk_tree_path_free(data->common.treeview.path);
212 data->path = NULL; 243 data->common.treeview.path = NULL;
213 } 244 }
214 245
215 pidgin_tooltip_destroy(); 246 pidgin_tooltip_destroy();
216 247
217 pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget); 248 pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget);
218 pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window(); 249 pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window();
219 pidgin_tooltip.paint_tooltip = data->paint_tooltip; 250 pidgin_tooltip.paint_tooltip = data->paint_tooltip;
220 251
221 if (!data->create_tooltip(tipwindow, path, data->userdata, &w, &h)) { 252 if (!data->common.treeview.create_tooltip(tipwindow, path, data->userdata, &w, &h)) {
222 pidgin_tooltip_destroy(); 253 if (tipwindow == pidgin_tooltip.tipwindow)
254 pidgin_tooltip_destroy();
223 gtk_tree_path_free(path); 255 gtk_tree_path_free(path);
224 return; 256 return;
225 } 257 }
226 258
227 setup_tooltip_window_position(data->userdata, w, h); 259 setup_tooltip_window_position(data->userdata, w, h);
228 260
229 data->path = path; 261 data->common.treeview.path = path;
230 g_signal_connect_swapped(G_OBJECT(tipwindow), "destroy", 262 g_signal_connect_swapped(G_OBJECT(pidgin_tooltip.tipwindow), "destroy",
231 G_CALLBACK(reset_data_treepath), data); 263 G_CALLBACK(reset_data_treepath), data);
232 } 264 }
233 265
234 static gboolean 266 static gboolean
235 pidgin_tooltip_timeout(gpointer data) 267 pidgin_tooltip_timeout(gpointer data)
236 { 268 {
269 PidginTooltipData *tdata = data;
237 pidgin_tooltip.timeout = 0; 270 pidgin_tooltip.timeout = 0;
238 pidgin_tooltip_draw(data); 271 if (GTK_IS_TREE_VIEW(tdata->widget))
272 pidgin_tooltip_draw_tree(data);
273 else
274 pidgin_tooltip_draw(data);
239 return FALSE; 275 return FALSE;
240 } 276 }
241 277
242 static gboolean 278 static gboolean
243 row_motion_cb(GtkWidget *tv, GdkEventMotion *event, gpointer userdata) 279 row_motion_cb(GtkWidget *tv, GdkEventMotion *event, gpointer userdata)
274 310
275 return FALSE; 311 return FALSE;
276 } 312 }
277 313
278 static gboolean 314 static gboolean
279 row_leave_cb(GtkWidget *tv, GdkEvent *event, gpointer userdata) 315 widget_leave_cb(GtkWidget *tv, GdkEvent *event, gpointer userdata)
280 { 316 {
281 pidgin_tooltip_destroy(); 317 pidgin_tooltip_destroy();
282 return FALSE; 318 return FALSE;
283 } 319 }
284 320
286 PidginTooltipCreateForTree create_tooltip, PidginTooltipPaint paint_tooltip) 322 PidginTooltipCreateForTree create_tooltip, PidginTooltipPaint paint_tooltip)
287 { 323 {
288 PidginTooltipData *tdata = g_new0(PidginTooltipData, 1); 324 PidginTooltipData *tdata = g_new0(PidginTooltipData, 1);
289 tdata->widget = tree; 325 tdata->widget = tree;
290 tdata->userdata = userdata; 326 tdata->userdata = userdata;
291 tdata->create_tooltip = create_tooltip; 327 tdata->common.treeview.create_tooltip = create_tooltip;
292 tdata->paint_tooltip = paint_tooltip; 328 tdata->paint_tooltip = paint_tooltip;
293 329
294 g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), tdata); 330 g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), tdata);
295 g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(row_leave_cb), NULL); 331 g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL);
296 g_signal_connect_swapped(G_OBJECT(tree), "destroy", G_CALLBACK(destroy_tooltip_data), tdata); 332 g_signal_connect_swapped(G_OBJECT(tree), "destroy", G_CALLBACK(destroy_tooltip_data), tdata);
297 return TRUE; 333 return TRUE;
298 } 334 }
299 335
336 static gboolean
337 widget_motion_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
338 {
339 int delay = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/tooltip_delay");
340
341 pidgin_tooltip_destroy();
342 if (delay == 0)
343 return FALSE;
344
345 pidgin_tooltip.timeout = g_timeout_add(delay, (GSourceFunc)pidgin_tooltip_timeout, data);
346 return FALSE;
347 }
348
349 gboolean pidgin_tooltip_setup_for_widget(GtkWidget *widget, gpointer userdata,
350 PidginTooltipCreate create_tooltip, PidginTooltipPaint paint_tooltip)
351 {
352 PidginTooltipData *wdata = g_new0(PidginTooltipData, 1);
353 wdata->widget = widget;
354 wdata->userdata = userdata;
355 wdata->common.widget.create_tooltip = create_tooltip;
356 wdata->paint_tooltip = paint_tooltip;
357
358 g_signal_connect(G_OBJECT(widget), "motion-notify-event", G_CALLBACK(widget_motion_cb), wdata);
359 g_signal_connect(G_OBJECT(widget), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL);
360 g_signal_connect_swapped(G_OBJECT(widget), "destroy", G_CALLBACK(g_free), wdata);
361 return TRUE;
362 }
363