More wxMotif work, OGL enhancements, USE_ macro corrections, object.cpp delete
[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
192 WXCursor cursor = GetXCursor(wxGetDisplay());
193 if (cursor)
194 {
195 wxXCursor* c = new wxXCursor;
196 c->m_cursor = cursor;
197 c->m_display = wxGetDisplay();
198 M_CURSORDATA->m_cursors.Append(c);
199 M_CURSORDATA->m_ok = TRUE;
200 }
201 }
202
203 wxCursor::~wxCursor()
204 {
205 }
206
207 // Motif-specific: create/get a cursor for the current display
208 WXCursor wxCursor::GetXCursor(WXDisplay* display)
209 {
210 if (!M_CURSORDATA)
211 return (WXCursor) 0;
212 wxNode* node = M_CURSORDATA->m_cursors.First();
213 while (node)
214 {
215 wxXCursor* c = (wxXCursor*) node->Data();
216 if (c->m_display == display)
217 return c->m_cursor;
218 node = node->Next();
219 }
220
221 // No cursor for this display, so let's see if we're an id-type cursor.
222
223 if (M_CURSORDATA->m_cursorId != wxCURSOR_NONE)
224 {
225 WXCursor cursor = MakeCursor(display, M_CURSORDATA->m_cursorId);
226 if (cursor)
227 {
228 wxXCursor* c = new wxXCursor;
229 c->m_cursor = cursor;
230 c->m_display = display;
231 M_CURSORDATA->m_cursors.Append(c);
232 return cursor;
233 }
234 else
235 return (WXCursor) 0;
236 }
237
238 // Not an id-type cursor, so we don't know how to create it.
239 return (WXCursor) 0;
240 }
241
242 // Make a cursor from standard id
243 WXCursor wxCursor::MakeCursor(WXDisplay* display, wxStockCursor id)
244 {
245 Display* dpy = (Display*) display;
246 Cursor cursor = (Cursor) 0;
247
248 switch (id)
249 {
250 case wxCURSOR_WAIT:
251 {
252 cursor = XCreateFontCursor (dpy, XC_watch);
253 break;
254 }
255 case wxCURSOR_CROSS:
256 {
257 cursor = XCreateFontCursor (dpy, XC_crosshair);
258 break;
259 }
260 case wxCURSOR_CHAR:
261 {
262 // Nothing
263 break;
264 }
265 case wxCURSOR_HAND:
266 {
267 cursor = XCreateFontCursor (dpy, XC_hand1);
268 break;
269 }
270 case wxCURSOR_BULLSEYE:
271 {
272 cursor = XCreateFontCursor (dpy, XC_target);
273 break;
274 }
275 case wxCURSOR_PENCIL:
276 {
277 cursor = XCreateFontCursor (dpy, XC_pencil);
278 break;
279 }
280 case wxCURSOR_MAGNIFIER:
281 {
282 cursor = XCreateFontCursor (dpy, XC_sizing);
283 break;
284 }
285 case wxCURSOR_IBEAM:
286 {
287 cursor = XCreateFontCursor (dpy, XC_xterm);
288 break;
289 }
290 case wxCURSOR_NO_ENTRY:
291 {
292 cursor = XCreateFontCursor (dpy, XC_pirate);
293 break;
294 }
295 case wxCURSOR_LEFT_BUTTON:
296 {
297 cursor = XCreateFontCursor (dpy, XC_leftbutton);
298 break;
299 }
300 case wxCURSOR_RIGHT_BUTTON:
301 {
302 cursor = XCreateFontCursor (dpy, XC_rightbutton);
303 break;
304 }
305 case wxCURSOR_MIDDLE_BUTTON:
306 {
307 cursor = XCreateFontCursor (dpy, XC_middlebutton);
308 break;
309 }
310 case wxCURSOR_QUESTION_ARROW:
311 {
312 cursor = XCreateFontCursor (dpy, XC_question_arrow);
313 break;
314 }
315 case wxCURSOR_SIZING:
316 {
317 cursor = XCreateFontCursor (dpy, XC_sizing);
318 break;
319 }
320 case wxCURSOR_WATCH:
321 {
322 cursor = XCreateFontCursor (dpy, XC_watch);
323 break;
324 }
325 case wxCURSOR_SPRAYCAN:
326 {
327 cursor = XCreateFontCursor (dpy, XC_spraycan);
328 break;
329 }
330 case wxCURSOR_PAINT_BRUSH:
331 {
332 cursor = XCreateFontCursor (dpy, XC_spraycan);
333 break;
334 }
335 case wxCURSOR_SIZENWSE:
336 case wxCURSOR_SIZENESW:
337 {
338 // Not available in X
339 cursor = XCreateFontCursor (dpy, XC_crosshair);
340 break;
341 }
342 case wxCURSOR_SIZEWE:
343 {
344 cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
345 break;
346 }
347 case wxCURSOR_SIZENS:
348 {
349 cursor = XCreateFontCursor (dpy, XC_sb_v_double_arrow);
350 break;
351 }
352 case wxCURSOR_POINT_LEFT:
353 {
354 cursor = XCreateFontCursor (dpy, XC_sb_left_arrow);
355 break;
356 }
357 case wxCURSOR_POINT_RIGHT:
358 {
359 cursor = XCreateFontCursor (dpy, XC_sb_right_arrow);
360 break;
361 }
362 // (JD Huggins) added more stock cursors for X
363 // X-only cursors BEGIN
364 case wxCURSOR_CROSS_REVERSE:
365 {
366 cursor = XCreateFontCursor(dpy, XC_cross_reverse);
367 break;
368 }
369 case wxCURSOR_DOUBLE_ARROW:
370 {
371 cursor = XCreateFontCursor(dpy, XC_double_arrow);
372 break;
373 }
374 case wxCURSOR_BASED_ARROW_UP:
375 {
376 cursor = XCreateFontCursor(dpy, XC_based_arrow_up);
377 break;
378 }
379 case wxCURSOR_BASED_ARROW_DOWN:
380 {
381 cursor = XCreateFontCursor(dpy, XC_based_arrow_down);
382 break;
383 }
384 default:
385 case wxCURSOR_ARROW:
386 {
387 cursor = XCreateFontCursor (dpy, XC_top_left_arrow);
388 break;
389 }
390 case wxCURSOR_BLANK:
391 {
392 GC gc;
393 XGCValues gcv;
394 Pixmap empty_pixmap;
395 XColor blank_color;
396
397 empty_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
398 16, 16, 1);
399 gcv.function = GXxor;
400 gc = XCreateGC (dpy,
401 empty_pixmap,
402 GCFunction,
403 &gcv);
404 XCopyArea (dpy,
405 empty_pixmap,
406 empty_pixmap,
407 gc,
408 0, 0,
409 16, 16,
410 0, 0);
411 XFreeGC (dpy, gc);
412 cursor = XCreatePixmapCursor (dpy,
413 empty_pixmap,
414 empty_pixmap,
415 &blank_color,
416 &blank_color,
417 8, 8);
418
419 break;
420 }
421 }
422 return (WXCursor) cursor;
423 }
424
425 // Global cursor setting
426 void wxSetCursor(const wxCursor& cursor)
427 {
428 // Nothing to do for Motif (no global cursor)
429 }
430
431