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