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) 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 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 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) 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 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) 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 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* 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 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 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* 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) 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) 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