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