]>
Commit | Line | Data |
---|---|---|
4bb6408c JS |
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" | |
f97c9854 | 17 | #include "wx/gdicmn.h" |
4bb6408c | 18 | #include "wx/icon.h" |
f97c9854 JS |
19 | #include "wx/app.h" |
20 | #include "wx/utils.h" | |
4daa4d66 CE |
21 | #if wxUSE_IMAGE |
22 | #include "wx/image.h" | |
23 | #endif | |
f97c9854 | 24 | |
338dd992 JJ |
25 | #ifdef __VMS__ |
26 | #pragma message disable nosimpint | |
27 | #endif | |
f97c9854 JS |
28 | #include <Xm/Xm.h> |
29 | #include <X11/cursorfont.h> | |
338dd992 JJ |
30 | #ifdef __VMS__ |
31 | #pragma message enable nosimpint | |
32 | #endif | |
f97c9854 JS |
33 | |
34 | #include "wx/motif/private.h" | |
4bb6408c | 35 | |
4bb6408c | 36 | IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap) |
f97c9854 | 37 | IMPLEMENT_DYNAMIC_CLASS(wxXCursor, wxObject) |
4bb6408c JS |
38 | |
39 | wxCursorRefData::wxCursorRefData() | |
40 | { | |
41 | m_width = 32; m_height = 32; | |
f97c9854 | 42 | m_cursorId = wxCURSOR_NONE; |
4bb6408c JS |
43 | } |
44 | ||
45 | wxCursorRefData::~wxCursorRefData() | |
46 | { | |
f97c9854 JS |
47 | wxNode* node = m_cursors.First(); |
48 | while (node) | |
49 | { | |
50 | wxXCursor* c = (wxXCursor*) node->Data(); | |
51 | // TODO: how to delete cursor? | |
52 | // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ?? | |
53 | delete c; | |
54 | node = node->Next(); | |
55 | } | |
4bb6408c JS |
56 | } |
57 | ||
4bb6408c JS |
58 | wxCursor::wxCursor() |
59 | { | |
60 | } | |
61 | ||
4daa4d66 CE |
62 | #if wxUSE_IMAGE |
63 | wxCursor::wxCursor(const wxImage & image) | |
64 | { | |
65 | unsigned char * rgbBits = image.GetData(); | |
66 | int w = image.GetWidth() ; | |
67 | int h = image.GetHeight(); | |
68 | bool bHasMask = image.HasMask(); | |
69 | int imagebitcount = (w*h)/8; | |
70 | ||
71 | unsigned char * bits = new unsigned char [imagebitcount]; | |
72 | unsigned char * maskBits = new unsigned char [imagebitcount]; | |
73 | ||
74 | int i, j, i8; unsigned char c, cMask; | |
75 | for (i=0; i<imagebitcount; i++) | |
76 | { | |
77 | bits[i] = 0; | |
78 | i8 = i * 8; | |
79 | ||
80 | cMask = 1; | |
81 | for (j=0; j<8; j++) | |
82 | { | |
83 | // possible overflow if we do the summation first ? | |
84 | c = rgbBits[(i8+j)*3]/3 + rgbBits[(i8+j)*3+1]/3 + rgbBits[(i8+j)*3+2]/3; | |
85 | //if average value is > mid grey | |
86 | if (c>127) | |
87 | bits[i] = bits[i] | cMask; | |
88 | cMask = cMask * 2; | |
89 | } | |
90 | } | |
91 | ||
92 | unsigned long keyMaskColor; | |
93 | if (bHasMask) | |
94 | { | |
95 | unsigned char | |
96 | r = image.GetMaskRed(), | |
97 | g = image.GetMaskGreen(), | |
98 | b = image.GetMaskBlue(); | |
99 | ||
100 | for (i=0; i<imagebitcount; i++) | |
101 | { | |
102 | maskBits[i] = 0x0; | |
103 | i8 = i * 8; | |
104 | ||
105 | cMask = 1; | |
106 | for (j=0; j<8; j++) | |
107 | { | |
108 | if (rgbBits[(i8+j)*3] != r || rgbBits[(i8+j)*3+1] != g || rgbBits[(i8+j)*3+2] != b) | |
109 | maskBits[i] = maskBits[i] | cMask; | |
110 | cMask = cMask * 2; | |
111 | } | |
112 | } | |
113 | ||
114 | keyMaskColor = (r << 16) | (g << 8) | b; | |
115 | } | |
116 | else // no mask | |
117 | { | |
118 | for (i=0; i<imagebitcount; i++) | |
119 | maskBits[i] = 0xFF; | |
120 | ||
121 | // init it to avoid compiler warnings | |
122 | keyMaskColor = 0; | |
123 | } | |
124 | /* | |
125 | // find the most frequent color(s) | |
126 | wxImageHistogram histogram; | |
127 | image.ComputeHistogram(histogram); | |
128 | ||
129 | // colors as rrggbb | |
130 | unsigned long key; | |
131 | unsigned long value; | |
132 | ||
133 | long colMostFreq = 0; | |
134 | unsigned long nMost = 0; | |
135 | long colNextMostFreq = 0; | |
136 | unsigned long nNext = 0; | |
137 | for ( wxImageHistogram::iterator entry = histogram.begin(); | |
138 | entry != histogram.end(); | |
139 | ++entry ) | |
140 | { | |
141 | value = entry->second.value; | |
142 | key = entry->first; | |
143 | if ( !bHasMask || (key != keyMaskColor) ) | |
144 | { | |
145 | if (value > nMost) | |
146 | { | |
147 | nMost = value; | |
148 | colMostFreq = key; | |
149 | } | |
150 | else if (value > nNext) | |
151 | { | |
152 | nNext = value; | |
153 | colNextMostFreq = key; | |
154 | } | |
155 | } | |
156 | } | |
157 | ||
158 | wxColour fg = wxColour ( (unsigned char)(colMostFreq >> 16), | |
159 | (unsigned char)(colMostFreq >> 8), | |
160 | (unsigned char)(colMostFreq) ); | |
161 | ||
162 | wxColour bg = wxColour ( (unsigned char)(colNextMostFreq >> 16), | |
163 | (unsigned char)(colNextMostFreq >> 8), | |
164 | (unsigned char)(colNextMostFreq) ); | |
165 | end of color code | |
166 | */ | |
167 | int hotSpotX; | |
168 | int hotSpotY; | |
169 | ||
170 | if (image.HasOption(wxCUR_HOTSPOT_X)) | |
171 | hotSpotX = image.GetOptionInt(wxCUR_HOTSPOT_X); | |
172 | else | |
173 | hotSpotX = 0; | |
174 | ||
175 | if (image.HasOption(wxCUR_HOTSPOT_Y)) | |
176 | hotSpotY = image.GetOptionInt(wxCUR_HOTSPOT_Y); | |
177 | else | |
178 | hotSpotY = 0; | |
179 | ||
180 | if (hotSpotX < 0 || hotSpotX >= w) | |
181 | hotSpotX = 0; | |
182 | if (hotSpotY < 0 || hotSpotY >= h) | |
183 | hotSpotY = 0; | |
184 | ||
185 | m_refData = new wxCursorRefData; | |
186 | ||
187 | Display *dpy = (Display*) wxGetDisplay(); | |
188 | int screen_num = DefaultScreen (dpy); | |
189 | ||
190 | Pixmap pixmap = XCreatePixmapFromBitmapData (dpy, | |
191 | RootWindow (dpy, DefaultScreen(dpy)), | |
192 | (char*) bits, w, h, | |
193 | 1 , 0 , 1); | |
194 | ||
195 | Pixmap mask_pixmap = None; | |
196 | if (maskBits != NULL) | |
197 | { | |
198 | mask_pixmap = XCreatePixmapFromBitmapData (dpy, | |
199 | RootWindow (dpy, DefaultScreen(dpy)), | |
200 | (char*) maskBits, w, h, | |
201 | 1 , 0 , 1); | |
202 | } | |
203 | ||
204 | XColor foreground_color; | |
205 | XColor background_color; | |
206 | foreground_color.pixel = BlackPixel(dpy, screen_num); | |
207 | background_color.pixel = WhitePixel(dpy, screen_num); | |
208 | Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); | |
209 | XQueryColor(dpy, cmap, &foreground_color); | |
210 | XQueryColor(dpy, cmap, &background_color); | |
211 | ||
212 | Cursor cursor = XCreatePixmapCursor (dpy, | |
213 | pixmap, | |
214 | mask_pixmap, | |
215 | &foreground_color, | |
216 | &background_color, | |
217 | hotSpotX , | |
218 | hotSpotY); | |
219 | ||
220 | XFreePixmap( dpy, pixmap ); | |
221 | if (mask_pixmap != None) | |
222 | { | |
223 | XFreePixmap( dpy, mask_pixmap ); | |
224 | } | |
225 | ||
226 | if (cursor) | |
227 | { | |
228 | wxXCursor *c = new wxXCursor; | |
229 | ||
230 | c->m_cursor = (WXCursor) cursor; | |
231 | c->m_display = (WXDisplay*) dpy; | |
232 | M_CURSORDATA->m_cursors.Append(c); | |
233 | M_CURSORDATA->m_ok = TRUE; | |
234 | } | |
235 | else | |
236 | { | |
237 | M_CURSORDATA->m_ok = TRUE; | |
238 | } | |
239 | ||
240 | } | |
241 | #endif | |
242 | ||
f97c9854 JS |
243 | wxCursor::wxCursor(const char bits[], int width, int height, |
244 | int hotSpotX, int hotSpotY, const char maskBits[]) | |
4bb6408c | 245 | { |
f97c9854 | 246 | m_refData = new wxCursorRefData; |
4bb6408c | 247 | |
f97c9854 JS |
248 | Display *dpy = (Display*) wxGetDisplay(); |
249 | int screen_num = DefaultScreen (dpy); | |
4bb6408c | 250 | |
f97c9854 JS |
251 | Pixmap pixmap = XCreatePixmapFromBitmapData (dpy, |
252 | RootWindow (dpy, DefaultScreen(dpy)), | |
253 | (char*) bits, width, height, | |
254 | 1 , 0 , 1); | |
4bb6408c | 255 | |
f97c9854 JS |
256 | Pixmap mask_pixmap = None; |
257 | if (maskBits != NULL) | |
4bb6408c | 258 | { |
f97c9854 JS |
259 | mask_pixmap = XCreatePixmapFromBitmapData (dpy, |
260 | RootWindow (dpy, DefaultScreen(dpy)), | |
261 | (char*) maskBits, width, height, | |
262 | 1 , 0 , 1); | |
4bb6408c | 263 | } |
f97c9854 JS |
264 | |
265 | XColor foreground_color; | |
266 | XColor background_color; | |
267 | foreground_color.pixel = BlackPixel(dpy, screen_num); | |
268 | background_color.pixel = WhitePixel(dpy, screen_num); | |
269 | Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); | |
270 | XQueryColor(dpy, cmap, &foreground_color); | |
271 | XQueryColor(dpy, cmap, &background_color); | |
272 | ||
273 | Cursor cursor = XCreatePixmapCursor (dpy, | |
274 | pixmap, | |
275 | mask_pixmap, | |
276 | &foreground_color, | |
277 | &background_color, | |
278 | hotSpotX , | |
279 | hotSpotY); | |
280 | ||
281 | XFreePixmap( dpy, pixmap ); | |
282 | if (mask_pixmap != None) | |
4bb6408c | 283 | { |
f97c9854 | 284 | XFreePixmap( dpy, mask_pixmap ); |
4bb6408c | 285 | } |
f97c9854 JS |
286 | |
287 | if (cursor) | |
4bb6408c | 288 | { |
f97c9854 JS |
289 | wxXCursor *c = new wxXCursor; |
290 | ||
291 | c->m_cursor = (WXCursor) cursor; | |
292 | c->m_display = (WXDisplay*) dpy; | |
293 | M_CURSORDATA->m_cursors.Append(c); | |
294 | M_CURSORDATA->m_ok = TRUE; | |
4bb6408c | 295 | } |
f97c9854 | 296 | else |
4bb6408c | 297 | { |
f97c9854 | 298 | M_CURSORDATA->m_ok = TRUE; |
4bb6408c | 299 | } |
f97c9854 JS |
300 | } |
301 | ||
302 | wxCursor::wxCursor(const wxString& name, long flags, int hotSpotX, int hotSpotY) | |
303 | { | |
304 | // Must be an XBM file | |
305 | if (flags != wxBITMAP_TYPE_XBM) | |
306 | return; | |
307 | ||
308 | m_refData = new wxCursorRefData; | |
309 | ||
310 | int hotX = -1, hotY = -1; | |
311 | unsigned int w, h; | |
312 | Pixmap pixmap; | |
313 | ||
314 | Display *dpy = (Display*) wxGetDisplay(); | |
315 | int screen_num = DefaultScreen (dpy); | |
316 | ||
317 | int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)), | |
318 | (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY); | |
319 | ||
320 | M_BITMAPDATA->m_width = w; | |
321 | M_BITMAPDATA->m_height = h; | |
322 | M_BITMAPDATA->m_depth = 1; | |
323 | ||
324 | if ((value == BitmapFileInvalid) || | |
325 | (value == BitmapOpenFailed) || | |
326 | (value == BitmapNoMemory)) | |
4bb6408c | 327 | { |
4bb6408c | 328 | } |
f97c9854 | 329 | else |
4bb6408c | 330 | { |
f97c9854 JS |
331 | XColor foreground_color; |
332 | XColor background_color; | |
333 | foreground_color.pixel = BlackPixel(dpy, screen_num); | |
334 | background_color.pixel = WhitePixel(dpy, screen_num); | |
335 | Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); | |
336 | XQueryColor(dpy, cmap, &foreground_color); | |
337 | XQueryColor(dpy, cmap, &background_color); | |
338 | ||
339 | // TODO: how do we determine whether hotX, hotY were read correctly? | |
340 | if (hotX < 0 || hotY < 0) | |
341 | { | |
342 | hotX = hotSpotX; | |
343 | hotY = hotSpotY; | |
344 | } | |
345 | if (hotX < 0 || hotY < 0) | |
346 | { | |
347 | hotX = 0; | |
348 | hotY = 0; | |
349 | } | |
350 | ||
351 | Pixmap mask_pixmap = None; | |
352 | Cursor cursor = XCreatePixmapCursor (dpy, | |
353 | pixmap, | |
354 | mask_pixmap, | |
355 | &foreground_color, | |
356 | &background_color, | |
357 | hotX, | |
358 | hotY); | |
359 | ||
360 | XFreePixmap( dpy, pixmap ); | |
361 | if (cursor) | |
362 | { | |
363 | wxXCursor *c = new wxXCursor; | |
364 | ||
365 | c->m_cursor = (WXCursor) cursor; | |
366 | c->m_display = (WXDisplay*) dpy; | |
367 | M_CURSORDATA->m_cursors.Append(c); | |
368 | M_CURSORDATA->m_ok = TRUE; | |
369 | } | |
4bb6408c | 370 | } |
f97c9854 JS |
371 | |
372 | } | |
373 | ||
374 | // Cursors by stock number | |
375 | wxCursor::wxCursor(wxStockCursor id) | |
376 | { | |
377 | m_refData = new wxCursorRefData; | |
378 | M_CURSORDATA->m_cursorId = id; | |
47bc1060 | 379 | M_CURSORDATA->m_ok = TRUE; |
f97c9854 | 380 | |
47bc1060 JS |
381 | WXDisplay* display = wxGetDisplay(); |
382 | if (!display) | |
383 | return; | |
384 | ||
385 | WXCursor cursor = GetXCursor(display); | |
f97c9854 | 386 | if (cursor) |
4bb6408c | 387 | { |
f97c9854 JS |
388 | wxXCursor* c = new wxXCursor; |
389 | c->m_cursor = cursor; | |
390 | c->m_display = wxGetDisplay(); | |
391 | M_CURSORDATA->m_cursors.Append(c); | |
392 | M_CURSORDATA->m_ok = TRUE; | |
4bb6408c | 393 | } |
f97c9854 JS |
394 | } |
395 | ||
396 | wxCursor::~wxCursor() | |
397 | { | |
398 | } | |
399 | ||
400 | // Motif-specific: create/get a cursor for the current display | |
401 | WXCursor wxCursor::GetXCursor(WXDisplay* display) | |
402 | { | |
403 | if (!M_CURSORDATA) | |
404 | return (WXCursor) 0; | |
405 | wxNode* node = M_CURSORDATA->m_cursors.First(); | |
406 | while (node) | |
4bb6408c | 407 | { |
f97c9854 JS |
408 | wxXCursor* c = (wxXCursor*) node->Data(); |
409 | if (c->m_display == display) | |
410 | return c->m_cursor; | |
411 | node = node->Next(); | |
4bb6408c | 412 | } |
f97c9854 JS |
413 | |
414 | // No cursor for this display, so let's see if we're an id-type cursor. | |
415 | ||
416 | if (M_CURSORDATA->m_cursorId != wxCURSOR_NONE) | |
4bb6408c | 417 | { |
f97c9854 JS |
418 | WXCursor cursor = MakeCursor(display, M_CURSORDATA->m_cursorId); |
419 | if (cursor) | |
420 | { | |
421 | wxXCursor* c = new wxXCursor; | |
422 | c->m_cursor = cursor; | |
423 | c->m_display = display; | |
424 | M_CURSORDATA->m_cursors.Append(c); | |
425 | return cursor; | |
426 | } | |
427 | else | |
428 | return (WXCursor) 0; | |
4bb6408c | 429 | } |
4bb6408c | 430 | |
f97c9854 JS |
431 | // Not an id-type cursor, so we don't know how to create it. |
432 | return (WXCursor) 0; | |
4bb6408c JS |
433 | } |
434 | ||
f97c9854 JS |
435 | // Make a cursor from standard id |
436 | WXCursor wxCursor::MakeCursor(WXDisplay* display, wxStockCursor id) | |
4bb6408c | 437 | { |
f97c9854 JS |
438 | Display* dpy = (Display*) display; |
439 | Cursor cursor = (Cursor) 0; | |
440 | ||
441 | switch (id) | |
442 | { | |
443 | case wxCURSOR_WAIT: | |
444 | { | |
445 | cursor = XCreateFontCursor (dpy, XC_watch); | |
446 | break; | |
447 | } | |
448 | case wxCURSOR_CROSS: | |
449 | { | |
450 | cursor = XCreateFontCursor (dpy, XC_crosshair); | |
451 | break; | |
452 | } | |
453 | case wxCURSOR_CHAR: | |
454 | { | |
455 | // Nothing | |
456 | break; | |
457 | } | |
458 | case wxCURSOR_HAND: | |
459 | { | |
460 | cursor = XCreateFontCursor (dpy, XC_hand1); | |
461 | break; | |
462 | } | |
463 | case wxCURSOR_BULLSEYE: | |
464 | { | |
465 | cursor = XCreateFontCursor (dpy, XC_target); | |
466 | break; | |
467 | } | |
468 | case wxCURSOR_PENCIL: | |
469 | { | |
470 | cursor = XCreateFontCursor (dpy, XC_pencil); | |
471 | break; | |
472 | } | |
473 | case wxCURSOR_MAGNIFIER: | |
474 | { | |
475 | cursor = XCreateFontCursor (dpy, XC_sizing); | |
476 | break; | |
477 | } | |
478 | case wxCURSOR_IBEAM: | |
479 | { | |
480 | cursor = XCreateFontCursor (dpy, XC_xterm); | |
481 | break; | |
482 | } | |
483 | case wxCURSOR_NO_ENTRY: | |
484 | { | |
485 | cursor = XCreateFontCursor (dpy, XC_pirate); | |
486 | break; | |
487 | } | |
488 | case wxCURSOR_LEFT_BUTTON: | |
489 | { | |
490 | cursor = XCreateFontCursor (dpy, XC_leftbutton); | |
491 | break; | |
492 | } | |
493 | case wxCURSOR_RIGHT_BUTTON: | |
494 | { | |
495 | cursor = XCreateFontCursor (dpy, XC_rightbutton); | |
496 | break; | |
497 | } | |
498 | case wxCURSOR_MIDDLE_BUTTON: | |
499 | { | |
500 | cursor = XCreateFontCursor (dpy, XC_middlebutton); | |
501 | break; | |
502 | } | |
503 | case wxCURSOR_QUESTION_ARROW: | |
504 | { | |
505 | cursor = XCreateFontCursor (dpy, XC_question_arrow); | |
506 | break; | |
507 | } | |
508 | case wxCURSOR_SIZING: | |
509 | { | |
510 | cursor = XCreateFontCursor (dpy, XC_sizing); | |
511 | break; | |
512 | } | |
513 | case wxCURSOR_WATCH: | |
514 | { | |
515 | cursor = XCreateFontCursor (dpy, XC_watch); | |
516 | break; | |
517 | } | |
518 | case wxCURSOR_SPRAYCAN: | |
519 | { | |
520 | cursor = XCreateFontCursor (dpy, XC_spraycan); | |
521 | break; | |
522 | } | |
523 | case wxCURSOR_PAINT_BRUSH: | |
524 | { | |
525 | cursor = XCreateFontCursor (dpy, XC_spraycan); | |
526 | break; | |
527 | } | |
528 | case wxCURSOR_SIZENWSE: | |
529 | case wxCURSOR_SIZENESW: | |
530 | { | |
531 | // Not available in X | |
532 | cursor = XCreateFontCursor (dpy, XC_crosshair); | |
533 | break; | |
534 | } | |
535 | case wxCURSOR_SIZEWE: | |
536 | { | |
537 | cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow); | |
538 | break; | |
539 | } | |
540 | case wxCURSOR_SIZENS: | |
541 | { | |
542 | cursor = XCreateFontCursor (dpy, XC_sb_v_double_arrow); | |
543 | break; | |
544 | } | |
545 | case wxCURSOR_POINT_LEFT: | |
546 | { | |
547 | cursor = XCreateFontCursor (dpy, XC_sb_left_arrow); | |
548 | break; | |
549 | } | |
550 | case wxCURSOR_POINT_RIGHT: | |
551 | { | |
552 | cursor = XCreateFontCursor (dpy, XC_sb_right_arrow); | |
553 | break; | |
554 | } | |
555 | // (JD Huggins) added more stock cursors for X | |
556 | // X-only cursors BEGIN | |
557 | case wxCURSOR_CROSS_REVERSE: | |
558 | { | |
559 | cursor = XCreateFontCursor(dpy, XC_cross_reverse); | |
560 | break; | |
561 | } | |
562 | case wxCURSOR_DOUBLE_ARROW: | |
563 | { | |
564 | cursor = XCreateFontCursor(dpy, XC_double_arrow); | |
565 | break; | |
566 | } | |
567 | case wxCURSOR_BASED_ARROW_UP: | |
568 | { | |
569 | cursor = XCreateFontCursor(dpy, XC_based_arrow_up); | |
570 | break; | |
571 | } | |
572 | case wxCURSOR_BASED_ARROW_DOWN: | |
573 | { | |
574 | cursor = XCreateFontCursor(dpy, XC_based_arrow_down); | |
575 | break; | |
576 | } | |
577 | default: | |
578 | case wxCURSOR_ARROW: | |
579 | { | |
580 | cursor = XCreateFontCursor (dpy, XC_top_left_arrow); | |
581 | break; | |
582 | } | |
583 | case wxCURSOR_BLANK: | |
584 | { | |
585 | GC gc; | |
586 | XGCValues gcv; | |
587 | Pixmap empty_pixmap; | |
588 | XColor blank_color; | |
589 | ||
590 | empty_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)), | |
591 | 16, 16, 1); | |
592 | gcv.function = GXxor; | |
593 | gc = XCreateGC (dpy, | |
594 | empty_pixmap, | |
595 | GCFunction, | |
596 | &gcv); | |
597 | XCopyArea (dpy, | |
598 | empty_pixmap, | |
599 | empty_pixmap, | |
600 | gc, | |
601 | 0, 0, | |
602 | 16, 16, | |
603 | 0, 0); | |
604 | XFreeGC (dpy, gc); | |
605 | cursor = XCreatePixmapCursor (dpy, | |
606 | empty_pixmap, | |
607 | empty_pixmap, | |
608 | &blank_color, | |
609 | &blank_color, | |
610 | 8, 8); | |
611 | ||
612 | break; | |
613 | } | |
614 | } | |
615 | return (WXCursor) cursor; | |
4bb6408c JS |
616 | } |
617 | ||
618 | // Global cursor setting | |
f9e02ac7 | 619 | void wxSetCursor(const wxCursor& WXUNUSED(cursor)) |
4bb6408c | 620 | { |
f97c9854 | 621 | // Nothing to do for Motif (no global cursor) |
4bb6408c JS |
622 | } |
623 | ||
624 | ||
707440dc JS |
625 | // ---------------------------------------------------------------------------- |
626 | // busy cursor stuff | |
627 | // ---------------------------------------------------------------------------- | |
628 | ||
629 | static int wxBusyCursorCount = 0; | |
630 | ||
631 | // Helper function | |
632 | static void | |
633 | wxXSetBusyCursor (wxWindow * win, wxCursor * cursor) | |
634 | { | |
635 | Display *display = (Display*) win->GetXDisplay(); | |
636 | ||
637 | Window xwin = (Window) win->GetXWindow(); | |
638 | if (!xwin) | |
639 | return; | |
640 | ||
641 | XSetWindowAttributes attrs; | |
642 | ||
643 | if (cursor) | |
644 | { | |
645 | attrs.cursor = (Cursor) cursor->GetXCursor(display); | |
646 | } | |
647 | else | |
648 | { | |
649 | // Restore old cursor | |
650 | if (win->GetCursor().Ok()) | |
651 | attrs.cursor = (Cursor) win->GetCursor().GetXCursor(display); | |
652 | else | |
653 | attrs.cursor = None; | |
654 | } | |
655 | if (xwin) | |
656 | XChangeWindowAttributes (display, xwin, CWCursor, &attrs); | |
657 | ||
658 | XFlush (display); | |
659 | ||
660 | for(wxNode *node = win->GetChildren().First (); node; node = node->Next()) | |
661 | { | |
662 | wxWindow *child = (wxWindow *) node->Data (); | |
663 | wxXSetBusyCursor (child, cursor); | |
664 | } | |
665 | } | |
666 | ||
667 | // Set the cursor to the busy cursor for all windows | |
668 | void wxBeginBusyCursor(wxCursor *cursor) | |
669 | { | |
670 | wxBusyCursorCount++; | |
671 | if (wxBusyCursorCount == 1) | |
672 | { | |
673 | for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next()) | |
674 | { | |
675 | wxWindow *win = (wxWindow *) node->Data (); | |
676 | wxXSetBusyCursor (win, cursor); | |
677 | } | |
678 | } | |
679 | } | |
680 | ||
681 | // Restore cursor to normal | |
682 | void wxEndBusyCursor() | |
683 | { | |
684 | if (wxBusyCursorCount == 0) | |
685 | return; | |
686 | ||
687 | wxBusyCursorCount--; | |
688 | if (wxBusyCursorCount == 0) | |
689 | { | |
690 | for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next()) | |
691 | { | |
692 | wxWindow *win = (wxWindow *) node->Data (); | |
693 | wxXSetBusyCursor (win, NULL); | |
694 | } | |
695 | } | |
696 | } | |
697 | ||
698 | // TRUE if we're between the above two calls | |
699 | bool wxIsBusy() | |
700 | { | |
701 | return (wxBusyCursorCount > 0); | |
702 | } |