1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxCursor class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "cursor.h"
16 #include "wx/cursor.h"
17 #include "wx/gdicmn.h"
23 #pragma message disable nosimpint
26 #include <X11/cursorfont.h>
28 #pragma message enable nosimpint
31 #include "wx/motif/private.h"
33 IMPLEMENT_DYNAMIC_CLASS(wxCursor
, wxBitmap
)
34 IMPLEMENT_DYNAMIC_CLASS(wxXCursor
, wxObject
)
36 wxCursorRefData::wxCursorRefData()
38 m_width
= 32; m_height
= 32;
39 m_cursorId
= wxCURSOR_NONE
;
42 wxCursorRefData::~wxCursorRefData()
44 wxNode
* node
= m_cursors
.First();
47 wxXCursor
* c
= (wxXCursor
*) node
->Data();
48 // TODO: how to delete cursor?
49 // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ??
59 wxCursor::wxCursor(const char bits
[], int width
, int height
,
60 int hotSpotX
, int hotSpotY
, const char maskBits
[])
62 m_refData
= new wxCursorRefData
;
64 Display
*dpy
= (Display
*) wxGetDisplay();
65 int screen_num
= DefaultScreen (dpy
);
67 Pixmap pixmap
= XCreatePixmapFromBitmapData (dpy
,
68 RootWindow (dpy
, DefaultScreen(dpy
)),
69 (char*) bits
, width
, height
,
72 Pixmap mask_pixmap
= None
;
75 mask_pixmap
= XCreatePixmapFromBitmapData (dpy
,
76 RootWindow (dpy
, DefaultScreen(dpy
)),
77 (char*) maskBits
, width
, height
,
81 XColor foreground_color
;
82 XColor background_color
;
83 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
84 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
85 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
86 XQueryColor(dpy
, cmap
, &foreground_color
);
87 XQueryColor(dpy
, cmap
, &background_color
);
89 Cursor cursor
= XCreatePixmapCursor (dpy
,
97 XFreePixmap( dpy
, pixmap
);
98 if (mask_pixmap
!= None
)
100 XFreePixmap( dpy
, mask_pixmap
);
105 wxXCursor
*c
= new wxXCursor
;
107 c
->m_cursor
= (WXCursor
) cursor
;
108 c
->m_display
= (WXDisplay
*) dpy
;
109 M_CURSORDATA
->m_cursors
.Append(c
);
110 M_CURSORDATA
->m_ok
= TRUE
;
114 M_CURSORDATA
->m_ok
= TRUE
;
118 wxCursor::wxCursor(const wxString
& name
, long flags
, int hotSpotX
, int hotSpotY
)
120 // Must be an XBM file
121 if (flags
!= wxBITMAP_TYPE_XBM
)
124 m_refData
= new wxCursorRefData
;
126 int hotX
= -1, hotY
= -1;
130 Display
*dpy
= (Display
*) wxGetDisplay();
131 int screen_num
= DefaultScreen (dpy
);
133 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
134 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
136 M_BITMAPDATA
->m_width
= w
;
137 M_BITMAPDATA
->m_height
= h
;
138 M_BITMAPDATA
->m_depth
= 1;
140 if ((value
== BitmapFileInvalid
) ||
141 (value
== BitmapOpenFailed
) ||
142 (value
== BitmapNoMemory
))
147 XColor foreground_color
;
148 XColor background_color
;
149 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
150 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
151 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
152 XQueryColor(dpy
, cmap
, &foreground_color
);
153 XQueryColor(dpy
, cmap
, &background_color
);
155 // TODO: how do we determine whether hotX, hotY were read correctly?
156 if (hotX
< 0 || hotY
< 0)
161 if (hotX
< 0 || hotY
< 0)
167 Pixmap mask_pixmap
= None
;
168 Cursor cursor
= XCreatePixmapCursor (dpy
,
176 XFreePixmap( dpy
, pixmap
);
179 wxXCursor
*c
= new wxXCursor
;
181 c
->m_cursor
= (WXCursor
) cursor
;
182 c
->m_display
= (WXDisplay
*) dpy
;
183 M_CURSORDATA
->m_cursors
.Append(c
);
184 M_CURSORDATA
->m_ok
= TRUE
;
190 // Cursors by stock number
191 wxCursor::wxCursor(wxStockCursor id
)
193 m_refData
= new wxCursorRefData
;
194 M_CURSORDATA
->m_cursorId
= id
;
195 M_CURSORDATA
->m_ok
= TRUE
;
197 WXDisplay
* display
= wxGetDisplay();
201 WXCursor cursor
= GetXCursor(display
);
204 wxXCursor
* c
= new wxXCursor
;
205 c
->m_cursor
= cursor
;
206 c
->m_display
= wxGetDisplay();
207 M_CURSORDATA
->m_cursors
.Append(c
);
208 M_CURSORDATA
->m_ok
= TRUE
;
212 wxCursor::~wxCursor()
216 // Motif-specific: create/get a cursor for the current display
217 WXCursor
wxCursor::GetXCursor(WXDisplay
* display
)
221 wxNode
* node
= M_CURSORDATA
->m_cursors
.First();
224 wxXCursor
* c
= (wxXCursor
*) node
->Data();
225 if (c
->m_display
== display
)
230 // No cursor for this display, so let's see if we're an id-type cursor.
232 if (M_CURSORDATA
->m_cursorId
!= wxCURSOR_NONE
)
234 WXCursor cursor
= MakeCursor(display
, M_CURSORDATA
->m_cursorId
);
237 wxXCursor
* c
= new wxXCursor
;
238 c
->m_cursor
= cursor
;
239 c
->m_display
= display
;
240 M_CURSORDATA
->m_cursors
.Append(c
);
247 // Not an id-type cursor, so we don't know how to create it.
251 // Make a cursor from standard id
252 WXCursor
wxCursor::MakeCursor(WXDisplay
* display
, wxStockCursor id
)
254 Display
* dpy
= (Display
*) display
;
255 Cursor cursor
= (Cursor
) 0;
261 cursor
= XCreateFontCursor (dpy
, XC_watch
);
266 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
276 cursor
= XCreateFontCursor (dpy
, XC_hand1
);
279 case wxCURSOR_BULLSEYE
:
281 cursor
= XCreateFontCursor (dpy
, XC_target
);
284 case wxCURSOR_PENCIL
:
286 cursor
= XCreateFontCursor (dpy
, XC_pencil
);
289 case wxCURSOR_MAGNIFIER
:
291 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
296 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
299 case wxCURSOR_NO_ENTRY
:
301 cursor
= XCreateFontCursor (dpy
, XC_pirate
);
304 case wxCURSOR_LEFT_BUTTON
:
306 cursor
= XCreateFontCursor (dpy
, XC_leftbutton
);
309 case wxCURSOR_RIGHT_BUTTON
:
311 cursor
= XCreateFontCursor (dpy
, XC_rightbutton
);
314 case wxCURSOR_MIDDLE_BUTTON
:
316 cursor
= XCreateFontCursor (dpy
, XC_middlebutton
);
319 case wxCURSOR_QUESTION_ARROW
:
321 cursor
= XCreateFontCursor (dpy
, XC_question_arrow
);
324 case wxCURSOR_SIZING
:
326 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
331 cursor
= XCreateFontCursor (dpy
, XC_watch
);
334 case wxCURSOR_SPRAYCAN
:
336 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
339 case wxCURSOR_PAINT_BRUSH
:
341 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
344 case wxCURSOR_SIZENWSE
:
345 case wxCURSOR_SIZENESW
:
347 // Not available in X
348 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
351 case wxCURSOR_SIZEWE
:
353 cursor
= XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
356 case wxCURSOR_SIZENS
:
358 cursor
= XCreateFontCursor (dpy
, XC_sb_v_double_arrow
);
361 case wxCURSOR_POINT_LEFT
:
363 cursor
= XCreateFontCursor (dpy
, XC_sb_left_arrow
);
366 case wxCURSOR_POINT_RIGHT
:
368 cursor
= XCreateFontCursor (dpy
, XC_sb_right_arrow
);
371 // (JD Huggins) added more stock cursors for X
372 // X-only cursors BEGIN
373 case wxCURSOR_CROSS_REVERSE
:
375 cursor
= XCreateFontCursor(dpy
, XC_cross_reverse
);
378 case wxCURSOR_DOUBLE_ARROW
:
380 cursor
= XCreateFontCursor(dpy
, XC_double_arrow
);
383 case wxCURSOR_BASED_ARROW_UP
:
385 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_up
);
388 case wxCURSOR_BASED_ARROW_DOWN
:
390 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_down
);
396 cursor
= XCreateFontCursor (dpy
, XC_top_left_arrow
);
406 empty_pixmap
= XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
408 gcv
.function
= GXxor
;
421 cursor
= XCreatePixmapCursor (dpy
,
431 return (WXCursor
) cursor
;
434 // Global cursor setting
435 void wxSetCursor(const wxCursor
& WXUNUSED(cursor
))
437 // Nothing to do for Motif (no global cursor)
441 // ----------------------------------------------------------------------------
443 // ----------------------------------------------------------------------------
445 static int wxBusyCursorCount
= 0;
449 wxXSetBusyCursor (wxWindow
* win
, wxCursor
* cursor
)
451 Display
*display
= (Display
*) win
->GetXDisplay();
453 Window xwin
= (Window
) win
->GetXWindow();
457 XSetWindowAttributes attrs
;
461 attrs
.cursor
= (Cursor
) cursor
->GetXCursor(display
);
465 // Restore old cursor
466 if (win
->GetCursor().Ok())
467 attrs
.cursor
= (Cursor
) win
->GetCursor().GetXCursor(display
);
472 XChangeWindowAttributes (display
, xwin
, CWCursor
, &attrs
);
476 for(wxNode
*node
= win
->GetChildren().First (); node
; node
= node
->Next())
478 wxWindow
*child
= (wxWindow
*) node
->Data ();
479 wxXSetBusyCursor (child
, cursor
);
483 // Set the cursor to the busy cursor for all windows
484 void wxBeginBusyCursor(wxCursor
*cursor
)
487 if (wxBusyCursorCount
== 1)
489 for(wxNode
*node
= wxTopLevelWindows
.First (); node
; node
= node
->Next())
491 wxWindow
*win
= (wxWindow
*) node
->Data ();
492 wxXSetBusyCursor (win
, cursor
);
497 // Restore cursor to normal
498 void wxEndBusyCursor()
500 if (wxBusyCursorCount
== 0)
504 if (wxBusyCursorCount
== 0)
506 for(wxNode
*node
= wxTopLevelWindows
.First (); node
; node
= node
->Next())
508 wxWindow
*win
= (wxWindow
*) node
->Data ();
509 wxXSetBusyCursor (win
, NULL
);
514 // TRUE if we're between the above two calls
517 return (wxBusyCursorCount
> 0);