1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/cursor.cpp 
   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" 
  23 //----------------------------------------------------------------------------- 
  25 //----------------------------------------------------------------------------- 
  27 extern void wxapp_install_idle_handler(); 
  30 //----------------------------------------------------------------------------- 
  32 //----------------------------------------------------------------------------- 
  34 class wxCursorRefData
: public wxObjectRefData
 
  44 wxCursorRefData::wxCursorRefData() 
  46     m_cursor 
= (GdkCursor 
*) NULL
; 
  49 wxCursorRefData::~wxCursorRefData() 
  51     if (m_cursor
) gdk_cursor_destroy( m_cursor 
); 
  54 //----------------------------------------------------------------------------- 
  56 #define M_CURSORDATA ((wxCursorRefData *)m_refData) 
  58 IMPLEMENT_DYNAMIC_CLASS(wxCursor
,wxObject
) 
  65 wxCursor::wxCursor( int cursorId 
) 
  67     m_refData 
= new wxCursorRefData(); 
  69     GdkCursorType gdk_cur 
= GDK_LEFT_PTR
; 
  74                 static const gchar bits
[] = { 0 }; 
  75                 static /* const -- not in GTK1 */ GdkColor color 
= { 0, 0, 0, 0 }; 
  77                 GdkPixmap 
*pixmap 
= gdk_bitmap_create_from_data(NULL
, bits
, 1, 1); 
  78                 M_CURSORDATA
