Home | History | Annotate | Download | only in gtk
      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