3 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or(at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
22 #include "gtkdnd-hints.h"
27 #include <gdk-pixbuf/gdk-pixbuf.h>
29 #include "gtk3compat.h"
41 * Info about each hint widget. See PidginDndHintWindowId enum.
43 static HintWindowInfo hint_windows
[] = {
44 { NULL
, "arrow-up.xpm", -13/2, 0 },
45 { NULL
, "arrow-down.xpm", -13/2, -16 },
46 { NULL
, "arrow-left.xpm", 0, -13/2 },
47 { NULL
, "arrow-right.xpm", -16, -13/2 },
52 dnd_hints_realized_cb(GtkWidget
*window
, GtkWidget
*pix
)
55 cairo_surface_t
*surface
;
56 cairo_region_t
*region
;
59 pixbuf
= gtk_image_get_pixbuf(GTK_IMAGE(pix
));
61 surface
= cairo_image_surface_create(CAIRO_FORMAT_A1
,
62 gdk_pixbuf_get_width(pixbuf
),
63 gdk_pixbuf_get_height(pixbuf
));
65 cr
= cairo_create(surface
);
66 gdk_cairo_set_source_pixbuf(cr
, pixbuf
, 0, 0);
70 region
= gdk_cairo_region_create_from_surface(surface
);
71 gtk_widget_shape_combine_region(window
, region
);
72 cairo_region_destroy(region
);
74 cairo_surface_destroy(surface
);
78 dnd_hints_init_window(const gchar
*fname
)
84 pixbuf
= gdk_pixbuf_new_from_file(fname
, NULL
);
85 g_return_val_if_fail(pixbuf
, NULL
);
87 win
= gtk_window_new(GTK_WINDOW_POPUP
);
88 pix
= gtk_image_new_from_pixbuf(pixbuf
);
89 gtk_container_add(GTK_CONTAINER(win
), pix
);
90 gtk_widget_show_all(pix
);
92 g_object_unref(G_OBJECT(pixbuf
));
94 g_signal_connect(G_OBJECT(win
), "realize",
95 G_CALLBACK(dnd_hints_realized_cb
), pix
);
101 get_widget_coords(GtkWidget
*w
, gint
*x1
, gint
*y1
, gint
*x2
, gint
*y2
)
103 gint ox
, oy
, width
, height
;
104 GtkWidget
*parent
= gtk_widget_get_parent(w
);
106 if (parent
&& gtk_widget_get_window(parent
) == gtk_widget_get_window(w
))
108 GtkAllocation allocation
;
110 gtk_widget_get_allocation(w
, &allocation
);
111 get_widget_coords(parent
, &ox
, &oy
, NULL
, NULL
);
112 height
= allocation
.height
;
113 width
= allocation
.width
;
117 GdkWindow
*win
= gtk_widget_get_window(w
);
118 gdk_window_get_origin(win
, &ox
, &oy
);
119 width
= gdk_window_get_width(win
);
120 height
= gdk_window_get_height(win
);
125 if (x2
) *x2
= ox
+ width
;
126 if (y2
) *y2
= oy
+ height
;
132 static gboolean done
= FALSE
;
140 for (i
= 0; hint_windows
[i
].filename
!= NULL
; i
++) {
143 fname
= g_build_filename(PURPLE_DATADIR
, "pixmaps", "pidgin",
144 hint_windows
[i
].filename
, NULL
);
146 hint_windows
[i
].widget
= dnd_hints_init_window(fname
);
153 pidgin_dnd_hints_hide_all(void)
157 for (i
= 0; hint_windows
[i
].filename
!= NULL
; i
++)
158 pidgin_dnd_hints_hide(i
);
162 pidgin_dnd_hints_hide(PidginDndHintWindowId i
)
164 GtkWidget
*w
= hint_windows
[i
].widget
;
166 if (w
&& GTK_IS_WIDGET(w
))
171 pidgin_dnd_hints_show(PidginDndHintWindowId id
, gint x
, gint y
)
177 w
= hint_windows
[id
].widget
;
179 if (w
&& GTK_IS_WIDGET(w
))
181 gtk_window_move(GTK_WINDOW(w
), hint_windows
[id
].ox
+ x
,
182 hint_windows
[id
].oy
+ y
);
188 pidgin_dnd_hints_show_relative(PidginDndHintWindowId id
, GtkWidget
*widget
,
189 PidginDndHintPosition horiz
, PidginDndHintPosition vert
)
193 GtkAllocation allocation
;
195 gtk_widget_get_allocation(widget
, &allocation
);
197 get_widget_coords(widget
, &x1
, &y1
, &x2
, &y2
);
198 x1
+= allocation
.x
; x2
+= allocation
.x
;
199 y1
+= allocation
.y
; y2
+= allocation
.y
;
203 case HINT_POSITION_RIGHT
: x
= x2
; break;
204 case HINT_POSITION_LEFT
: x
= x1
; break;
205 case HINT_POSITION_CENTER
: x
= (x1
+ x2
) / 2; break;
207 /* should not happen */
208 g_warning("Invalid parameter to pidgin_dnd_hints_show_relative");
214 case HINT_POSITION_TOP
: y
= y1
; break;
215 case HINT_POSITION_BOTTOM
: y
= y2
; break;
216 case HINT_POSITION_CENTER
: y
= (y1
+ y2
) / 2; break;
218 /* should not happen */
219 g_warning("Invalid parameter to pidgin_dnd_hints_show_relative");
223 pidgin_dnd_hints_show(id
, x
, y
);