From 9f556d1dd6a06524c0d5419862836b9f0e9e6e1d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 11 Feb 2007 03:02:34 +0000 Subject: [PATCH] added support for colour cursors in wxGTK (patch 1655576) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44462 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + docs/latex/wx/cursor.tex | 19 ++++++--- src/gtk/cursor.cpp | 86 ++++++++++++++++++++++++++++++++-------- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index f74cf55783..ce23d8298a 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -33,6 +33,7 @@ wxGTK: - wxTopLevelWindow::SetSizeHints size increments now work - wxTopLevelWindow::GetSize() returns the size including the WM decorations - wxTopLevelWindow::GetClientSize() returns 0x0 when the window is minimized +- Added support for colour cursors (Pascal Monasse) wxMSW: diff --git a/docs/latex/wx/cursor.tex b/docs/latex/wx/cursor.tex index 7a07cdd229..a6f8fceed5 100644 --- a/docs/latex/wx/cursor.tex +++ b/docs/latex/wx/cursor.tex @@ -74,13 +74,20 @@ Constructs a cursor using a cursor identifier. \func{}{wxCursor}{\param{const wxImage\&}{ image}} -Constructs a cursor from a wxImage. The cursor is monochrome, colors with the RGB elements all greater -than 127 will be foreground, colors less than this background. The mask (if any) will be used as transparent. +Constructs a cursor from a wxImage. If cursor are monochrome on the current +platform, colors with the RGB elements all greater than 127 will be foreground, +colors less than this background. The mask (if any) will be used to specify the +transparent area. -In MSW the foreground will be white and the background black. If the cursor is larger than 32x32 it is resized. -In GTK, the two most frequent colors will be used for foreground and background. The cursor will be displayed -at the size of the image. -On MacOS if the cursor is larger than 16x16 it is resized and currently only shown as black/white (mask respected). +In wxMSW the foreground will be white and the background black. If the cursor +is larger than 32x32 it is resized. + +In wxGTK, colour cursors and alpha channel are supported (starting from GTK+ +2.2). Otherwise the two most frequent colors will be used for foreground and +background. In any case, the cursor will be displayed at the size of the image. + +In wxMac, if the cursor is larger than 16x16 it is resized and currently only +shown as black/white (mask respected). \func{}{wxCursor}{\param{const wxCursor\&}{ cursor}} diff --git a/src/gtk/cursor.cpp b/src/gtk/cursor.cpp index aa71d2490f..56d699feb7 100644 --- a/src/gtk/cursor.cpp +++ b/src/gtk/cursor.cpp @@ -152,6 +152,24 @@ wxCursor::wxCursor(const char bits[], int width, int height, #if wxUSE_IMAGE +static void GetHotSpot(const wxImage& image, int& x, int& y) +{ + if (image.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X)) + x = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X); + else + x = 0; + + if (image.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y)) + y = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y); + else + y = 0; + + if (x < 0 || x >= image.GetWidth()) + x = 0; + if (y < 0 || y >= image.GetHeight()) + y = 0; +} + wxCursor::wxCursor( const wxImage & image ) { unsigned char * rgbBits = image.GetData(); @@ -160,6 +178,55 @@ wxCursor::wxCursor( const wxImage & image ) bool bHasMask = image.HasMask(); int imagebitcount = (w*h)/8; +#if GTK_CHECK_VERSION(2,2,0) + if ( gdk_display_supports_cursor_color(gdk_display_get_default()) ) + { + unsigned char rMask = 0, + gMask = 0, + bMask = 0; + if (bHasMask) + { + rMask = image.GetMaskRed(); + gMask = image.GetMaskGreen(); + bMask = image.GetMaskBlue(); + } + + GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, w, h); + unsigned char *alpha = image.HasAlpha() ? image.GetAlpha() : NULL; + unsigned char *out = gdk_pixbuf_get_pixels(pixbuf); + int rowpad = gdk_pixbuf_get_rowstride(pixbuf) - 4 * w; + for ( int y = 0; y < h; y++, out += rowpad ) + { + for ( int x = 0; x < w; x++, out += 4, rgbBits += 3 ) + { + out[0] = rgbBits[0]; + out[1] = rgbBits[1]; + out[2] = rgbBits[2]; + if (bHasMask && + out[0] == rMask && out[1] == gMask && out[2] == bMask) + out[3] = 0; + else + out[3] = alpha ? *alpha : 255; + if ( alpha ) + ++alpha; + } + } + + int hotSpotX, hotSpotY; + GetHotSpot(image, hotSpotX, hotSpotY); + + m_refData = new wxCursorRefData; + M_CURSORDATA->m_cursor = gdk_cursor_new_from_pixbuf + ( + gdk_display_get_default(), + pixbuf, + hotSpotX, hotSpotY + ); + g_object_unref (pixbuf); + return; + } +#endif // GTK+ 2.2+ + unsigned char * bits = new unsigned char [imagebitcount]; unsigned char * maskBits = new unsigned char [imagebitcount]; @@ -266,23 +333,8 @@ wxCursor::wxCursor( const wxImage & image ) bg = tmp; } - int hotSpotX; - int hotSpotY; - - if (image.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X)) - hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X); - else - hotSpotX = 0; - - if (image.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y)) - hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y); - else - hotSpotY = 0; - - if (hotSpotX < 0 || hotSpotX >= w) - hotSpotX = 0; - if (hotSpotY < 0 || hotSpotY >= h) - hotSpotY = 0; + int hotSpotX, hotSpotY; + GetHotSpot(image, hotSpotX, hotSpotY); GdkBitmap *data = gdk_bitmap_create_from_data(wxGetRootWindow()->window, (gchar *) bits, w, h); -- 2.45.2