| 219 } |
213 } |
| 220 |
214 |
| 221 static void |
215 static void |
| 222 reset_data_treepath(PidginTooltipData *data) |
216 reset_data_treepath(PidginTooltipData *data) |
| 223 { |
217 { |
| 224 gtk_tree_path_free(data->common.treeview.path); |
218 gtk_tree_path_free(data->path); |
| 225 data->common.treeview.path = NULL; |
219 data->path = NULL; |
| 226 } |
220 } |
| 227 |
221 |
| 228 static void |
222 static gboolean |
| 229 pidgin_tooltip_draw(PidginTooltipData *data) |
223 pidgin_tooltip_timeout(gpointer userdata) |
| 230 { |
224 { |
| 231 GtkWidget *tipwindow; |
225 PidginTooltipData *data = (PidginTooltipData *)userdata; |
| 232 int w, h; |
|
| 233 |
|
| 234 pidgin_tooltip_destroy(); |
|
| 235 |
|
| 236 pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget); |
|
| 237 pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window(); |
|
| 238 pidgin_tooltip.paint_tooltip = data->paint_tooltip; |
|
| 239 |
|
| 240 if (!data->common.widget.create_tooltip(tipwindow, data->userdata, &w, &h)) { |
|
| 241 if (tipwindow == pidgin_tooltip.tipwindow) |
|
| 242 pidgin_tooltip_destroy(); |
|
| 243 return; |
|
| 244 } |
|
| 245 |
|
| 246 setup_tooltip_window_position(data->userdata, w, h); |
|
| 247 } |
|
| 248 |
|
| 249 static void |
|
| 250 pidgin_tooltip_draw_tree(PidginTooltipData *data) |
|
| 251 { |
|
| 252 GtkWidget *tipwindow; |
226 GtkWidget *tipwindow; |
| 253 GtkTreePath *path = NULL; |
227 GtkTreePath *path = NULL; |
| 254 int w, h; |
228 int w, h; |
| |
229 |
| |
230 pidgin_tooltip.timeout = 0; |
| 255 |
231 |
| 256 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(data->widget), |
232 if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(data->widget), |
| 257 pidgin_tooltip.tip_rect.x, |
233 pidgin_tooltip.tip_rect.x, |
| 258 pidgin_tooltip.tip_rect.y + (pidgin_tooltip.tip_rect.height/2), |
234 pidgin_tooltip.tip_rect.y + (pidgin_tooltip.tip_rect.height/2), |
| 259 &path, NULL, NULL, NULL)) { |
235 &path, NULL, NULL, NULL)) { |
| 260 pidgin_tooltip_destroy(); |
236 pidgin_tooltip_destroy(); |
| 261 return; |
237 return FALSE; |
| 262 } |
238 } |
| 263 |
239 |
| 264 if (data->common.treeview.path) { |
240 if (data->path) { |
| 265 if (gtk_tree_path_compare(data->common.treeview.path, path) == 0) { |
241 if (gtk_tree_path_compare(data->path, path) == 0) { |
| 266 gtk_tree_path_free(path); |
242 gtk_tree_path_free(path); |
| 267 return; |
243 return FALSE; |
| 268 } |
244 } |
| 269 gtk_tree_path_free(data->common.treeview.path); |
245 gtk_tree_path_free(data->path); |
| 270 data->common.treeview.path = NULL; |
246 data->path = NULL; |
| 271 } |
247 } |
| 272 |
248 |
| 273 pidgin_tooltip_destroy(); |
249 pidgin_tooltip_destroy(); |
| 274 |
250 |
| 275 pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget); |
251 pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget); |
| 276 pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window(); |
252 pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window(); |
| 277 pidgin_tooltip.paint_tooltip = data->paint_tooltip; |
253 pidgin_tooltip.paint_tooltip = data->paint_tooltip; |
| 278 |
254 |
| 279 if (!data->common.treeview.create_tooltip(tipwindow, path, data->userdata, &w, &h)) { |
255 if (!data->create_tooltip(tipwindow, path, data->userdata, &w, &h)) { |
| 280 if (tipwindow == pidgin_tooltip.tipwindow) |
256 if (tipwindow == pidgin_tooltip.tipwindow) |
| 281 pidgin_tooltip_destroy(); |
257 pidgin_tooltip_destroy(); |
| 282 gtk_tree_path_free(path); |
258 gtk_tree_path_free(path); |
| 283 return; |
259 return FALSE; |
| 284 } |
260 } |
| 285 |
261 |
| 286 setup_tooltip_window_position(data->userdata, w, h); |
262 setup_tooltip_window_position(data->userdata, w, h); |
| 287 |
263 |
| 288 data->common.treeview.path = path; |
264 data->path = path; |
| 289 g_signal_connect_swapped(G_OBJECT(pidgin_tooltip.tipwindow), "destroy", |
265 g_signal_connect_swapped(G_OBJECT(pidgin_tooltip.tipwindow), "destroy", |
| 290 G_CALLBACK(reset_data_treepath), data); |
266 G_CALLBACK(reset_data_treepath), data); |
| 291 } |
267 |
| 292 |
|
| 293 static gboolean |
|
| 294 pidgin_tooltip_timeout(gpointer data) |
|
| 295 { |
|
| 296 PidginTooltipData *tdata = data; |
|
| 297 pidgin_tooltip.timeout = 0; |
|
| 298 if (GTK_IS_TREE_VIEW(tdata->widget)) |
|
| 299 pidgin_tooltip_draw_tree(data); |
|
| 300 else |
|
| 301 pidgin_tooltip_draw(data); |
|
| 302 return FALSE; |
268 return FALSE; |
| 303 } |
269 } |
| 304 |
270 |
| 305 static gboolean |
271 static gboolean |
| 306 row_motion_cb(GtkWidget *tv, GdkEventMotion *event, gpointer userdata) |
272 row_motion_cb(GtkWidget *tv, GdkEventMotion *event, gpointer userdata) |
| 347 PidginTooltipCreateForTree create_tooltip, PidginTooltipPaint paint_tooltip) |
313 PidginTooltipCreateForTree create_tooltip, PidginTooltipPaint paint_tooltip) |
| 348 { |
314 { |
| 349 PidginTooltipData *tdata = g_new0(PidginTooltipData, 1); |
315 PidginTooltipData *tdata = g_new0(PidginTooltipData, 1); |
| 350 tdata->widget = tree; |
316 tdata->widget = tree; |
| 351 tdata->userdata = userdata; |
317 tdata->userdata = userdata; |
| 352 tdata->common.treeview.create_tooltip = create_tooltip; |
318 tdata->create_tooltip = create_tooltip; |
| 353 tdata->paint_tooltip = paint_tooltip; |
319 tdata->paint_tooltip = paint_tooltip; |
| 354 |
320 |
| 355 g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), tdata); |
321 g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), tdata); |
| 356 g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL); |
322 g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL); |
| 357 g_signal_connect(G_OBJECT(tree), "scroll-event", G_CALLBACK(widget_leave_cb), NULL); |
323 g_signal_connect(G_OBJECT(tree), "scroll-event", G_CALLBACK(widget_leave_cb), NULL); |
| 358 g_signal_connect_swapped(G_OBJECT(tree), "destroy", G_CALLBACK(destroy_tooltip_data), tdata); |
324 g_signal_connect_swapped(G_OBJECT(tree), "destroy", G_CALLBACK(destroy_tooltip_data), tdata); |
| 359 return TRUE; |
325 return TRUE; |
| 360 } |
326 } |
| 361 |
|
| 362 static gboolean |
|
| 363 widget_motion_cb(GtkWidget *widget, GdkEvent *event, gpointer data) |
|
| 364 { |
|
| 365 initialize_tooltip_delay(); |
|
| 366 |
|
| 367 pidgin_tooltip_destroy(); |
|
| 368 if (!enable_tooltips) |
|
| 369 return FALSE; |
|
| 370 |
|
| 371 pidgin_tooltip.timeout = g_timeout_add(tooltip_delay, (GSourceFunc)pidgin_tooltip_timeout, data); |
|
| 372 return FALSE; |
|
| 373 } |
|
| 374 |
|
| 375 gboolean pidgin_tooltip_setup_for_widget(GtkWidget *widget, gpointer userdata, |
|
| 376 PidginTooltipCreate create_tooltip, PidginTooltipPaint paint_tooltip) |
|
| 377 { |
|
| 378 PidginTooltipData *wdata = g_new0(PidginTooltipData, 1); |
|
| 379 wdata->widget = widget; |
|
| 380 wdata->userdata = userdata; |
|
| 381 wdata->common.widget.create_tooltip = create_tooltip; |
|
| 382 wdata->paint_tooltip = paint_tooltip; |
|
| 383 |
|
| 384 g_signal_connect(G_OBJECT(widget), "motion-notify-event", G_CALLBACK(widget_motion_cb), wdata); |
|
| 385 g_signal_connect(G_OBJECT(widget), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL); |
|
| 386 g_signal_connect(G_OBJECT(widget), "scroll-event", G_CALLBACK(widget_leave_cb), NULL); |
|
| 387 g_signal_connect_swapped(G_OBJECT(widget), "destroy", G_CALLBACK(destroy_tooltip_data), wdata); |
|
| 388 return TRUE; |
|
| 389 } |
|
| 390 |
|