1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  13 #include "wx/cursor.h" 
  17 #include "wx/gtk/private.h" //for idle stuff 
  22 //----------------------------------------------------------------------------- 
  24 //----------------------------------------------------------------------------- 
  26 class wxCursorRefData
: public wxObjectRefData
 
  36 wxCursorRefData::wxCursorRefData() 
  38     m_cursor 
= (GdkCursor 
*) NULL
; 
  41 wxCursorRefData::~wxCursorRefData() 
  43     if (m_cursor
) gdk_cursor_destroy( m_cursor 
); 
  46 //----------------------------------------------------------------------------- 
  48 #define M_CURSORDATA ((wxCursorRefData *)m_refData) 
  50 IMPLEMENT_DYNAMIC_CLASS(wxCursor
,wxObject
) 
  57 wxCursor::wxCursor( int cursorId 
) 
  59     m_refData 
= new wxCursorRefData(); 
  61     GdkCursorType gdk_cur 
= GDK_LEFT_PTR
; 
  66                 static const gchar bits
[] = { 0 }; 
  67                 static /* const -- not in GTK1 */ GdkColor color 
= { 0, 0, 0, 0 }; 
  69                 GdkPixmap 
*pixmap 
= gdk_bitmap_create_from_data(NULL
, bits
, 1, 1); 
  70                 M_CURSORDATA