->m_cursor 
= gdk_cursor_new_from_pixmap(pixmap
, 
  86         case wxCURSOR_ARROW
:            // fall through to default 
  87         case wxCURSOR_DEFAULT
:          gdk_cur 
= GDK_LEFT_PTR
; break; 
  88         case wxCURSOR_RIGHT_ARROW
:      gdk_cur 
= GDK_RIGHT_PTR
; break; 
  89         case wxCURSOR_HAND
:             gdk_cur 
= GDK_HAND1
; break; 
  90         case wxCURSOR_CROSS
:            gdk_cur 
= GDK_CROSSHAIR
; break; 
  91         case wxCURSOR_SIZEWE
:           gdk_cur 
= GDK_SB_H_DOUBLE_ARROW
; break; 
  92         case wxCURSOR_SIZENS
:           gdk_cur 
= GDK_SB_V_DOUBLE_ARROW
; break; 
  93         case wxCURSOR_ARROWWAIT
: 
  95         case wxCURSOR_WATCH
:            gdk_cur 
= GDK_WATCH
; break; 
  96         case wxCURSOR_SIZING
:           gdk_cur 
= GDK_SIZING
; break; 
  97         case wxCURSOR_SPRAYCAN
:         gdk_cur 
= GDK_SPRAYCAN
; break; 
  98         case wxCURSOR_IBEAM
:            gdk_cur 
= GDK_XTERM
; break; 
  99         case wxCURSOR_PENCIL
:           gdk_cur 
= GDK_PENCIL
; break; 
 100         case wxCURSOR_NO_ENTRY
:         gdk_cur 
= GDK_PIRATE
; break; 
 101         case wxCURSOR_SIZENWSE
: 
 102         case wxCURSOR_SIZENESW
:         gdk_cur 
= GDK_FLEUR
; break; 
 103         case wxCURSOR_QUESTION_ARROW
:   gdk_cur 
= GDK_QUESTION_ARROW
; break; 
 104         case wxCURSOR_PAINT_BRUSH
:      gdk_cur 
= GDK_SPRAYCAN
; break; 
 105         case wxCURSOR_MAGNIFIER
:        gdk_cur 
= GDK_PLUS
; break; 
 106         case wxCURSOR_CHAR
:             gdk_cur 
= GDK_XTERM
; break; 
 107         case wxCURSOR_LEFT_BUTTON
:      gdk_cur 
= GDK_LEFTBUTTON
; break; 
 108         case wxCURSOR_MIDDLE_BUTTON
:    gdk_cur 
= GDK_MIDDLEBUTTON
; break; 
 109         case wxCURSOR_RIGHT_BUTTON
:     gdk_cur 
= GDK_RIGHTBUTTON
; break; 
 110         case wxCURSOR_BULLSEYE
:         gdk_cur 
= GDK_TARGET
; break; 
 112         case wxCURSOR_POINT_LEFT
:       gdk_cur 
= GDK_SB_LEFT_ARROW
; break; 
 113         case wxCURSOR_POINT_RIGHT
:      gdk_cur 
= GDK_SB_RIGHT_ARROW
; break; 
 115         case wxCURSOR_DOUBLE_ARROW:     gdk_cur = GDK_DOUBLE_ARROW; break; 
 116         case wxCURSOR_CROSS_REVERSE:    gdk_cur = GDK_CROSS_REVERSE; break; 
 117         case wxCURSOR_BASED_ARROW_UP:   gdk_cur = GDK_BASED_ARROW_UP; break; 
 118         case wxCURSOR_BASED_ARROW_DOWN: gdk_cur = GDK_BASED_ARROW_DOWN; break; 
 122             wxFAIL_MSG(wxT("unsupported cursor type")); 
 123             // will use the standard one 
 127     M_CURSORDATA
->m_cursor 
= gdk_cursor_new( gdk_cur 
); 
 130 extern GtkWidget 
*wxGetRootWindow(); 
 132 wxCursor::wxCursor(const char bits
[], int width
, int  height
, 
 133                    int hotSpotX
, int hotSpotY
, 
 134                    const char maskBits
[], const wxColour 
*fg
, const wxColour 
*bg
) 
 142     if (hotSpotX 
< 0 || hotSpotX 
>= width
) 
 144     if (hotSpotY 
< 0 || hotSpotY 
>= height
) 
 147     GdkBitmap 
*data 
= gdk_bitmap_create_from_data( wxGetRootWindow()->window
, (gchar 
*) bits
, width
, height 
); 
 148     GdkBitmap 
*mask 
= gdk_bitmap_create_from_data( wxGetRootWindow()->window
, (gchar 
*) maskBits
, width
, height
); 
 150     m_refData 
= new wxCursorRefData
; 
 151     M_CURSORDATA
->m_cursor 
= gdk_cursor_new_from_pixmap( 
 152                  data
, mask
, fg
->GetColor(), bg
->GetColor(), 
 153                  hotSpotX
, hotSpotY 
); 
 155     gdk_bitmap_unref( data 
); 
 156     gdk_bitmap_unref( mask 
); 
 161 wxCursor::wxCursor( const wxImage 
& image 
) 
 163     unsigned char * rgbBits 
= image
.GetData(); 
 164     int w 
= image
.GetWidth() ; 
 165     int h 
= image
.GetHeight(); 
 166     bool bHasMask 
= image
.HasMask(); 
 167     int imagebitcount 
= (w
*h
)/8; 
 169     unsigned char * bits 
= new unsigned char [imagebitcount
]; 
 170     unsigned char * maskBits 
= new unsigned char [imagebitcount
]; 
 172     int i
, j
, i8
; unsigned char c
, cMask
; 
 173     for (i
=0; i
<imagebitcount
; i
++) 
 181             // possible overflow if we do the summation first ? 
 182             c 
= rgbBits
[(i8
+j
)*3]/3 + rgbBits
[(i8
+j
)*3+1]/3 + rgbBits
[(i8
+j
)*3+2]/3; 
 183             //if average value is > mid grey 
 185                 bits
[i
] = bits
[i
] | cMask
; 
 190     unsigned long keyMaskColor
; 
 194             r 
= image
.GetMaskRed(), 
 195             g 
= image
.GetMaskGreen(), 
 196             b 
= image
.GetMaskBlue(); 
 198         for (i
=0; i
<imagebitcount
; i
++) 
 206                 if (rgbBits
[(i8
+j
)*3] != r 
|| rgbBits
[(i8
+j
)*3+1] != g 
|| rgbBits
[(i8
+j
)*3+2] != b
) 
 207                     maskBits
[i
] = maskBits
[i
] | cMask
; 
 212         keyMaskColor 
= (r 
<< 16) | (g 
<< 8) | b
; 
 216         for (i
=0; i
<imagebitcount
; i
++) 
 219         // init it to avoid compiler warnings 
 223     // find the most frequent color(s) 
 224     wxImageHistogram histogram
; 
 225     image
.ComputeHistogram(histogram
); 
 231     long colMostFreq 
= 0; 
 232     unsigned long nMost 
= 0; 
 233     long colNextMostFreq 
= 0; 
 234     unsigned long nNext 
= 0; 
 235     for ( wxImageHistogram::iterator entry 
= histogram
.begin(); 
 236           entry 
!= histogram
.end(); 
 239         value 
= entry
->second
.value
; 
 241         if ( !bHasMask 
|| (key 
!= keyMaskColor
) ) 
 248             else if (value 
> nNext
) 
 251                 colNextMostFreq 
= key
; 
 256     wxColour fg 
= wxColour ( (unsigned char)(colMostFreq 
>> 16), 
 257                              (unsigned char)(colMostFreq 
>> 8), 
 258                              (unsigned char)(colMostFreq
) ); 
 260     wxColour bg 
= wxColour ( (unsigned char)(colNextMostFreq 
>> 16), 
 261                              (unsigned char)(colNextMostFreq 
>> 8), 
 262                              (unsigned char)(colNextMostFreq
) ); 
 264     int fg_intensity 
= fg
.Red() + fg
.Green() + fg
.Blue(); 
 265     int bg_intensity 
= bg
.Red() + bg
.Green() + bg
.Blue(); 
 267     if (bg_intensity 
> fg_intensity
) 
 278     if (image
.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X
)) 
 279         hotSpotX 
= image
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X
); 
 283     if (image
.HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y
)) 
 284         hotSpotY 
