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 #if !USE_SHARED_LIBRARIES
34 IMPLEMENT_DYNAMIC_CLASS(wxCursor
, wxBitmap
)
35 IMPLEMENT_DYNAMIC_CLASS(wxXCursor
, wxObject
)
38 wxCursorRefData::wxCursorRefData()
40 m_width
= 32; m_height
= 32;
41 m_cursorId
= wxCURSOR_NONE
;
44 wxCursorRefData::~wxCursorRefData()
46 wxNode
* node
= m_cursors
.First();
49 wxXCursor
* c
= (wxXCursor
*) node
->Data();
50 // TODO: how to delete cursor?
51 // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ??
61 wxCursor::wxCursor(const char bits
[], int width
, int height
,
62 int hotSpotX
, int hotSpotY
, const char maskBits
[])
64 m_refData
= new wxCursorRefData
;
66 Display
*dpy
= (Display
*) wxGetDisplay();
67 int screen_num
= DefaultScreen (dpy
);
69 Pixmap pixmap
= XCreatePixmapFromBitmapData (dpy
,
70 RootWindow (dpy
, DefaultScreen(dpy
)),
71 (char*) bits
, width
, height
,
74 Pixmap mask_pixmap
= None
;
77 mask_pixmap
= XCreatePixmapFromBitmapData (dpy
,
78 RootWindow (dpy
, DefaultScreen(dpy
)),
79 (char*) maskBits
, width
, height
,
83 XColor foreground_color
;
84 XColor background_color
;
85 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
86 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
87 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
88 XQueryColor(dpy
, cmap
, &foreground_color
);
89 XQueryColor(dpy
, cmap
, &background_color
);
91 Cursor cursor
= XCreatePixmapCursor (dpy
,
99 XFreePixmap( dpy
, pixmap
);
100 if (mask_pixmap
!= None
)
102 XFreePixmap( dpy
, mask_pixmap
);
107 wxXCursor
*c
= new wxXCursor
;
109 c
->m_cursor
= (WXCursor
) cursor
;
110 c
->m_display
= (WXDisplay
*) dpy
;
111 M_CURSORDATA
->m_cursors
.Append(c
);
112 M_CURSORDATA
->m_ok
= TRUE
;
116 M_CURSORDATA
->m_ok
= TRUE
;
120 wxCursor::wxCursor(const wxString
& name
, long flags
, int hotSpotX
, int hotSpotY
)
122 // Must be an XBM file
123 if (flags
!= wxBITMAP_TYPE_XBM
)
126 m_refData
= new wxCursorRefData
;
128 int hotX
= -1, hotY
= -1;
132 Display
*dpy
= (Display
*) wxGetDisplay();
133 int screen_num
= DefaultScreen (dpy
);
135 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
136 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
138 M_BITMAPDATA
->m_width
= w
;
139 M_BITMAPDATA
->m_height
= h
;
140 M_BITMAPDATA
->m_depth
= 1;
142 if ((value
== BitmapFileInvalid
) ||
143 (value
== BitmapOpenFailed
) ||
144 (value
== BitmapNoMemory
))
149 XColor foreground_color
;
150 XColor background_color
;
151 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
152 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
153 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
154 XQueryColor(dpy
, cmap
, &foreground_color
);
155 XQueryColor(dpy
, cmap
, &background_color
);
157 // TODO: how do we determine whether hotX, hotY were read correctly?
158 if (hotX
< 0 || hotY
< 0)
163 if (hotX
< 0 || hotY
< 0)
169 Pixmap mask_pixmap
= None
;
170 Cursor cursor
= XCreatePixmapCursor (dpy
,
178 XFreePixmap( dpy
, pixmap
);
181 wxXCursor
*c
= new wxXCursor
;
183 c
->m_cursor
= (WXCursor
) cursor
;
184 c
->m_display
= (WXDisplay
*) dpy
;
185 M_CURSORDATA
->m_cursors
.Append(c
);
186 M_CURSORDATA
->m_ok
= TRUE
;
192 // Cursors by stock number
193 wxCursor::wxCursor(wxStockCursor id
)
195 m_refData
= new wxCursorRefData
;
196 M_CURSORDATA
->m_cursorId
= id
;
197 M_CURSORDATA
->m_ok
= TRUE
;
199 WXDisplay
* display
= wxGetDisplay();
203 WXCursor cursor
= GetXCursor(display
);
206 wxXCursor
* c
= new wxXCursor
;
207 c
->m_cursor
= cursor
;
208 c
->m_display
= wxGetDisplay();
209 M_CURSORDATA
->m_cursors
.Append(c
);
210 M_CURSORDATA
->m_ok
= TRUE
;
214 wxCursor::~wxCursor()
218 // Motif-specific: create/get a cursor for the current display
219 WXCursor
wxCursor::GetXCursor(WXDisplay
* display
)
223 wxNode
* node
= M_CURSORDATA
->m_cursors
.First();
226 wxXCursor
* c
= (wxXCursor
*) node
->Data();
227 if (c
->m_display
== display
)
232 // No cursor for this display, so let's see if we're an id-type cursor.
234 if (M_CURSORDATA
->m_cursorId
!= wxCURSOR_NONE
)
236 WXCursor cursor
= MakeCursor(display
, M_CURSORDATA
->m_cursorId
);
239 wxXCursor
* c
= new wxXCursor
;
240 c
->m_cursor
= cursor
;
241 c
->m_display
= display
;
242 M_CURSORDATA
->m_cursors
.Append(c
);
249 // Not an id-type cursor, so we don't know how to create it.
253 // Make a cursor from standard id
254 WXCursor
wxCursor::MakeCursor(WXDisplay
* display
, wxStockCursor id
)
256 Display
* dpy
= (Display
*) display
;
257 Cursor cursor
= (Cursor
) 0;
263 cursor
= XCreateFontCursor (dpy
, XC_watch
);
268 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
278 cursor
= XCreateFontCursor (dpy
, XC_hand1
);
281 case wxCURSOR_BULLSEYE
:
283 cursor
= XCreateFontCursor (dpy
, XC_target
);
286 case wxCURSOR_PENCIL
:
288 cursor
= XCreateFontCursor (dpy
, XC_pencil
);
291 case wxCURSOR_MAGNIFIER
:
293 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
298 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
301 case wxCURSOR_NO_ENTRY
:
303 cursor
= XCreateFontCursor (dpy
, XC_pirate
);
306 case wxCURSOR_LEFT_BUTTON
:
308 cursor
= XCreateFontCursor (dpy
, XC_leftbutton
);
311 case wxCURSOR_RIGHT_BUTTON
:
313 cursor
= XCreateFontCursor (dpy
, XC_rightbutton
);
316 case wxCURSOR_MIDDLE_BUTTON
:
318 cursor
= XCreateFontCursor (dpy
, XC_middlebutton
);
321 case wxCURSOR_QUESTION_ARROW
:
323 cursor
= XCreateFontCursor (dpy
, XC_question_arrow
);
326 case wxCURSOR_SIZING
:
328 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
333 cursor
= XCreateFontCursor (dpy
, XC_watch
);
336 case wxCURSOR_SPRAYCAN
:
338 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
341 case wxCURSOR_PAINT_BRUSH
:
343 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
346 case wxCURSOR_SIZENWSE
:
347 case wxCURSOR_SIZENESW
:
349 // Not available in X
350 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
353 case wxCURSOR_SIZEWE
:
355 cursor
= XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
358 case wxCURSOR_SIZENS
:
360 cursor
= XCreateFontCursor (dpy
, XC_sb_v_double_arrow
);
363 case wxCURSOR_POINT_LEFT
:
365 cursor
= XCreateFontCursor (dpy
, XC_sb_left_arrow
);
368 case wxCURSOR_POINT_RIGHT
:
370 cursor
= XCreateFontCursor (dpy
, XC_sb_right_arrow
);
373 // (JD Huggins) added more stock cursors for X
374 // X-only cursors BEGIN
375 case wxCURSOR_CROSS_REVERSE
:
377 cursor
= XCreateFontCursor(dpy
, XC_cross_reverse
);
380 case wxCURSOR_DOUBLE_ARROW
:
382 cursor
= XCreateFontCursor(dpy
, XC_double_arrow
);
385 case wxCURSOR_BASED_ARROW_UP
:
387 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_up
);
390 case wxCURSOR_BASED_ARROW_DOWN
:
392 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_down
);
398 cursor
= XCreateFontCursor (dpy
, XC_top_left_arrow
);
408 empty_pixmap
= XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
410 gcv
.function
= GXxor
;
423 cursor
= XCreatePixmapCursor (dpy
,
433 return (WXCursor
) cursor
;
436 // Global cursor setting
437 void wxSetCursor(const wxCursor
& WXUNUSED(cursor
))
439 // Nothing to do for Motif (no global cursor)