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 #include <X11/cursorfont.h>
25 #include "wx/motif/private.h"
27 #if !USE_SHARED_LIBRARIES
28 IMPLEMENT_DYNAMIC_CLASS(wxCursor
, wxBitmap
)
29 IMPLEMENT_DYNAMIC_CLASS(wxXCursor
, wxObject
)
32 wxCursorRefData::wxCursorRefData()
34 m_width
= 32; m_height
= 32;
35 m_cursorId
= wxCURSOR_NONE
;
38 wxCursorRefData::~wxCursorRefData()
40 wxNode
* node
= m_cursors
.First();
43 wxXCursor
* c
= (wxXCursor
*) node
->Data();
44 // TODO: how to delete cursor?
45 // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ??
55 wxCursor::wxCursor(const char bits
[], int width
, int height
,
56 int hotSpotX
, int hotSpotY
, const char maskBits
[])
58 m_refData
= new wxCursorRefData
;
60 Display
*dpy
= (Display
*) wxGetDisplay();
61 int screen_num
= DefaultScreen (dpy
);
63 Pixmap pixmap
= XCreatePixmapFromBitmapData (dpy
,
64 RootWindow (dpy
, DefaultScreen(dpy
)),
65 (char*) bits
, width
, height
,
68 Pixmap mask_pixmap
= None
;
71 mask_pixmap
= XCreatePixmapFromBitmapData (dpy
,
72 RootWindow (dpy
, DefaultScreen(dpy
)),
73 (char*) maskBits
, width
, height
,
77 XColor foreground_color
;
78 XColor background_color
;
79 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
80 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
81 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
82 XQueryColor(dpy
, cmap
, &foreground_color
);
83 XQueryColor(dpy
, cmap
, &background_color
);
85 Cursor cursor
= XCreatePixmapCursor (dpy
,
93 XFreePixmap( dpy
, pixmap
);
94 if (mask_pixmap
!= None
)
96 XFreePixmap( dpy
, mask_pixmap
);
101 wxXCursor
*c
= new wxXCursor
;
103 c
->m_cursor
= (WXCursor
) cursor
;
104 c
->m_display
= (WXDisplay
*) dpy
;
105 M_CURSORDATA
->m_cursors
.Append(c
);
106 M_CURSORDATA
->m_ok
= TRUE
;
110 M_CURSORDATA
->m_ok
= TRUE
;
114 wxCursor::wxCursor(const wxString
& name
, long flags
, int hotSpotX
, int hotSpotY
)
116 // Must be an XBM file
117 if (flags
!= wxBITMAP_TYPE_XBM
)
120 m_refData
= new wxCursorRefData
;
122 int hotX
= -1, hotY
= -1;
126 Display
*dpy
= (Display
*) wxGetDisplay();
127 int screen_num
= DefaultScreen (dpy
);
129 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
130 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
132 M_BITMAPDATA
->m_width
= w
;
133 M_BITMAPDATA
->m_height
= h
;
134 M_BITMAPDATA
->m_depth
= 1;
136 if ((value
== BitmapFileInvalid
) ||
137 (value
== BitmapOpenFailed
) ||
138 (value
== BitmapNoMemory
))
143 XColor foreground_color
;
144 XColor background_color
;
145 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
146 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
147 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
148 XQueryColor(dpy
, cmap
, &foreground_color
);
149 XQueryColor(dpy
, cmap
, &background_color
);
151 // TODO: how do we determine whether hotX, hotY were read correctly?
152 if (hotX
< 0 || hotY
< 0)
157 if (hotX
< 0 || hotY
< 0)
163 Pixmap mask_pixmap
= None
;
164 Cursor cursor
= XCreatePixmapCursor (dpy
,
172 XFreePixmap( dpy
, pixmap
);
175 wxXCursor
*c
= new wxXCursor
;
177 c
->m_cursor
= (WXCursor
) cursor
;
178 c
->m_display
= (WXDisplay
*) dpy
;
179 M_CURSORDATA
->m_cursors
.Append(c
);
180 M_CURSORDATA
->m_ok
= TRUE
;
186 // Cursors by stock number
187 wxCursor::wxCursor(wxStockCursor id
)
189 m_refData
= new wxCursorRefData
;
190 M_CURSORDATA
->m_cursorId
= id
;
191 M_CURSORDATA
->m_ok
= TRUE
;
193 WXDisplay
* display
= wxGetDisplay();
197 WXCursor cursor
= GetXCursor(display
);
200 wxXCursor
* c
= new wxXCursor
;
201 c
->m_cursor
= cursor
;
202 c
->m_display
= wxGetDisplay();
203 M_CURSORDATA
->m_cursors
.Append(c
);
204 M_CURSORDATA
->m_ok
= TRUE
;
208 wxCursor::~wxCursor()
212 // Motif-specific: create/get a cursor for the current display
213 WXCursor
wxCursor::GetXCursor(WXDisplay
* display
)
217 wxNode
* node
= M_CURSORDATA
->m_cursors
.First();
220 wxXCursor
* c
= (wxXCursor
*) node
->Data();
221 if (c
->m_display
== display
)
226 // No cursor for this display, so let's see if we're an id-type cursor.
228 if (M_CURSORDATA
->m_cursorId
!= wxCURSOR_NONE
)
230 WXCursor cursor
= MakeCursor(display
, M_CURSORDATA
->m_cursorId
);
233 wxXCursor
* c
= new wxXCursor
;
234 c
->m_cursor
= cursor
;
235 c
->m_display
= display
;
236 M_CURSORDATA
->m_cursors
.Append(c
);
243 // Not an id-type cursor, so we don't know how to create it.
247 // Make a cursor from standard id
248 WXCursor
wxCursor::MakeCursor(WXDisplay
* display
, wxStockCursor id
)
250 Display
* dpy
= (Display
*) display
;
251 Cursor cursor
= (Cursor
) 0;
257 cursor
= XCreateFontCursor (dpy
, XC_watch
);
262 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
272 cursor
= XCreateFontCursor (dpy
, XC_hand1
);
275 case wxCURSOR_BULLSEYE
:
277 cursor
= XCreateFontCursor (dpy
, XC_target
);
280 case wxCURSOR_PENCIL
:
282 cursor
= XCreateFontCursor (dpy
, XC_pencil
);
285 case wxCURSOR_MAGNIFIER
:
287 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
292 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
295 case wxCURSOR_NO_ENTRY
:
297 cursor
= XCreateFontCursor (dpy
, XC_pirate
);
300 case wxCURSOR_LEFT_BUTTON
:
302 cursor
= XCreateFontCursor (dpy
, XC_leftbutton
);
305 case wxCURSOR_RIGHT_BUTTON
:
307 cursor
= XCreateFontCursor (dpy
, XC_rightbutton
);
310 case wxCURSOR_MIDDLE_BUTTON
:
312 cursor
= XCreateFontCursor (dpy
, XC_middlebutton
);
315 case wxCURSOR_QUESTION_ARROW
:
317 cursor
= XCreateFontCursor (dpy
, XC_question_arrow
);
320 case wxCURSOR_SIZING
:
322 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
327 cursor
= XCreateFontCursor (dpy
, XC_watch
);
330 case wxCURSOR_SPRAYCAN
:
332 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
335 case wxCURSOR_PAINT_BRUSH
:
337 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
340 case wxCURSOR_SIZENWSE
:
341 case wxCURSOR_SIZENESW
:
343 // Not available in X
344 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
347 case wxCURSOR_SIZEWE
:
349 cursor
= XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
352 case wxCURSOR_SIZENS
:
354 cursor
= XCreateFontCursor (dpy
, XC_sb_v_double_arrow
);
357 case wxCURSOR_POINT_LEFT
:
359 cursor
= XCreateFontCursor (dpy
, XC_sb_left_arrow
);
362 case wxCURSOR_POINT_RIGHT
:
364 cursor
= XCreateFontCursor (dpy
, XC_sb_right_arrow
);
367 // (JD Huggins) added more stock cursors for X
368 // X-only cursors BEGIN
369 case wxCURSOR_CROSS_REVERSE
:
371 cursor
= XCreateFontCursor(dpy
, XC_cross_reverse
);
374 case wxCURSOR_DOUBLE_ARROW
:
376 cursor
= XCreateFontCursor(dpy
, XC_double_arrow
);
379 case wxCURSOR_BASED_ARROW_UP
:
381 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_up
);
384 case wxCURSOR_BASED_ARROW_DOWN
:
386 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_down
);
392 cursor
= XCreateFontCursor (dpy
, XC_top_left_arrow
);
402 empty_pixmap
= XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
404 gcv
.function
= GXxor
;
417 cursor
= XCreatePixmapCursor (dpy
,
427 return (WXCursor
) cursor
;
430 // Global cursor setting
431 void wxSetCursor(const wxCursor
& cursor
)
433 // Nothing to do for Motif (no global cursor)