= image
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y
); 
 288     if (hotSpotX 
< 0 || hotSpotX 
>= w
) 
 290     if (hotSpotY 
< 0 || hotSpotY 
>= h
) 
 293     GdkBitmap 
*data 
= gdk_bitmap_create_from_data(wxGetRootWindow()->window
, 
 294                                                   (gchar 
*) bits
, w
, h
); 
 295     GdkBitmap 
*mask 
= gdk_bitmap_create_from_data(wxGetRootWindow()->window
, 
 296                                                   (gchar 
*) maskBits
, w
, h
); 
 298     m_refData 
= new wxCursorRefData
; 
 299     M_CURSORDATA
->m_cursor 
= gdk_cursor_new_from_pixmap
 
 303                                 fg
.GetColor(), bg
.GetColor(), 
 307     gdk_bitmap_unref( data 
); 
 308     gdk_bitmap_unref( mask 
); 
 313 #endif // wxUSE_IMAGE 
 315 wxCursor::~wxCursor() 
 319 bool wxCursor::operator == ( const wxCursor
& cursor 
) const 
 321     return m_refData 
== cursor
.m_refData
; 
 324 bool wxCursor::operator != ( const wxCursor
& cursor 
) const 
 326     return m_refData 
!= cursor
.m_refData
; 
 329 bool wxCursor::Ok() const 
 331     return (m_refData 
!= NULL
); 
 334 GdkCursor 
*wxCursor::GetCursor() const 
 336     return M_CURSORDATA
->m_cursor
; 
 339 //----------------------------------------------------------------------------- 
 340 // busy cursor routines 
 341 //----------------------------------------------------------------------------- 
 343 extern wxCursor g_globalCursor
; 
 345 static wxCursor  gs_savedCursor
; 
 346 static int       gs_busyCount 
= 0; 
 348 const wxCursor 
&wxBusyCursor::GetStoredCursor() 
 350     return gs_savedCursor
; 
 353 const wxCursor 
wxBusyCursor::GetBusyCursor() 
 355     return wxCursor(wxCURSOR_WATCH
); 
 358 void wxEndBusyCursor() 
 360     if (--gs_busyCount 
> 0) 
 363     wxSetCursor( gs_savedCursor 
); 
 364     gs_savedCursor 
= wxNullCursor
; 
 367         wxTheApp
->ProcessIdle(); 
 370 void wxBeginBusyCursor( const wxCursor 
*WXUNUSED(cursor
) ) 
 372     if (gs_busyCount
++ > 0) 
 375     wxASSERT_MSG( !gs_savedCursor
.Ok(), 
 376                   wxT("forgot to call wxEndBusyCursor, will leak memory") ); 
 378     gs_savedCursor 
= g_globalCursor
; 
 380     wxSetCursor( wxCursor(wxCURSOR_WATCH
) ); 
 383         wxTheApp
->ProcessIdle(); 
 390     return gs_busyCount 
> 0; 
 393 void wxSetCursor( const wxCursor
& cursor 
) 
 396         wxapp_install_idle_handler(); 
 398     g_globalCursor 
= cursor
;