summaryrefslogtreecommitdiffstats
path: root/vcl/unx/gtk/app/gtkdata.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/gtk/app/gtkdata.cxx')
-rw-r--r--vcl/unx/gtk/app/gtkdata.cxx75
1 files changed, 60 insertions, 15 deletions
diff --git a/vcl/unx/gtk/app/gtkdata.cxx b/vcl/unx/gtk/app/gtkdata.cxx
index 0a71ad01dab0..dde909ff27f2 100644
--- a/vcl/unx/gtk/app/gtkdata.cxx
+++ b/vcl/unx/gtk/app/gtkdata.cxx
@@ -333,25 +333,70 @@ long GtkSalDisplay::Dispatch( XEvent* pEvent )
return GDK_FILTER_CONTINUE;
}
-GdkCursor* GtkSalDisplay::getFromXPM( const unsigned char *pBitmap,
+#if GTK_CHECK_VERSION(3,0,0)
+namespace
+{
+ //cairo annoyingly won't take raw xbm data unless it fits
+ //the required cairo stride
+ unsigned char* ensurePaddedForCairo(const unsigned char *pXBM,
+ int nWidth, int nHeight, int nStride)
+ {
+ unsigned char *pPaddedXBM = const_cast<unsigned char*>(pXBM);
+
+ int bytes_per_row = (nWidth + 7) / 8;
+
+ if (nStride != bytes_per_row)
+ {
+ pPaddedXBM = new unsigned char[nStride * nHeight];
+ for (int row = 0; row < nHeight; ++row)
+ {
+ memcpy(pPaddedXBM + (nStride * row),
+ pXBM + (bytes_per_row * row), bytes_per_row);
+ memset(pPaddedXBM + (nStride * row) + bytes_per_row,
+ 0, nStride - bytes_per_row);
+ }
+ }
+
+ return pPaddedXBM;
+ }
+}
+#endif
+
+GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
const unsigned char *pMask,
int nWidth, int nHeight,
int nXHot, int nYHot )
{
#if GTK_CHECK_VERSION(3,0,0)
- g_warning ("FIXME: to use gdk_cursor_new_from_pixbuf instead of spiders");
- // We need to do something like:
- /*
- GdkPixbuf *pPix = gdk_pixbuf_new_from_xpm_data (pBitmap);
- GdkPixbuf *pMask = gdk_pixbuf_new_from_xpm_data (pMask);
-
- GdkCursor* gdk_cursor_new_from_pixbuf (GdkDisplay *display,
- GdkPixbuf *pixbuf,
- gint x,
- gint y);
- */
- return gdk_cursor_new_for_display (gdk_display_get_default(),
- GDK_SPIDER);
+ int cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, nWidth);
+
+ unsigned char *pPaddedXBM = ensurePaddedForCairo(pBitmap, nWidth, nHeight, cairo_stride);
+ cairo_surface_t *s = cairo_image_surface_create_for_data(
+ pPaddedXBM,
+ CAIRO_FORMAT_A1, nWidth, nHeight,
+ cairo_stride);
+
+ cairo_t *cr = cairo_create(s);
+ unsigned char *pPaddedMaskXBM = ensurePaddedForCairo(pMask, nWidth, nHeight, cairo_stride);
+ cairo_surface_t *mask = cairo_image_surface_create_for_data(
+ pPaddedMaskXBM,
+ CAIRO_FORMAT_A1, nWidth, nHeight,
+ cairo_stride);
+ cairo_mask_surface(cr, mask, 0, 0);
+ cairo_destroy(cr);
+ cairo_surface_destroy(mask);
+ if (pPaddedMaskXBM != pMask)
+ delete [] pPaddedMaskXBM;
+
+ GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, nWidth, nHeight);
+ cairo_surface_destroy(s);
+ if (pPaddedXBM != pBitmap)
+ delete [] pPaddedXBM;
+
+ GdkCursor *cursor = gdk_cursor_new_from_pixbuf(m_pGdkDisplay, pixbuf, nXHot, nYHot);
+ g_object_unref(pixbuf);
+
+ return cursor;
#else
GdkScreen *pScreen = gdk_display_get_default_screen( m_pGdkDisplay );
GdkDrawable *pDrawable = GDK_DRAWABLE( gdk_screen_get_root_window (pScreen) );
@@ -375,7 +420,7 @@ GdkCursor* GtkSalDisplay::getFromXPM( const unsigned char *pBitmap,
#define MAKE_CURSOR( vcl_name, name ) \
case vcl_name: \
- pCursor = getFromXPM( name##curs##_bits, name##mask##_bits, \
+ pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
name##curs_width, name##curs_height, \
name##curs_x_hot, name##curs_y_hot ); \
break