1 /*
2 * Copyright (C) 2010 Collabora Ltd.
3 * Copyright (C) 2010 Igalia, S.L.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "GtkVersioning.h"
22
23 #include <gtk/gtk.h>
24
25 #if !GTK_CHECK_VERSION(2, 14, 0)
gtk_adjustment_set_value(GtkAdjustment * adjusment,gdouble value)26 void gtk_adjustment_set_value(GtkAdjustment* adjusment, gdouble value)
27 {
28 m_adjustment->value = m_currentPos;
29 gtk_adjustment_value_changed(m_adjustment);
30 }
31
gtk_adjustment_configure(GtkAdjustment * adjustment,gdouble value,gdouble lower,gdouble upper,gdouble stepIncrement,gdouble pageIncrement,gdouble pageSize)32 void gtk_adjustment_configure(GtkAdjustment* adjustment, gdouble value, gdouble lower, gdouble upper,
33 gdouble stepIncrement, gdouble pageIncrement, gdouble pageSize)
34 {
35 g_object_freeze_notify(G_OBJECT(adjustment));
36
37 g_object_set(adjustment,
38 "lower", lower,
39 "upper", upper,
40 "step-increment", stepIncrement,
41 "page-increment", pageIncrement,
42 "page-size", pageSize,
43 NULL);
44
45 g_object_thaw_notify(G_OBJECT(adjustment));
46
47 gtk_adjustment_changed(adjustment);
48 gtk_adjustment_value_changed(adjustment);
49 }
50 #endif
51
getDefaultGDKPointerDevice(GdkWindow * window)52 GdkDevice *getDefaultGDKPointerDevice(GdkWindow* window)
53 {
54 #ifndef GTK_API_VERSION_2
55 GdkDeviceManager *manager = gdk_display_get_device_manager(gdk_window_get_display(window));
56 return gdk_device_manager_get_client_pointer(manager);
57 #else
58 return gdk_device_get_core_pointer();
59 #endif // GTK_API_VERSION_2
60 }
61
62 #if !GTK_CHECK_VERSION(2, 17, 3)
gdk_window_get_root_coords(GdkWindow * window,gint x,gint y,gint * rootX,gint * rootY)63 void gdk_window_get_root_coords(GdkWindow* window, gint x, gint y, gint* rootX, gint* rootY)
64 {
65 gdk_window_get_root_origin(window, rootX, rootY);
66 *rootX = *rootX + x;
67 *rootY = *rootY + y;
68 }
69 #endif
70
blankCursor()71 GdkCursor * blankCursor()
72 {
73 #if GTK_CHECK_VERSION(2, 16, 0)
74 return gdk_cursor_new(GDK_BLANK_CURSOR);
75 #else
76 GdkCursor * cursor;
77 GdkPixmap * source;
78 GdkPixmap * mask;
79 GdkColor foreground = { 0, 65535, 0, 0 }; // Red.
80 GdkColor background = { 0, 0, 0, 65535 }; // Blue.
81 static gchar cursorBits[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
82
83 source = gdk_bitmap_create_from_data(0, cursorBits, 8, 8);
84 mask = gdk_bitmap_create_from_data(0, cursorBits, 8, 8);
85 cursor = gdk_cursor_new_from_pixmap(source, mask, &foreground, &background, 8, 8);
86 gdk_pixmap_unref(source);
87 gdk_pixmap_unref(mask);
88 return cursor;
89 #endif // GTK_CHECK_VERSION(2, 16, 0)
90 }
91
92 #if !GTK_CHECK_VERSION(2, 16, 0)
gtk_menu_item_get_label(GtkMenuItem * menuItem)93 const gchar* gtk_menu_item_get_label(GtkMenuItem* menuItem)
94 {
95 GtkWidget * label = gtk_bin_get_child(GTK_BIN(menuItem));
96 if (GTK_IS_LABEL(label))
97 return gtk_label_get_text(GTK_LABEL(label));
98 return 0;
99 }
100 #endif // GTK_CHECK_VERSION(2, 16, 0)
101
102 #ifdef GTK_API_VERSION_2
103 static cairo_format_t
gdk_cairo_format_for_content(cairo_content_t content)104 gdk_cairo_format_for_content(cairo_content_t content)
105 {
106 switch (content) {
107 case CAIRO_CONTENT_COLOR:
108 return CAIRO_FORMAT_RGB24;
109 case CAIRO_CONTENT_ALPHA:
110 return CAIRO_FORMAT_A8;
111 case CAIRO_CONTENT_COLOR_ALPHA:
112 default:
113 return CAIRO_FORMAT_ARGB32;
114 }
115 }
116
117 static cairo_surface_t*
gdk_cairo_surface_coerce_to_image(cairo_surface_t * surface,cairo_content_t content,int width,int height)118 gdk_cairo_surface_coerce_to_image(cairo_surface_t* surface,
119 cairo_content_t content,
120 int width,
121 int height)
122 {
123 cairo_surface_t * copy;
124 cairo_t * cr;
125
126 if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE
127 && cairo_surface_get_content(surface) == content
128 && cairo_image_surface_get_width(surface) >= width
129 && cairo_image_surface_get_height(surface) >= height)
130 return cairo_surface_reference(surface);
131
132 copy = cairo_image_surface_create(gdk_cairo_format_for_content(content),
133 width,
134 height);
135
136 cr = cairo_create(copy);
137 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
138 cairo_set_source_surface(cr, surface, 0, 0);
139 cairo_paint(cr);
140 cairo_destroy(cr);
141
142 return copy;
143 }
144
145 static void
convert_alpha(guchar * destData,int destStride,guchar * srcData,int srcStride,int srcX,int srcY,int width,int height)146 convert_alpha(guchar * destData, int destStride,
147 guchar * srcData, int srcStride,
148 int srcX, int srcY, int width, int height)
149 {
150 int x, y;
151
152 srcData += srcStride * srcY + srcY * 4;
153
154 for (y = 0; y < height; y++) {
155 guint32 * src = (guint32 *) srcData;
156
157 for (x = 0; x < width; x++) {
158 guint alpha = src[x] >> 24;
159
160 if (!alpha) {
161 destData[x * 4 + 0] = 0;
162 destData[x * 4 + 1] = 0;
163 destData[x * 4 + 2] = 0;
164 } else {
165 destData[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
166 destData[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
167 destData[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
168 }
169 destData[x * 4 + 3] = alpha;
170 }
171
172 srcData += srcStride;
173 destData += destStride;
174 }
175 }
176
177 static void
convert_no_alpha(guchar * destData,int destStride,guchar * srcData,int srcStride,int srcX,int srcY,int width,int height)178 convert_no_alpha(guchar * destData, int destStride, guchar * srcData,
179 int srcStride, int srcX, int srcY,
180 int width, int height)
181 {
182 int x, y;
183
184 srcData += srcStride * srcY + srcX * 4;
185
186 for (y = 0; y < height; y++) {
187 guint32 * src = (guint32 *) srcData;
188
189 for (x = 0; x < width; x++) {
190 destData[x * 3 + 0] = src[x] >> 16;
191 destData[x * 3 + 1] = src[x] >> 8;
192 destData[x * 3 + 2] = src[x];
193 }
194
195 srcData += srcStride;
196 destData += destStride;
197 }
198 }
199
200 /**
201 * gdk_pixbuf_get_from_surface:
202 * @surface: surface to copy from
203 * @src_x: Source X coordinate within @surface
204 * @src_y: Source Y coordinate within @surface
205 * @width: Width in pixels of region to get
206 * @height: Height in pixels of region to get
207 *
208 * Transfers image data from a #cairo_surface_t and converts it to an RGB(A)
209 * representation inside a #GdkPixbuf. This allows you to efficiently read
210 * individual pixels from cairo surfaces. For #GdkWindows, use
211 * gdk_pixbuf_get_from_window() instead.
212 *
213 * This function will create an RGB pixbuf with 8 bits per channel. The pixbuf
214 * will contain an alpha channel if the @surface contains one.
215 *
216 * Return value: (transfer full): A newly-created pixbuf with a reference count
217 * of 1, or %NULL on error
218 **/
219 GdkPixbuf*
gdk_pixbuf_get_from_surface(cairo_surface_t * surface,int srcX,int srcY,int width,int height)220 gdk_pixbuf_get_from_surface(cairo_surface_t * surface,
221 int srcX, int srcY,
222 int width, int height)
223 {
224 cairo_content_t content;
225 GdkPixbuf * dest;
226
227 /* General sanity checks */
228 g_return_val_if_fail(surface, NULL);
229 g_return_val_if_fail(srcX >= 0 && srcY >= 0, NULL);
230 g_return_val_if_fail(width > 0 && height > 0, NULL);
231
232 content = cairo_surface_get_content(surface) | CAIRO_CONTENT_COLOR;
233 dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
234 !!(content & CAIRO_CONTENT_ALPHA),
235 8,
236 width, height);
237
238 surface = gdk_cairo_surface_coerce_to_image(surface, content, srcX + width, srcY + height);
239 cairo_surface_flush(surface);
240 if (cairo_surface_status(surface) || !dest) {
241 cairo_surface_destroy(surface);
242 return NULL;
243 }
244
245 if (gdk_pixbuf_get_has_alpha(dest))
246 convert_alpha(gdk_pixbuf_get_pixels(dest),
247 gdk_pixbuf_get_rowstride(dest),
248 cairo_image_surface_get_data(surface),
249 cairo_image_surface_get_stride(surface),
250 srcX, srcY,
251 width, height);
252 else
253 convert_no_alpha(gdk_pixbuf_get_pixels(dest),
254 gdk_pixbuf_get_rowstride(dest),
255 cairo_image_surface_get_data(surface),
256 cairo_image_surface_get_stride(surface),
257 srcX, srcY,
258 width, height);
259
260 cairo_surface_destroy(surface);
261 return dest;
262 }
263
264 #endif // GTK_API_VERSION_2
265
266 #if !GLIB_CHECK_VERSION(2, 27, 1)
g_signal_accumulator_first_wins(GSignalInvocationHint * invocationHint,GValue * returnAccumulator,const GValue * handlerReturn,gpointer data)267 gboolean g_signal_accumulator_first_wins(GSignalInvocationHint *invocationHint, GValue *returnAccumulator, const GValue *handlerReturn, gpointer data)
268 {
269 g_value_copy(handlerReturn, returnAccumulator);
270 return FALSE;
271 }
272 #endif
273
274 #if !GTK_CHECK_VERSION(2, 22, 0)
gdk_window_create_similar_surface(GdkWindow * window,cairo_content_t content,int width,int height)275 cairo_surface_t *gdk_window_create_similar_surface(GdkWindow *window, cairo_content_t content, int width, int height)
276 {
277 cairo_t *cairoContext = gdk_cairo_create(window);
278 cairo_surface_t *cairoSurface = cairo_get_target(cairoContext);
279 cairo_surface_t *newSurface = cairo_surface_create_similar(cairoSurface, content, width, height);
280 cairo_destroy(cairoContext);
281 return newSurface;
282 }
283 #endif // GTK_CHECK_VERSION(2, 22, 0)
284