+ GdkDisplay* display = gdk_drawable_get_display(gtk_widget_get_window(wxGetRootWindow()));
+ if (gdk_display_supports_cursor_color(display))
+ {
+ if (!image.HasAlpha())
+ {
+ // add alpha, so wxBitmap will convert to pixbuf format
+ image_copy.InitAlpha();
+ }
+ wxBitmap bitmap(image_copy);
+ wxASSERT(bitmap.HasPixbuf());
+ M_CURSORDATA->m_cursor = gdk_cursor_new_from_pixbuf
+ (
+ display,
+ bitmap.GetPixbuf(),
+ hotSpotX, hotSpotY
+ );
+ }
+ else // no colour cursor support
+ {
+ unsigned long keyMaskColor = 0;
+ GdkPixmap *maskRaw;
+ if (bHasMask)
+ {
+ keyMaskColor = wxImageHistogram::MakeKey(
+ image.GetMaskRed(), image.GetMaskGreen(), image.GetMaskBlue());
+ // get mask before image is modified
+ wxBitmap bitmap(image, 1);
+ maskRaw = bitmap.GetMask()->GetBitmap();
+ g_object_ref(maskRaw);
+ }
+ else
+ {
+ const int size = ((w + 7) / 8) * h;
+ char* bits = new char[size];
+ memset(bits, 0xff, size);
+ maskRaw = gdk_bitmap_create_from_data(
+ gtk_widget_get_window(wxGetRootWindow()), bits, w, h);
+ delete[] bits;
+ }
+
+ // assign the raw pointer to wxGtkObject to ensure it is unref'd later
+ wxGtkObject<GdkPixmap> mask(maskRaw);
+
+ // modify image so wxBitmap can be used to convert to pixmap
+ image_copy.SetMask(false);
+ wxByte* data = image_copy.GetData();
+ for (int j = 0; j < h; j++)
+ {
+ for (int i = 0; i < w; i++, data += 3)
+ {
+ // if average value of the pixel is > mid grey, convert it to
+ // background (0), otherwise to foreground (255, using wxBitmap
+ // convention)
+ data[0] =
+ data[1] =
+ data[2] = int(data[0]) + data[1] + data[2] >= 3 * 128 ? 0 : 255;
+ }
+ }
+ wxBitmap bitmap(image_copy, 1);
+
+ // find the most frequent color(s)
+ wxImageHistogram histogram;
+ image.ComputeHistogram(histogram);
+
+ long colMostFreq = 0;
+ unsigned long nMost = 0;
+ long colNextMostFreq = 0;
+ unsigned long nNext = 0;
+ for ( wxImageHistogram::iterator entry = histogram.begin();
+ entry != histogram.end();
+ ++entry )
+ {
+ unsigned long key = entry->first;
+ if ( !bHasMask || (key != keyMaskColor) )
+ {
+ unsigned long value = entry->second.value;
+ if (value > nMost)
+ {
+ nNext = nMost;
+ colNextMostFreq = colMostFreq;
+ nMost = value;
+ colMostFreq = key;
+ }
+ else if (value > nNext)
+ {
+ nNext = value;
+ colNextMostFreq = key;
+ }
+ }
+ }
+
+ wxColour fg = wxColour ( (unsigned char)(colMostFreq >> 16),
+ (unsigned char)(colMostFreq >> 8),
+ (unsigned char)(colMostFreq) );
+
+ wxColour bg = wxColour ( (unsigned char)(colNextMostFreq >> 16),
+ (unsigned char)(colNextMostFreq >> 8),
+ (unsigned char)(colNextMostFreq) );
+
+ int fg_intensity = fg.Red() + fg.Green() + fg.Blue();
+ int bg_intensity = bg.Red() + bg.Green() + bg.Blue();
+
+ if (bg_intensity > fg_intensity)
+ {
+ //swap fg and bg
+ wxColour tmp = fg;
+ fg = bg;
+ bg = tmp;
+ }
+
+ M_CURSORDATA->m_cursor = gdk_cursor_new_from_pixmap
+ (
+ bitmap.GetPixmap(),
+ mask,
+ fg.GetColor(), bg.GetColor(),
+ hotSpotX, hotSpotY
+ );
+ }