Wait! Why use GDK-2 when there ate later stable versions you can download for free? Sometimes you use a tool – such as OpenCV – that integrates with GTK-2, and GDK-2.
Your operating system may allow you to create custom cursor, or mouse pointers, of your own with colors and an alpha channel (opacity). GDK allows you to create a cursor from a pixel buffer (pixbuf), using the function ‘gdk_cursor_new_from_pixbuf‘. OK, but first let’s make a pixel buffer. In the documentation of GDK 3, I found 2 functions to create a pixbuf: gdk_pixbuf_get_from_window and gdk_pixbuf_get_from_surface. The latter does not exist in GDK-2. However, there is one method, I haven’t found documented` It’s called gdk_pixbuf_new_from_data. You can get the data from Cairo after you’ve drawn your image using Cairo.
Using Cairo might be a bit confusing because::
- Cairo uses two data types for color channels: double-precision floating-point numbers and unsigned 8-bit integers.
- The color of the cursor is not as intended when calling ‘cairo_set_source_rgba’.
The following function in C will demonstrate what I mean:
Here, when the cursor is created its color is yellow, but if you save your created image to a file it will be cyan.



The image when saved to a PNG file
void createCursor(){ double arcEnd=2*M_PI; GdkPixbuf *pixbuf; int stride=cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, 10); // Will be used later, when we'll create the pixbuf. cairo_surface_t *surf=cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); // A canvas of width 10 and height 10. cairo_t *cairo_ctx = cairo_create(surf); cairo_set_source_rgba(cairo_ctx, 0., 1., 1., 1.); // Double precision values for Red, Green, Blue and Alpha channels between 0 and 1. cairo_arc(cairo_ctx,5,5,4,0,arcEnd); // Draw a circle or an arc of a circle whose center is at (5,5) and whose radius is 4 // The arc begins at angle 0 and ends in angle 2Π cairo_fill(cairo_ctx); // Fill the circle with cyan, though we've intended to create a yellow one. // Create an example image for the blog cairo_surface_write_to_png(surf, "/tmp/fortheblog.png"); guchar *data = cairo_image_surface_get_data(surf); // The data is in BGR, reverse order of RGB !!! pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, true, 8, 10, 10, stride, NULL, NULL); // Stride is the difference in bytes between two // consecutive rows. cursor=gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, 5, 5); }
“cursor” in this function is a global variable of type “GdkCursor *”.Now, to add the cursor to a window, use gdk_window_set_cursor.
The “gtk_pixbuf_new_from_data” Function.
This function uses the data returned from the function “cairo_image_surface_get_data”. The data is a pointer to a character. The function receiving the data doesn’t know how many characters are referred to, and how to split it into rows and columns. Following is its prototype:
GdkPixbuf *gdk_pixbuf_new_from_data (const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data);
One thought on “Creating Custom Cursors With GDK-Pixbuf-2 And Cairo”
Comments are closed.