->m_cursor 
= gdk_cursor_new_from_pixmap(pixmap
, 
  78         case wxCURSOR_ARROW
:            // fall through to default 
  79         case wxCURSOR_DEFAULT
:          gdk_cur 
= GDK_LEFT_PTR
; break; 
  80         case wxCURSOR_RIGHT_ARROW
:      gdk_cur 
= GDK_RIGHT_PTR
; break; 
  81         case wxCURSOR_HAND
:             gdk_cur 
= GDK_HAND1
; break; 
  82         case wxCURSOR_CROSS
:            gdk_cur 
= GDK_CROSSHAIR
; break; 
  83         case wxCURSOR_SIZEWE
:           gdk_cur 
= GDK_SB_H_DOUBLE_ARROW
; break; 
  84         case wxCURSOR_SIZENS
:           gdk_cur 
= GDK_SB_V_DOUBLE_ARROW
; break; 
  85         case wxCURSOR_ARROWWAIT
: 
  87         case wxCURSOR_WATCH
:            gdk_cur 
= GDK_WATCH
; break; 
  88         case wxCURSOR_SIZING
:           gdk_cur 
= GDK_SIZING
; break; 
  89         case wxCURSOR_SPRAYCAN
:         gdk_cur 
= GDK_SPRAYCAN
; break; 
  90         case wxCURSOR_IBEAM
:            gdk_cur 
= GDK_XTERM
; break; 
  91         case wxCURSOR_PENCIL
:           gdk_cur 
= GDK_PENCIL
; break; 
  92         case wxCURSOR_NO_ENTRY
:         gdk_cur 
= GDK_PIRATE
; break; 
  93         case wxCURSOR_SIZENWSE
: 
  94         case wxCURSOR_SIZENESW
:         gdk_cur 
= GDK_FLEUR
; break; 
  95         case wxCURSOR_QUESTION_ARROW
:   gdk_cur 
= GDK_QUESTION_ARROW
; break; 
  96         case wxCURSOR_PAINT_BRUSH
:      gdk_cur 
= GDK_SPRAYCAN
; break; 
  97         case wxCURSOR_MAGNIFIER
:        gdk_cur 
= GDK_PLUS
; break; 
  98         case wxCURSOR_CHAR
:             gdk_cur 
= GDK_XTERM
; break; 
  99         case wxCURSOR_LEFT_BUTTON
:      gdk_cur 
= GDK_LEFTBUTTON
; break; 
 100         case wxCURSOR_MIDDLE_BUTTON
:    gdk_cur 
= GDK_MIDDLEBUTTON
; break; 
 101         case wxCURSOR_RIGHT_BUTTON
:     gdk_cur 
= GDK_RIGHTBUTTON
; break; 
 102         case wxCURSOR_BULLSEYE
:         gdk_cur 
= GDK_TARGET
; break; 
 104         case wxCURSOR_POINT_LEFT
:       gdk_cur 
= GDK_SB_LEFT_ARROW
; break; 
 105         case wxCURSOR_POINT_RIGHT
:      gdk_cur 
= GDK_SB_RIGHT_ARROW
; break; 
 107         case wxCURSOR_DOUBLE_ARROW:     gdk_cur = GDK_DOUBLE_ARROW; break; 
 108         case wxCURSOR_CROSS_REVERSE:    gdk_cur = GDK_CROSS_REVERSE; break; 
 109         case wxCURSOR_BASED_ARROW_UP:   gdk_cur = GDK_BASED_ARROW_UP; break; 
 110         case wxCURSOR_BASED_ARROW_DOWN: gdk_cur = GDK_BASED_ARROW_DOWN; break; 
 114             wxFAIL_MSG(wxT("unsupported cursor type")); 
 115             // will use the standard one 
 119     M_CURSORDATA
->m_cursor 
= gdk_cursor_new( gdk_cur 
); 
 122 extern GtkWidget 
*wxGetRootWindow(); 
 124 wxCursor::wxCursor(const char bits
[], int width
, int  height
, 
 125                    int hotSpotX
, int hotSpotY
, 
 126                    const char maskBits
[], wxColour 
*fg
, wxColour 
*bg
) 
 134     if (hotSpotX 
< 0 || hotSpotX 
>= width
) 
 136     if (hotSpotY 
< 0 || hotSpotY 
>= height
) 
 139     GdkBitmap 
*data 
= gdk_bitmap_create_from_data( wxGetRootWindow()->window
, (gchar 
*) bits
, width
, height 
); 
 140     GdkBitmap 
*mask 
= gdk_bitmap_create_from_data( wxGetRootWindow()->window
, (gchar 
*) maskBits
, width
, height
); 
 142     m_refData 
= new wxCursorRefData
; 
 143     M_CURSORDATA
->m_cursor 
= gdk_cursor_new_from_pixmap( 
 144                  data
, mask
, fg
->GetColor(), bg
->GetColor(), 
 145                  hotSpotX
, hotSpotY 
); 
 147     gdk_bitmap_unref( data 
); 
 148     gdk_bitmap_unref( mask 
); 
 153 wxCursor::wxCursor( const wxImage 
& image 
) 
 155     unsigned char * rgbBits 
= image
.GetData(); 
 156     int w 
= image
.GetWidth() ; 
 157     int h 
= image
.GetHeight(); 
 158     bool bHasMask 
= image
.HasMask(); 
 159     int imagebitcount 
= (w
*h
)/8; 
 161     unsigned char * bits 
= new unsigned char [imagebitcount
]; 
 162     unsigned char * maskBits 
= new unsigned char [imagebitcount
]; 
 164     int i
, j
, i8
; unsigned char c
, cMask
; 
 165     for (i
=0; i
<imagebitcount
; i
++) 
 173             // possible overflow if we do the summation first ? 
 174             c 
= rgbBits
[(i8
+j
)*3]/3 + rgbBits
[(i8
+j
)*3+1]/3 + rgbBits
[(i8
+j
)*3+2]/3; 
 175             //if average value is > mid grey 
 177                 bits
[i
] = bits
[i
] | cMask
; 
 182     unsigned long keyMaskColor
; 
 186             r 
= image
.GetMaskRed(), 
 187             g 
= image
.GetMaskGreen(), 
 188             b 
= image
.GetMaskBlue(); 
 190         for (i
=0; i
<imagebitcount
; i
++) 
 198                 if (rgbBits
[(i8
+j
)*3] != r 
|| rgbBits
[(i8
+j
)*3+1] != g 
|| rgbBits
[(i8
+j
)*3+2] != b
) 
 199                     maskBits
[i
] = maskBits
[i
] | cMask
; 
 204         keyMaskColor 
= (r 
<< 16) | (g 
<< 8) | b
; 
 208         for (i
=0; i
<imagebitcount
; i
++) 
 211         // init it to avoid compiler warnings 
 215     // find the most frequent color(s) 
 216     wxImageHistogram histogram
; 
 217     image
.ComputeHistogram(histogram
); 
 223     long colMostFreq 
= 0; 
 224     unsigned long nMost 
= 0; 
 225     long colNextMostFreq 
= 0; 
 226     unsigned long nNext 
= 0; 
 227     for ( wxImageHistogram::iterator entry 
= histogram
.begin(); 
 228           entry 
!= histogram
.end(); 
 231         value 
= entry
->second
.value
; 
 233         if ( !bHasMask 
|| (key 
!= keyMaskColor
) ) 
 240             else if (value 
> nNext
) 
 243                 colNextMostFreq 
= key
; 
 248     wxColour fg 
= wxColour ( (unsigned char)(colMostFreq 
>> 16), 
 249                              (unsigned char)(colMostFreq 
>> 8), 
 250                              (unsigned char)(colMostFreq
) ); 
 252     wxColour bg 
= wxColour ( (unsigned char)(colNextMostFreq 
>> 16), 
 253                              (unsigned char)(colNextMostFreq 
>> 8), 
 254                              (unsigned char)(colNextMostFreq
) ); 
 256     int fg_intensity 
= fg
.Red() + fg
.Green() + fg
.Blue(); 
 257     int bg_intensity 
= bg
.Red() + bg
.Green() + bg
.Blue(); 
 259     if (bg_intensity 
> fg_intensity
) 
 270     if (image
.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X
)) 
 271         hotSpotX 
= image
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X
); 
 275     if (image
.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y
)) 
 276         hotSpotY 
