Misc. Motif; removed duplicate wxICON; variant compile fix; added wxString form
[wxWidgets.git] / src / motif / cursor.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: cursor.cpp
3 // Purpose: wxCursor class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "cursor.h"
14 #endif
15
16 #include "wx/cursor.h"
17 #include "wx/gdicmn.h"
18 #include "wx/icon.h"
19 #include "wx/app.h"
20 #include "wx/utils.h"
21
22 #include <Xm/Xm.h>
23 #include <X11/cursorfont.h>
24
25 #include "wx/motif/private.h"
26
27 #if !USE_SHARED_LIBRARIES
28 IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap)
29 IMPLEMENT_DYNAMIC_CLASS(wxXCursor, wxObject)
30 #endif
31
32 wxCursorRefData::wxCursorRefData()
33 {
34 m_width = 32; m_height = 32;
35 m_cursorId = wxCURSOR_NONE;
36 }
37
38 wxCursorRefData::~wxCursorRefData()
39 {
40 wxNode* node = m_cursors.First();
41 while (node)
42 {
43 wxXCursor* c = (wxXCursor*) node->Data();
44 // TODO: how to delete cursor?
45 // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ??
46 delete c;
47 node = node->Next();
48 }
49 }
50
51 wxCursor::wxCursor()
52 {
53 }
54
55 wxCursor::wxCursor(const char bits[], int width, int height,
56 int hotSpotX, int hotSpotY, const char maskBits[])
57 {
58 m_refData = new wxCursorRefData;
59
60 Display *dpy = (Display*) wxGetDisplay();
61 int screen_num = DefaultScreen (dpy);
62
63 Pixmap pixmap = XCreatePixmapFromBitmapData (dpy,
64 RootWindow (dpy, DefaultScreen(dpy)),
65 (char*) bits, width, height,
66 1 , 0 , 1);
67
68 Pixmap mask_pixmap = None;
69 if (maskBits != NULL)
70 {
71 mask_pixmap = XCreatePixmapFromBitmapData (dpy,
72 RootWindow (dpy, DefaultScreen(dpy)),
73 (char*) maskBits, width, height,
74 1 , 0 , 1);
75 }
76
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);
84
85 Cursor cursor = XCreatePixmapCursor (dpy,
86 pixmap,
87 mask_pixmap,
88 &foreground_color,
89 &background_color,
90 hotSpotX ,
91 hotSpotY);
92
93 XFreePixmap( dpy, pixmap );
94 if (mask_pixmap != None)
95 {
96 XFreePixmap( dpy, mask_pixmap );
97 }
98
99 if (cursor)
100 {
101 wxXCursor *c = new wxXCursor;
102
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;
107 }
108 else
109 {
110 M_CURSORDATA->m_ok = TRUE;
111 }
112 }
113
114 wxCursor::wxCursor(const wxString& name, long flags, int hotSpotX, int hotSpotY)
115 {
116 // Must be an XBM file
117 if (flags != wxBITMAP_TYPE_XBM)
118 return;
119
120 m_refData = new wxCursorRefData;
121
122 int hotX = -1, hotY = -1;
123 unsigned int w, h;
124 Pixmap pixmap;
125
126 Display *dpy = (Display*) wxGetDisplay();
127 int screen_num = DefaultScreen (dpy);
128
129 int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
130 (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
131
132 M_BITMAPDATA->m_width = w;
133 M_BITMAPDATA->m_height = h;
134 M_BITMAPDATA->m_depth = 1;
135
136 if ((value == BitmapFileInvalid) ||
137 (value == BitmapOpenFailed) ||
138 (value == BitmapNoMemory))
139 {
140 }
141 else
142 {
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);
150
151 // TODO: how do we determine whether hotX, hotY were read correctly?
152 if (hotX < 0 || hotY < 0)
153 {
154 hotX = hotSpotX;
155 hotY = hotSpotY;
156 }
157 if (hotX < 0 || hotY < 0)
158 {
159 hotX = 0;
160 hotY = 0;
161 }
162
163 Pixmap mask_pixmap = None;
164 Cursor cursor = XCreatePixmapCursor (dpy,
165 pixmap,
166 mask_pixmap,
167 &foreground_color,
168 &background_color,
169 hotX,
170 hotY);
171
172 XFreePixmap( dpy, pixmap );
173 if (cursor)
174 {
175 wxXCursor *c = new wxXCursor;
176
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;
181 }
182 }
183
184 }
185
186 // Cursors by stock number
187 wxCursor::wxCursor(wxStockCursor id)
188 {
189 m_refData = new wxCursorRefData;
190 M_CURSORDATA->m_cursorId = id;
191 M_CURSORDATA->m_ok = TRUE;
192
193 WXDisplay* display = wxGetDisplay();
194 if (!display)
195 return;
196
197 WXCursor cursor = GetXCursor(display);
198 if (cursor)
199 {
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;
205 }
206 }
207
208 wxCursor::~wxCursor()
209 {
210 }
211
212 // Motif-specific: create/get a cursor for the current display
213 WXCursor wxCursor::GetXCursor(WXDisplay* display)
214 {
215 if (!M_CURSORDATA)
216 return (WXCursor) 0;
217 wxNode* node = M_CURSORDATA->m_cursors.First();
218 while (node)
219 {
220 wxXCursor* c = (wxXCursor*) node->Data();
221 if (c->m_display == display)
222 return c->m_cursor;
223 node = node->Next();
224 }
225
226 // No cursor for this display, so let's see if we're an id-type cursor.
227
228 if (M_CURSORDATA->m_cursorId != wxCURSOR_NONE)
229 {
230 WXCursor cursor = MakeCursor(display, M_CURSORDATA->m_cursorId);
231 if (cursor)
232 {
233 wxXCursor* c = new wxXCursor;
234 c->m_cursor = cursor;
235 c->m_display = display;
236 M_CURSORDATA->m_cursors.Append(c);
237 return cursor;
238 }
239 else
240 return (WXCursor) 0;
241 }
242
243 // Not an id-type cursor, so we don't know how to create it.
244 return (WXCursor) 0;
245 }
246
247 // Make a cursor from standard id
248 WXCursor wxCursor::MakeCursor(WXDisplay* display, wxStockCursor id)
249 {
250 Display* dpy = (Display*) display;
251 Cursor cursor = (Cursor) 0;
252
253 switch (id)
254 {
255 case wxCURSOR_WAIT:
256 {
257 cursor = XCreateFontCursor (dpy, XC_watch);
258 break;
259 }
260 case wxCURSOR_CROSS:
261 {
262 cursor = XCreateFontCursor (dpy, XC_crosshair);
263 break;
264 }
265 case wxCURSOR_CHAR:
266 {
267 // Nothing
268 break;
269 }
270 case wxCURSOR_HAND:
271 {
272 cursor = XCreateFontCursor (dpy, XC_hand1);
273 break;
274 }
275 case wxCURSOR_BULLSEYE:
276 {
277 cursor = XCreateFontCursor (dpy, XC_target);
278 break;
279 }
280 case wxCURSOR_PENCIL:
281 {
282 cursor = XCreateFontCursor (dpy, XC_pencil);
283 break;
284 }
285 case wxCURSOR_MAGNIFIER:
286 {
287 cursor = XCreateFontCursor (dpy, XC_sizing);
288 break;
289 }
290 case wxCURSOR_IBEAM:
291 {
292 cursor = XCreateFontCursor (dpy, XC_xterm);
293 break;
294 }
295 case wxCURSOR_NO_ENTRY:
296 {
297 cursor = XCreateFontCursor (dpy, XC_pirate);
298 break;
299 }
300 case wxCURSOR_LEFT_BUTTON:
301 {
302 cursor = XCreateFontCursor (dpy, XC_leftbutton);
303 break;
304 }
305 case wxCURSOR_RIGHT_BUTTON:
306 {
307 cursor = XCreateFontCursor (dpy, XC_rightbutton);
308 break;
309 }
310 case wxCURSOR_MIDDLE_BUTTON:
311 {
312 cursor = XCreateFontCursor (dpy, XC_middlebutton);
313 break;
314 }
315 case wxCURSOR_QUESTION_ARROW:
316 {
317 cursor = XCreateFontCursor (dpy, XC_question_arrow);
318 break;
319 }
320 case wxCURSOR_SIZING:
321 {
322 cursor = XCreateFontCursor (dpy, XC_sizing);
323 break;
324 }
325 case wxCURSOR_WATCH:
326 {
327 cursor = XCreateFontCursor (dpy, XC_watch);
328 break;
329 }
330 case wxCURSOR_SPRAYCAN:
331 {
332 cursor = XCreateFontCursor (dpy, XC_spraycan);
333 break;
334 }
335 case wxCURSOR_PAINT_BRUSH:
336 {
337 cursor = XCreateFontCursor (dpy, XC_spraycan);
338 break;
339 }
340 case wxCURSOR_SIZENWSE:
341 case wxCURSOR_SIZENESW:
342 {
343 // Not available in X
344 cursor = XCreateFontCursor (dpy, XC_crosshair);
345 break;
346 }
347 case wxCURSOR_SIZEWE:
348 {
349 cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
350 break;
351 }
352 case wxCURSOR_SIZENS:
353 {
354 cursor = XCreateFontCursor (dpy, XC_sb_v_double_arrow);
355 break;
356 }
357 case wxCURSOR_POINT_LEFT:
358 {
359 cursor = XCreateFontCursor (dpy, XC_sb_left_arrow);
360 break;
361 }
362 case wxCURSOR_POINT_RIGHT:
363 {
364 cursor = XCreateFontCursor (dpy, XC_sb_right_arrow);
365 break;
366 }
367 // (JD Huggins) added more stock cursors for X
368 // X-only cursors BEGIN
369 case wxCURSOR_CROSS_REVERSE:
370 {
371 cursor = XCreateFontCursor(dpy, XC_cross_reverse);
372 break;
373 }
374 case wxCURSOR_DOUBLE_ARROW:
375 {
376 cursor = XCreateFontCursor(dpy, XC_double_arrow);
377 break;
378 }
379 case wxCURSOR_BASED_ARROW_UP:
380 {
381 cursor = XCreateFontCursor(dpy, XC_based_arrow_up);
382 break;
383 }
384 case wxCURSOR_BASED_ARROW_DOWN:
385 {
386 cursor = XCreateFontCursor(dpy, XC_based_arrow_down);
387 break;
388 }
389 default:
390 case wxCURSOR_ARROW:
391 {
392 cursor = XCreateFontCursor (dpy, XC_top_left_arrow);
393 break;
394 }
395 case wxCURSOR_BLANK:
396 {
397 GC gc;
398 XGCValues gcv;
399 Pixmap empty_pixmap;
400 XColor blank_color;
401
402 empty_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
403 16, 16, 1);
404 gcv.function = GXxor;
405 gc = XCreateGC (dpy,
406 empty_pixmap,
407 GCFunction,
408 &gcv);
409 XCopyArea (dpy,
410 empty_pixmap,
411 empty_pixmap,
412 gc,
413 0, 0,
414 16, 16,
415 0, 0);
416 XFreeGC (dpy, gc);
417 cursor = XCreatePixmapCursor (dpy,
418 empty_pixmap,
419 empty_pixmap,
420 &blank_color,
421 &blank_color,
422 8, 8);
423
424 break;
425 }
426 }
427 return (WXCursor) cursor;
428 }
429
430 // Global cursor setting
431 void wxSetCursor(const wxCursor& cursor)
432 {
433 // Nothing to do for Motif (no global cursor)
434 }
435
436