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
25 #include <X11/cursorfont.h>
27 #pragma message enable nosimpint
30 #include "wx/x11/private.h"
32 IMPLEMENT_DYNAMIC_CLASS(wxCursor
, wxBitmap
)
33 IMPLEMENT_DYNAMIC_CLASS(wxXCursor
, wxObject
)
35 wxCursorRefData::wxCursorRefData()
37 m_width
= 32; m_height
= 32;
38 m_cursorId
= wxCURSOR_NONE
;
41 wxCursorRefData::~wxCursorRefData()
43 wxNode
* node
= m_cursors
.First();
46 wxXCursor
* c
= (wxXCursor
*) node
->Data();
47 // TODO: how to delete cursor?
48 // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ??
58 wxCursor::wxCursor(const char bits
[], int width
, int height
,
59 int hotSpotX
, int hotSpotY
, const char maskBits
[])
61 m_refData
= new wxCursorRefData
;
63 Display
*dpy
= (Display
*) wxGetDisplay();
64 int screen_num
= DefaultScreen (dpy
);
66 Pixmap pixmap
= XCreatePixmapFromBitmapData (dpy
,
67 RootWindow (dpy
, DefaultScreen(dpy
)),
68 (char*) bits
, width
, height
,
71 Pixmap mask_pixmap
= None
;
74 mask_pixmap
= XCreatePixmapFromBitmapData (dpy
,
75 RootWindow (dpy
, DefaultScreen(dpy
)),
76 (char*) maskBits
, width
, height
,
80 XColor foreground_color
;
81 XColor background_color
;
82 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
83 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
84 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
85 XQueryColor(dpy
, cmap
, &foreground_color
);
86 XQueryColor(dpy
, cmap
, &background_color
);
88 Cursor cursor
= XCreatePixmapCursor (dpy
,
96 XFreePixmap( dpy
, pixmap
);
97 if (mask_pixmap
!= None
)
99 XFreePixmap( dpy
, mask_pixmap
);
104 wxXCursor
*c
= new wxXCursor
;
106 c
->m_cursor
= (WXCursor
) cursor
;
107 c
->m_display
= (WXDisplay
*) dpy
;
108 M_CURSORDATA
->m_cursors
.Append(c
);
109 M_CURSORDATA
->m_ok
= TRUE
;
113 M_CURSORDATA
->m_ok
= TRUE
;
117 wxCursor::wxCursor(const wxString
& name
, long flags
, int hotSpotX
, int hotSpotY
)
119 // Must be an XBM file
120 if (flags
!= wxBITMAP_TYPE_XBM
)
123 m_refData
= new wxCursorRefData
;
125 int hotX
= -1, hotY
= -1;
129 Display
*dpy
= (Display
*) wxGetDisplay();
130 int screen_num
= DefaultScreen (dpy
);
132 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
133 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
135 M_BITMAPDATA
->m_width
= w
;
136 M_BITMAPDATA
->m_height
= h
;
137 M_BITMAPDATA
->m_depth
= 1;
139 if ((value
== BitmapFileInvalid
) ||
140 (value
== BitmapOpenFailed
) ||
141 (value
== BitmapNoMemory
))
146 XColor foreground_color
;
147 XColor background_color
;
148 foreground_color
.pixel
= BlackPixel(dpy
, screen_num
);
149 background_color
.pixel
= WhitePixel(dpy
, screen_num
);
150 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dpy
);
151 XQueryColor(dpy
, cmap
, &foreground_color
);
152 XQueryColor(dpy
, cmap
, &background_color
);
154 // TODO: how do we determine whether hotX, hotY were read correctly?
155 if (hotX
< 0 || hotY
< 0)
160 if (hotX
< 0 || hotY
< 0)
166 Pixmap mask_pixmap
= None
;
167 Cursor cursor
= XCreatePixmapCursor (dpy
,
175 XFreePixmap( dpy
, pixmap
);
178 wxXCursor
*c
= new wxXCursor
;
180 c
->m_cursor
= (WXCursor
) cursor
;
181 c
->m_display
= (WXDisplay
*) dpy
;
182 M_CURSORDATA
->m_cursors
.Append(c
);
183 M_CURSORDATA
->m_ok
= TRUE
;
189 // Cursors by stock number
190 wxCursor::wxCursor(wxStockCursor id
)
192 m_refData
= new wxCursorRefData
;
193 M_CURSORDATA
->m_cursorId
= id
;
194 M_CURSORDATA
->m_ok
= TRUE
;
196 WXDisplay
* display
= wxGetDisplay();
200 WXCursor cursor
= GetXCursor(display
);
203 wxXCursor
* c
= new wxXCursor
;
204 c
->m_cursor
= cursor
;
205 c
->m_display
= wxGetDisplay();
206 M_CURSORDATA
->m_cursors
.Append(c
);
207 M_CURSORDATA
->m_ok
= TRUE
;
211 wxCursor::~wxCursor()
215 // Motif-specific: create/get a cursor for the current display
216 WXCursor
wxCursor::GetXCursor(WXDisplay
* display
)
220 wxNode
* node
= M_CURSORDATA
->m_cursors
.First();
223 wxXCursor
* c
= (wxXCursor
*) node
->Data();
224 if (c
->m_display
== display
)
229 // No cursor for this display, so let's see if we're an id-type cursor.
231 if (M_CURSORDATA
->m_cursorId
!= wxCURSOR_NONE
)
233 WXCursor cursor
= MakeCursor(display
, M_CURSORDATA
->m_cursorId
);
236 wxXCursor
* c
= new wxXCursor
;
237 c
->m_cursor
= cursor
;
238 c
->m_display
= display
;
239 M_CURSORDATA
->m_cursors
.Append(c
);
246 // Not an id-type cursor, so we don't know how to create it.
250 // Make a cursor from standard id
251 WXCursor
wxCursor::MakeCursor(WXDisplay
* display
, wxStockCursor id
)
253 Display
* dpy
= (Display
*) display
;
254 Cursor cursor
= (Cursor
) 0;
260 cursor
= XCreateFontCursor (dpy
, XC_watch
);
265 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
275 cursor
= XCreateFontCursor (dpy
, XC_hand1
);
278 case wxCURSOR_BULLSEYE
:
280 cursor
= XCreateFontCursor (dpy
, XC_target
);
283 case wxCURSOR_PENCIL
:
285 cursor
= XCreateFontCursor (dpy
, XC_pencil
);
288 case wxCURSOR_MAGNIFIER
:
290 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
295 cursor
= XCreateFontCursor (dpy
, XC_xterm
);
298 case wxCURSOR_NO_ENTRY
:
300 cursor
= XCreateFontCursor (dpy
, XC_pirate
);
303 case wxCURSOR_LEFT_BUTTON
:
305 cursor
= XCreateFontCursor (dpy
, XC_leftbutton
);
308 case wxCURSOR_RIGHT_BUTTON
:
310 cursor
= XCreateFontCursor (dpy
, XC_rightbutton
);
313 case wxCURSOR_MIDDLE_BUTTON
:
315 cursor
= XCreateFontCursor (dpy
, XC_middlebutton
);
318 case wxCURSOR_QUESTION_ARROW
:
320 cursor
= XCreateFontCursor (dpy
, XC_question_arrow
);
323 case wxCURSOR_SIZING
:
325 cursor
= XCreateFontCursor (dpy
, XC_sizing
);
330 cursor
= XCreateFontCursor (dpy
, XC_watch
);
333 case wxCURSOR_SPRAYCAN
:
335 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
338 case wxCURSOR_PAINT_BRUSH
:
340 cursor
= XCreateFontCursor (dpy
, XC_spraycan
);
343 case wxCURSOR_SIZENWSE
:
344 case wxCURSOR_SIZENESW
:
346 // Not available in X
347 cursor
= XCreateFontCursor (dpy
, XC_crosshair
);
350 case wxCURSOR_SIZEWE
:
352 cursor
= XCreateFontCursor (dpy
, XC_sb_h_double_arrow
);
355 case wxCURSOR_SIZENS
:
357 cursor
= XCreateFontCursor (dpy
, XC_sb_v_double_arrow
);
360 case wxCURSOR_POINT_LEFT
:
362 cursor
= XCreateFontCursor (dpy
, XC_sb_left_arrow
);
365 case wxCURSOR_POINT_RIGHT
:
367 cursor
= XCreateFontCursor (dpy
, XC_sb_right_arrow
);
370 // (JD Huggins) added more stock cursors for X
371 // X-only cursors BEGIN
372 case wxCURSOR_CROSS_REVERSE
:
374 cursor
= XCreateFontCursor(dpy
, XC_cross_reverse
);
377 case wxCURSOR_DOUBLE_ARROW
:
379 cursor
= XCreateFontCursor(dpy
, XC_double_arrow
);
382 case wxCURSOR_BASED_ARROW_UP
:
384 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_up
);
387 case wxCURSOR_BASED_ARROW_DOWN
:
389 cursor
= XCreateFontCursor(dpy
, XC_based_arrow_down
);
395 cursor
= XCreateFontCursor (dpy
, XC_top_left_arrow
);
405 empty_pixmap
= XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
407 gcv
.function
= GXxor
;
420 cursor
= XCreatePixmapCursor (dpy
,
430 return (WXCursor
) cursor
;
433 // Global cursor setting
434 void wxSetCursor(const wxCursor
& WXUNUSED(cursor
))
436 // Nothing to do for Motif (no global cursor)