= image
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y
); 
 280     if (hotSpotX 
< 0 || hotSpotX 
>= w
) 
 282     if (hotSpotY 
< 0 || hotSpotY 
>= h
) 
 285     GdkBitmap 
*data 
= gdk_bitmap_create_from_data(wxGetRootWindow()->window
, 
 286                                                   (gchar 
*) bits
, w
, h
); 
 287     GdkBitmap 
*mask 
= gdk_bitmap_create_from_data(wxGetRootWindow()->window
, 
 288                                                   (gchar 
*) maskBits
, w
, h
); 
 290     m_refData 
= new wxCursorRefData
; 
 291     M_CURSORDATA
->m_cursor 
= gdk_cursor_new_from_pixmap
 
 295                                 fg
.GetColor(), bg
.GetColor(), 
 299     gdk_bitmap_unref( data 
); 
 300     gdk_bitmap_unref( mask 
); 
 305 #endif // wxUSE_IMAGE 
 307 wxCursor::~wxCursor() 
 311 bool wxCursor::operator == ( const wxCursor
& cursor 
) const 
 313     return m_refData 
== cursor
.m_refData
; 
 316 bool wxCursor::operator != ( const wxCursor
& cursor 
) const 
 318     return m_refData 
!= cursor
.m_refData
; 
 321 bool wxCursor::Ok() const 
 323     return (m_refData 
!= NULL
); 
 326 GdkCursor 
*wxCursor::GetCursor() const 
 328     return M_CURSORDATA
->m_cursor
; 
 331 //----------------------------------------------------------------------------- 
 332 // busy cursor routines 
 333 //----------------------------------------------------------------------------- 
 335 extern wxCursor g_globalCursor
; 
 337 static wxCursor  gs_savedCursor
; 
 338 static int       gs_busyCount 
= 0; 
 340 const wxCursor 
&wxBusyCursor::GetStoredCursor() 
 342     return gs_savedCursor
; 
 345 const wxCursor 
wxBusyCursor::GetBusyCursor() 
 347     return wxCursor(wxCURSOR_WATCH
); 
 350 void wxEndBusyCursor() 
 352     if (--gs_busyCount 
> 0) 
 355     wxSetCursor( gs_savedCursor 
); 
 356     gs_savedCursor 
= wxNullCursor
; 
 359         wxTheApp
->ProcessIdle(); 
 362 void wxBeginBusyCursor( wxCursor 
*WXUNUSED(cursor
) ) 
 364     if (gs_busyCount
++ > 0) 
 367     wxASSERT_MSG( !gs_savedCursor
.Ok(), 
 368                   wxT("forgot to call wxEndBusyCursor, will leak memory") ); 
 370     gs_savedCursor 
= g_globalCursor
; 
 372     wxSetCursor( wxCursor(wxCURSOR_WATCH
) ); 
 375         wxTheApp
->ProcessIdle(); 
 382     return gs_busyCount 
> 0; 
 385 void wxSetCursor( const wxCursor
& cursor 
) 
 388         wxapp_install_idle_handler(); 
 390     g_globalCursor 
= cursor
;