blob: 1cb5c74783f950118be15196ecca55ca400d7e3d [file] [log] [blame]
DRC8e631682011-06-23 08:28:18 +00001*** fltk-1.3.0/CMakeLists.txt 2011-01-06 04:24:58.000000000 -0600
2--- fltk/CMakeLists.txt 2011-06-22 23:01:51.000000000 -0500
3***************
4*** 62,65 ****
5--- 62,66 ----
6 set(HAVE_DIRENT_H 1)
7 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa")
8+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Carbon")
9 endif(APPLE)
10
11*** fltk-1.3.0/FL/Enumerations.H 2011-05-21 16:55:59.000000000 -0500
12--- fltk/FL/Enumerations.H 2011-06-22 22:35:32.000000000 -0500
13***************
14*** 293,297 ****
15 following FL_PASTE event.
16 */
17! FL_DND_RELEASE = 23
18 };
19
20--- 293,302 ----
21 following FL_PASTE event.
22 */
23! FL_DND_RELEASE = 23,
24!
25! /** The fullscreen state of the window has changed
26! */
27! FL_FULLSCREEN = 24
28!
29 };
30
31***************
32*** 875,907 ****
33 /** The following constants define the mouse cursors that are available in FLTK.
34
35! The double-headed arrows are bitmaps provided by FLTK on X, the others
36! are provided by system-defined cursors.
37
38 \todo enum Fl_Cursor needs maybe an image.
Pierre Ossman554b3ee2011-06-09 10:47:19 +000039 */
DRC8e631682011-06-23 08:28:18 +000040 enum Fl_Cursor {
41! FL_CURSOR_DEFAULT = 0, /**< the default cursor, usually an arrow. */
42! FL_CURSOR_ARROW = 35, /**< an arrow pointer. */
43! FL_CURSOR_CROSS = 66, /**< crosshair. */
44! FL_CURSOR_WAIT = 76, /**< watch or hourglass. */
45! FL_CURSOR_INSERT = 77, /**< I-beam. */
46! FL_CURSOR_HAND = 31, /**< hand (uparrow on MSWindows). */
47! FL_CURSOR_HELP = 47, /**< question mark. */
48! FL_CURSOR_MOVE = 27, /**< 4-pointed arrow. */
49! // fltk provides bitmaps for these:
50! FL_CURSOR_NS = 78, /**< up/down arrow. */
51! FL_CURSOR_WE = 79, /**< left/right arrow. */
52! FL_CURSOR_NWSE = 80, /**< diagonal arrow. */
53! FL_CURSOR_NESW = 81, /**< diagonal arrow. */
54! FL_CURSOR_NONE =255, /**< invisible. */
55! // for back compatibility (non MSWindows ones):
56! FL_CURSOR_N = 70, /**< for back compatibility. */
57! FL_CURSOR_NE = 69, /**< for back compatibility. */
58! FL_CURSOR_E = 49, /**< for back compatibility. */
59! FL_CURSOR_SE = 8, /**< for back compatibility. */
60! FL_CURSOR_S = 9, /**< for back compatibility. */
61! FL_CURSOR_SW = 7, /**< for back compatibility. */
62! FL_CURSOR_W = 36, /**< for back compatibility. */
63! FL_CURSOR_NW = 68 /**< for back compatibility. */
64 };
65 /*@}*/ // group: Cursors
66--- 880,913 ----
67 /** The following constants define the mouse cursors that are available in FLTK.
68
69! Cursors are provided by the system when available, or bitmaps built into
70! FLTK as a fallback.
71
72 \todo enum Fl_Cursor needs maybe an image.
73 */
74 enum Fl_Cursor {
75! FL_CURSOR_DEFAULT = 0, /**< the default cursor, usually an arrow. */
76! FL_CURSOR_ARROW = 1, /**< an arrow pointer. */
77! FL_CURSOR_CROSS = 2, /**< crosshair. */
78! FL_CURSOR_WAIT = 3, /**< busy indicator (e.g. hourglass). */
79! FL_CURSOR_INSERT = 4, /**< I-beam. */
80! FL_CURSOR_HAND = 5, /**< pointing hand. */
81! FL_CURSOR_HELP = 6, /**< question mark pointer. */
82! FL_CURSOR_MOVE = 7, /**< 4-pointed arrow or hand. */
83!
84! /* Resize indicators */
85! FL_CURSOR_NS = 101, /**< up/down resize. */
86! FL_CURSOR_WE = 102, /**< left/right resize. */
87! FL_CURSOR_NWSE = 103, /**< diagonal resize. */
88! FL_CURSOR_NESW = 104, /**< diagonal resize. */
89! FL_CURSOR_NE = 110, /**< upwards, right resize. */
90! FL_CURSOR_N = 111, /**< upwards resize. */
91! FL_CURSOR_NW = 112, /**< upwards, left resize. */
92! FL_CURSOR_E = 113, /**< leftwards resize. */
93! FL_CURSOR_W = 114, /**< rightwards resize. */
94! FL_CURSOR_SE = 115, /**< downwards, right resize. */
95! FL_CURSOR_S = 116, /**< downwards resize. */
96! FL_CURSOR_SW = 117, /**< downwards, left resize. */
97!
98! FL_CURSOR_NONE = 255, /**< invisible. */
99 };
100 /*@}*/ // group: Cursors
101*** fltk-1.3.0/FL/Fl.H 2011-05-23 13:01:29.000000000 -0500
102--- fltk/FL/Fl.H 2011-06-22 22:35:31.000000000 -0500
103***************
104*** 109,112 ****
105--- 109,115 ----
106 typedef int (*Fl_Event_Dispatch)(int event, Fl_Window *w);
107
108+ /** Signature of add_clipboard_notify functions passed as parameters */
109+ typedef void (*Fl_Clipboard_Notify_Handler)(int source, void *data);
110+
111 /** @} */ /* group callback_functions */
112
113***************
114*** 745,748 ****
115--- 748,764 ----
116 static void paste(Fl_Widget &receiver, int source /*=0*/); // platform dependent
117 /**
118+ FLTK will call the registered callback whenever there is a change to the
119+ selection buffer or the clipboard. The source argument indicates which
120+ of the two has changed. Only changes by other applications are reported.
121+ \note Some systems require polling to monitor the clipboard and may
122+ therefore have some delay in detecting changes.
Pierre Ossman554b3ee2011-06-09 10:47:19 +0000123+ */
DRC8e631682011-06-23 08:28:18 +0000124+ static void add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data);
125+ /**
126+ Stop calling the specified callback when there are changes to the selection
127+ buffer or the clipboard.
128+ */
129+ static void remove_clipboard_notify(Fl_Clipboard_Notify_Handler h);
130+ /**
131 Initiate a Drag And Drop operation. The selection buffer should be
132 filled with relevant data before calling this method. FLTK will
133*** fltk-1.3.0/FL/Fl_Image.H 2011-01-30 03:24:40.000000000 -0600
134--- fltk/FL/Fl_Image.H 2011-06-22 22:35:32.000000000 -0500
135***************
136*** 35,38 ****
137--- 35,39 ----
138
139 class Fl_Widget;
140+ class Fl_Pixmap;
141 struct Fl_Menu_Item;
142 struct Fl_Label;
143***************
144*** 197,200 ****
145--- 198,202 ----
146 Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0) :
147 Fl_Image(W,H,D), array(bits), alloc_array(0), id_(0), mask_(0) {data((const char **)&array, 1); ld(LD);}
148+ Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg=FL_GRAY);
149 virtual ~Fl_RGB_Image();
150 virtual Fl_Image *copy(int W, int H);
151*** fltk-1.3.0/FL/Fl_Widget.H 2011-04-24 12:09:41.000000000 -0500
152--- fltk/FL/Fl_Widget.H 2011-06-22 22:41:26.000000000 -0500
153***************
154*** 109,112 ****
155--- 109,113 ----
156 class FL_EXPORT Fl_Widget {
157 friend class Fl_Group;
158+ friend class Fl_X;
159
160 Fl_Group* parent_;
161***************
162*** 180,183 ****
163--- 181,186 ----
164 GROUP_RELATIVE = 1<<16, ///< position this widget relative to the parent group, not to the window
165 COPIED_TOOLTIP = 1<<17, ///< the widget tooltip is internally copied, its destruction is handled by the widget
166+ SIMPLE_KEYBOARD = 1<<18, ///< the widget wants simple, consistent keypresses and not advanced input (like character composition and CJK input)
167+ FULLSCREEN = 1<<19, ///< a fullscreen window (Fl_Window)
168 // (space for more flags)
169 USERFLAG3 = 1<<29, ///< reserved for 3rd party extensions
170***************
171*** 785,788 ****
172--- 788,820 ----
173 void clear_changed() {flags_ &= ~CHANGED;}
174
175+ /**
176+ Returns if the widget sees a simplified keyboard model or not.
177+
178+ Normally widgets get a full-featured keyboard model that is geared
179+ towards text input. This includes support for compose sequences and
180+ advanced input methods, commonly used for asian writing system. This
181+ system however has downsides in that extra graphic can be presented
182+ to the user and that a physical key press doesn't correspond directly
183+ to a FLTK event.
184+
185+ Widgets that need a direct correspondence between actual key events
186+ and those seen by the widget can swith to the simplified keyboard
187+ model.
188+
189+ \retval 0 if the widget uses the normal keyboard model
190+ \see set_changed(), clear_changed()
191+ */
192+ unsigned int simple_keyboard() const {return flags_&SIMPLE_KEYBOARD;}
193+
194+ /** Marks a widget to use the simple keyboard model.
195+ \see changed(), clear_changed()
196+ */
197+ void set_simple_keyboard() {flags_ |= SIMPLE_KEYBOARD;}
198+
199+ /** Marks a widget to use the normal keyboard model.
200+ \see changed(), set_changed()
201+ */
202+ void set_normal_keyboard() {flags_ &= ~SIMPLE_KEYBOARD;}
203+
204 /** Gives the widget the keyboard focus.
205 Tries to make this widget be the Fl::focus() widget, by first sending
206***************
207*** 853,856 ****
208--- 885,891 ----
209 /* Internal use only. */
210 static int test_shortcut(const char*, const bool require_alt = false);
211+ /* Internal use only. */
212+ void _set_fullscreen() {flags_ |= FULLSCREEN;}
213+ void _clear_fullscreen() {flags_ &= ~FULLSCREEN;}
214
215 /** Checks if w is a child of this widget.
216*** fltk-1.3.0/FL/Fl_Window.H 2011-04-15 16:38:05.000000000 -0500
217--- fltk/FL/Fl_Window.H 2011-06-22 22:35:32.000000000 -0500
218***************
219*** 38,41 ****
220--- 38,42 ----
221
222 class Fl_X;
223+ class Fl_RGB_Image;
224
225 /**
226***************
227*** 70,76 ****
228 int dw, dh, aspect;
229 uchar size_range_set;
230 // cursor stuff
231 Fl_Cursor cursor_default;
232- Fl_Color cursor_fg, cursor_bg;
233 void size_range_();
234 void _Fl_Window(); // constructor innards
235--- 71,77 ----
236 int dw, dh, aspect;
237 uchar size_range_set;
238+ int no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h;
239 // cursor stuff
240 Fl_Cursor cursor_default;
241 void size_range_();
242 void _Fl_Window(); // constructor innards
243***************
244*** 385,392 ****
245 Makes the window completely fill the screen, without any window
246 manager border visible. You must use fullscreen_off() to undo
247! this. This may not work with all window managers.
248 */
249 void fullscreen();
250 /**
251 Turns off any side effects of fullscreen() and does
252 resize(x,y,w,h).
253--- 386,401 ----
254 Makes the window completely fill the screen, without any window
255 manager border visible. You must use fullscreen_off() to undo
256! this.
257!
258! \note On some platforms, this can result in the keyboard being
259! grabbed. The window may also be recreated, meaning hide() and
260! show() will be called.
261 */
262 void fullscreen();
263 /**
264+ Turns off any side effects of fullscreen()
265+ */
266+ void fullscreen_off();
267+ /**
268 Turns off any side effects of fullscreen() and does
269 resize(x,y,w,h).
270***************
271*** 394,397 ****
272--- 403,410 ----
273 void fullscreen_off(int,int,int,int);
274 /**
275+ Returns non zero if FULLSCREEN flag is set, 0 otherwise.
276+ */
277+ unsigned int fullscreen_active() const { return flags() & FULLSCREEN; }
278+ /**
279 Iconifies the window. If you call this when shown() is false
280 it will show() it as an icon. If the window is already
281***************
282*** 435,446 ****
283
284 The type Fl_Cursor is an enumeration defined in <FL/Enumerations.H>.
285- (Under X you can get any XC_cursor value by passing
286- Fl_Cursor((XC_foo/2)+1)). The colors only work on X, they are
287- not implemented on WIN32.
288
289! For back compatibility only.
290 */
291! void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); // platform dependent
292! void default_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE);
293 static void default_callback(Fl_Window*, void* v);
294
295--- 448,462 ----
296
297 The type Fl_Cursor is an enumeration defined in <FL/Enumerations.H>.
298
299! \see cursor(const Fl_RGB_Image*, int, int), default_cursor()
300 */
301! void cursor(Fl_Cursor);
302! void cursor(const Fl_RGB_Image*, int, int);
303! void default_cursor(Fl_Cursor);
304!
305! /* for legacy compatibility */
306! void cursor(Fl_Cursor c, Fl_Color, Fl_Color=FL_WHITE) { cursor(c); };
307! void default_cursor(Fl_Cursor c, Fl_Color, Fl_Color=FL_WHITE) { default_cursor(c); };
308!
309 static void default_callback(Fl_Window*, void* v);
310
311*** fltk-1.3.0/FL/fl_draw.H 2011-06-02 03:06:09.000000000 -0500
312--- fltk/FL/fl_draw.H 2011-06-22 22:35:32.000000000 -0500
313***************
314*** 758,762 ****
315 FL_EXPORT void fl_overlay_rect(int x,int y,int w,int h);
316 FL_EXPORT void fl_overlay_clear();
317! FL_EXPORT void fl_cursor(Fl_Cursor, Fl_Color fg=FL_BLACK, Fl_Color bg=FL_WHITE);
318 FL_EXPORT const char* fl_expand_text(const char* from, char* buf, int maxbuf,
319 double maxw, int& n, double &width,
320--- 758,763 ----
321 FL_EXPORT void fl_overlay_rect(int x,int y,int w,int h);
322 FL_EXPORT void fl_overlay_clear();
323! FL_EXPORT void fl_cursor(Fl_Cursor);
324! FL_EXPORT void fl_cursor(Fl_Cursor, Fl_Color fg, Fl_Color bg=FL_WHITE);
325 FL_EXPORT const char* fl_expand_text(const char* from, char* buf, int maxbuf,
326 double maxw, int& n, double &width,
327*** fltk-1.3.0/FL/mac.H 2011-05-12 06:50:43.000000000 -0500
328--- fltk/FL/mac.H 2011-06-22 22:35:32.000000000 -0500
329***************
330*** 142,146 ****
331 WindowRef window_ref(void);
332 void set_key_window(void);
333! void set_cursor(Fl_Cursor);
334 static CGImageRef CGImage_from_window_rect(Fl_Window *win, int x, int y, int w, int h);
335 static unsigned char *bitmap_from_window_rect(Fl_Window *win, int x, int y, int w, int h, int *bytesPerPixel);
336--- 142,147 ----
337 WindowRef window_ref(void);
338 void set_key_window(void);
339! int set_cursor(Fl_Cursor);
340! int set_cursor(const Fl_RGB_Image*, int, int);
341 static CGImageRef CGImage_from_window_rect(Fl_Window *win, int x, int y, int w, int h);
342 static unsigned char *bitmap_from_window_rect(Fl_Window *win, int x, int y, int w, int h, int *bytesPerPixel);
343*** fltk-1.3.0/FL/names.h 2010-11-28 15:06:39.000000000 -0600
344--- fltk/FL/names.h 2011-06-22 22:35:32.000000000 -0500
345***************
346*** 76,79 ****
347--- 76,80 ----
348 "FL_DND_LEAVE",
349 "FL_DND_RELEASE",
350+ "FL_FULLSCREEN"
351 };
352
353*** fltk-1.3.0/FL/win32.H 2011-05-23 13:32:47.000000000 -0500
354--- fltk/FL/win32.H 2011-06-22 22:35:32.000000000 -0500
355***************
356*** 93,96 ****
357--- 93,98 ----
358 void set_minmax(LPMINMAXINFO minmax);
359 void mapraise();
360+ int set_cursor(Fl_Cursor);
361+ int set_cursor(const Fl_RGB_Image*, int, int);
362 static Fl_X* make(Fl_Window*);
363 };
364*** fltk-1.3.0/FL/x.H 2011-05-21 05:05:19.000000000 -0500
365--- fltk/FL/x.H 2011-06-22 22:35:32.000000000 -0500
366***************
367*** 164,167 ****
368--- 164,169 ----
369 void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
370 void sendxjunk();
371+ int set_cursor(Fl_Cursor);
372+ int set_cursor(const Fl_RGB_Image*, int, int);
373 static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, Colormap=fl_colormap);
374 static Fl_X* set_xid(Fl_Window*, Window);
375*** fltk-1.3.0/configh.in 2011-06-09 11:21:40.000000000 -0500
376--- fltk/configh.in 2011-06-22 22:35:32.000000000 -0500
377***************
378*** 118,121 ****
379--- 118,137 ----
380
381 /*
382+ * HAVE_XFIXES:
383+ *
384+ * Do we have the X fixes extension?
Pierre Ossman554b3ee2011-06-09 10:47:19 +0000385+ */
DRC8e631682011-06-23 08:28:18 +0000386+
387+ #define HAVE_XFIXES 0
388+
389+ /*
390+ * HAVE_XCURSOR:
391+ *
392+ * Do we have the X cursor library?
Pierre Ossman554b3ee2011-06-09 10:47:19 +0000393+ */
DRC8e631682011-06-23 08:28:18 +0000394+
395+ #define HAVE_XCURSOR 0
396+
397+ /*
398 * __APPLE_QUARTZ__:
399 *
400*** fltk-1.3.0/configure.in 2011-03-06 10:54:58.000000000 -0600
401--- fltk/configure.in 2011-06-22 22:35:32.000000000 -0500
402***************
403*** 875,878 ****
404--- 875,880 ----
405 # MacOS X uses Cocoa for graphics.
406 LIBS="$LIBS -framework Cocoa"
407+ # And some Carbon for keyboard handling
408+ LIBS="$LIBS -framework Carbon"
409
410 if test x$have_pthread = xyes; then
411***************
412*** 1007,1010 ****
413--- 1009,1032 ----
414 fi
415
416+ dnl Check for the Xfixes extension unless disabled...
417+ AC_ARG_ENABLE(xfixes, [ --enable-xfixes turn on Xfixes support [default=yes]])
418+
419+ if test x$enable_xfixes != xno; then
420+ AC_CHECK_HEADER(X11/extensions/Xfixes.h, AC_DEFINE(HAVE_XFIXES),,
421+ [#include <X11/Xlib.h>])
422+ AC_CHECK_LIB(Xfixes, XFixesQueryExtension,
423+ LIBS="-lXfixes $LIBS")
424+ fi
425+
426+ dnl Check for the Xcursor library unless disabled...
427+ AC_ARG_ENABLE(xcursor, [ --enable-xcursor turn on Xcursor support [default=yes]])
428+
429+ if test x$enable_xcursor != xno; then
430+ AC_CHECK_HEADER(X11/Xcursor/Xcursor.h, AC_DEFINE(HAVE_XCURSOR),,
431+ [#include <X11/Xlib.h>])
432+ AC_CHECK_LIB(Xcursor, XcursorImageCreate,
433+ LIBS="-lXcursor $LIBS")
434+ fi
435+
436 dnl Check for overlay visuals...
437 AC_PATH_PROG(XPROP, xprop)
438*** fltk-1.3.0/documentation/src/enumerations.dox 2011-05-11 10:49:30.000000000 -0500
439--- fltk/documentation/src/enumerations.dox 2011-06-22 22:35:32.000000000 -0500
440***************
441*** 58,61 ****
442--- 58,62 ----
443 data.
444 \li FL_DND_RELEASE - Dragged data is about to be dropped.
445+ \li FL_FULLSCREEN - The fullscreen state of the window has changed.
446
447
448*** fltk-1.3.0/documentation/src/events.dox 2011-05-11 10:49:30.000000000 -0500
449--- fltk/documentation/src/events.dox 2011-06-22 22:35:32.000000000 -0500
450***************
451*** 301,304 ****
452--- 301,311 ----
453 the immediately following \p FL_PASTE event.
454
455+ \subsection events_fl_fullscreen FL_FULLSCREEN
456+
457+ The application window has been changed from normal to fullscreen, or
458+ from fullscreen to normal. If you are using a X window manager which
459+ supports Extended Window Manager Hints, this event will not be
460+ delivered until the change has actually happened.
461+
462
463 \section events_event_xxx Fl::event_*() methods
464*** fltk-1.3.0/src/Fl.cxx 2011-05-23 11:49:02.000000000 -0500
465--- fltk-1.3.0.new/src/Fl.cxx 2011-06-22 22:35:32.000000000 -0500
466***************
467*** 80,83 ****
468--- 80,85 ----
469 #endif // WIN32
470
471+ extern void fl_update_focus(void);
472+
473 //
474 // Globals...
475***************
476*** 445,448 ****
477--- 447,513 ----
478
479 ////////////////////////////////////////////////////////////////
480+ // Clipboard notifications
481+
482+ struct Clipboard_Notify {
483+ Fl_Clipboard_Notify_Handler handler;
484+ void *data;
485+ struct Clipboard_Notify *next;
486+ };
487+
488+ static struct Clipboard_Notify *clip_notify_list = NULL;
489+
490+ extern void fl_clipboard_notify_change(); // in Fl_<platform>.cxx
491+
492+ void Fl::add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data) {
493+ struct Clipboard_Notify *node;
494+
495+ remove_clipboard_notify(h);
496+
497+ node = new Clipboard_Notify;
498+
499+ node->handler = h;
500+ node->data = data;
501+ node->next = clip_notify_list;
502+
503+ clip_notify_list = node;
504+
505+ fl_clipboard_notify_change();
506+ }
507+
508+ void Fl::remove_clipboard_notify(Fl_Clipboard_Notify_Handler h) {
509+ struct Clipboard_Notify *node, **prev;
510+
511+ node = clip_notify_list;
512+ prev = &clip_notify_list;
513+ while (node != NULL) {
514+ if (node->handler == h) {
515+ *prev = node->next;
516+ delete node;
517+
518+ fl_clipboard_notify_change();
519+
520+ return;
521+ }
522+
523+ prev = &node->next;
524+ node = node->next;
525+ }
526+ }
527+
528+ bool fl_clipboard_notify_empty(void) {
529+ return clip_notify_list == NULL;
530+ }
531+
532+ void fl_trigger_clipboard_notify(int source) {
533+ struct Clipboard_Notify *node;
534+
535+ node = clip_notify_list;
536+ while (node != NULL) {
537+ node->handler(source, node->data);
538+ node = node->next;
539+ }
540+ }
541+
542+ ////////////////////////////////////////////////////////////////
543 // wait/run/check/ready:
544
545***************
546*** 881,884 ****
547--- 946,951 ----
548 }
549 e_number = old_event;
550+ // let the platform code do what it needs
551+ fl_update_focus();
552 }
553 }
554***************
555*** 1362,1366 ****
556 // hide() destroys the X window, it does not do unmap!
557
558! #if !defined(WIN32) && USE_XFT
559 extern void fl_destroy_xft_draw(Window);
560 #endif
561--- 1429,1436 ----
562 // hide() destroys the X window, it does not do unmap!
563
564! #if defined(WIN32)
565! extern void fl_clipboard_notify_untarget(HWND wnd);
566! extern void fl_update_clipboard(void);
567! #elif USE_XFT
568 extern void fl_destroy_xft_draw(Window);
569 #endif
570***************
571*** 1409,1420 ****
572 // this little trick keeps the current clipboard alive, even if we are about
573 // to destroy the window that owns the selection.
574! if (GetClipboardOwner()==ip->xid) {
575! Fl_Window *w1 = Fl::first_window();
576! if (w1 && OpenClipboard(fl_xid(w1))) {
577! EmptyClipboard();
578! SetClipboardData(CF_TEXT, NULL);
579! CloseClipboard();
580! }
581! }
582 // Send a message to myself so that I'll get out of the event loop...
583 PostMessage(ip->xid, WM_APP, 0, 0);
584--- 1479,1486 ----
585 // this little trick keeps the current clipboard alive, even if we are about
586 // to destroy the window that owns the selection.
587! if (GetClipboardOwner()==ip->xid)
588! fl_update_clipboard();
589! // Make sure we unlink this window from the clipboard chain
590! fl_clipboard_notify_untarget(ip->xid);
591 // Send a message to myself so that I'll get out of the event loop...
592 PostMessage(ip->xid, WM_APP, 0, 0);
593*** fltk-1.3.0/src/Fl_Image.cxx 2011-04-20 09:01:04.000000000 -0500
594--- fltk-1.3.0.new/src/Fl_Image.cxx 2011-06-22 22:35:32.000000000 -0500
595***************
596*** 173,176 ****
597--- 173,189 ----
598 // RGB image class...
599 //
600+
601+ int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
602+
603+ /** The constructor creates a new RGBA image from the specified Fl_Pixmap. */
604+ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg):
605+ Fl_Image(pxm->w(), pxm->h(), 4), id_(0), mask_(0)
606+ {
607+ array = new uchar[w() * h() * d()];
608+ alloc_array = 1;
609+ fl_convert_pixmap(pxm->data(), (uchar*)array, bg);
610+ data((const char **)&array, 1);
611+ }
612+
613 /** The destructor free all memory and server resources that are used by the image. */
614 Fl_RGB_Image::~Fl_RGB_Image() {
615*** fltk-1.3.0/src/Fl_Window.cxx 2011-02-25 02:44:47.000000000 -0600
616--- fltk-1.3.0.new/src/Fl_Window.cxx 2011-06-22 22:35:32.000000000 -0500
617***************
618*** 60,63 ****
619--- 60,67 ----
620 size_range_set = 0;
621 minw = maxw = minh = maxh = 0;
622+ no_fullscreen_x = 0;
623+ no_fullscreen_y = 0;
624+ no_fullscreen_w = w();
625+ no_fullscreen_h = h();
626 callback((Fl_Callback*)default_callback);
627 }
628***************
629*** 66,71 ****
630 : Fl_Group(X, Y, W, H, l) {
631 cursor_default = FL_CURSOR_DEFAULT;
632- cursor_fg = FL_BLACK;
633- cursor_bg = FL_WHITE;
634
635 _Fl_Window();
636--- 70,73 ----
637***************
638*** 77,82 ****
639 : Fl_Group((Fl_Group::current(0),0), 0, W, H, l) {
640 cursor_default = FL_CURSOR_DEFAULT;
641- cursor_fg = FL_BLACK;
642- cursor_bg = FL_WHITE;
643
644 _Fl_Window();
645--- 79,82 ----
646*** fltk-1.3.0/src/Fl_Window_fullscreen.cxx 2011-03-12 15:36:21.000000000 -0600
647--- fltk-1.3.0.new/src/Fl_Window_fullscreen.cxx 2011-06-22 22:35:32.000000000 -0500
648***************
649*** 61,97 ****
650 }
651
652 void Fl_Window::fullscreen() {
653! #ifndef WIN32
654! //this would clobber the fake wm, since it relies on the border flags to
655! //determine its thickness
656! border(0);
657! #endif
658! #if defined(__APPLE__) || defined(WIN32) || defined(USE_X11)
659! int sx, sy, sw, sh;
660! Fl::screen_xywh(sx, sy, sw, sh, x(), y(), w(), h());
661! // if we are on the main screen, we will leave the system menu bar unobstructed
662! if (Fl::x()>=sx && Fl::y()>=sy && Fl::x()+Fl::w()<=sx+sw && Fl::y()+Fl::h()<=sy+sh) {
663! sx = Fl::x(); sy = Fl::y();
664! sw = Fl::w(); sh = Fl::h();
665 }
666- if (x()==sx) x(sx+1); // make sure that we actually execute the resize
667- #if defined(USE_X11)
668- resize(0, 0, w(), h()); // work around some quirks in X11
669- #endif
670- resize(sx, sy, sw, sh);
671- #else
672- if (!x()) x(1); // make sure that we actually execute the resize
673- resize(0,0,Fl::w(),Fl::h());
674- #endif
675 }
676
677 void Fl_Window::fullscreen_off(int X,int Y,int W,int H) {
678! // this order produces less blinking on IRIX:
679! resize(X,Y,W,H);
680! #ifndef WIN32
681! border(1);
682! #endif
683 }
684
685 //
686 // End of "$Id: Fl_Window_fullscreen.cxx 8515 2011-03-12 21:36:21Z manolo $".
687--- 61,106 ----
688 }
689
690+ void fullscreen_x(Fl_Window *w);
691+ void fullscreen_off_x();
692+ void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H);
693+
694+ /* Note: The previous implementation toggled border(). With this new
695+ implementation this is not necessary. Additionally, if we do that,
696+ the application may lose focus when switching out of fullscreen
697+ mode with some window managers. Besides, the API does not say that
698+ the FLTK border state should be toggled; it only says that the
699+ borders should not be *visible*.
Pierre Ossman554b3ee2011-06-09 10:47:19 +0000700+ */
DRC8e631682011-06-23 08:28:18 +0000701 void Fl_Window::fullscreen() {
702! if (shown() && !(flags() & Fl_Widget::FULLSCREEN)) {
703! no_fullscreen_x = x();
704! no_fullscreen_y = y();
705! no_fullscreen_w = w();
706! no_fullscreen_h = h();
707! fullscreen_x(this);
708! } else {
709! set_flag(FULLSCREEN);
710 }
711 }
712
713 void Fl_Window::fullscreen_off(int X,int Y,int W,int H) {
714! if (shown() && (flags() & Fl_Widget::FULLSCREEN)) {
715! fullscreen_off_x(this, X, Y, W, H);
716! } else {
717! clear_flag(FULLSCREEN);
718! }
719! no_fullscreen_x = no_fullscreen_y = no_fullscreen_w = no_fullscreen_h = 0;
720! }
721!
722! void Fl_Window::fullscreen_off() {
723! if (!no_fullscreen_x && !no_fullscreen_y) {
724! // Window was initially created fullscreen - default to current monitor
725! no_fullscreen_x = x();
726! no_fullscreen_y = y();
727! }
728! fullscreen_off(no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h);
729 }
730
731+
732 //
733 // End of "$Id: Fl_Window_fullscreen.cxx 8515 2011-03-12 21:36:21Z manolo $".
734*** fltk-1.3.0/src/Fl_cocoa.mm 2011-06-16 07:35:32.000000000 -0500
735--- fltk-1.3.0.new/src/Fl_cocoa.mm 2011-06-22 22:35:32.000000000 -0500
736***************
737*** 62,65 ****
738--- 62,66 ----
739
740 #import <Cocoa/Cocoa.h>
741+ #import <Carbon/Carbon.h>
742
743 #ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
744***************
745*** 108,112 ****
746 void *fl_system_menu; // this is really a NSMenu*
747 Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0;
748- void *fl_default_cursor; // this is really a NSCursor*
749 void *fl_capture = 0; // (NSWindow*) we need this to compensate for a missing(?) mouse capture
750 bool fl_show_iconic; // true if called from iconize() - shows the next created window in collapsed state
751--- 109,112 ----
752***************
753*** 125,128 ****
754--- 125,130 ----
755 #endif
756
757+ bool use_simple_keyboard = false;
758+
759 enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
760
761***************
762*** 141,144 ****
763--- 143,179 ----
764 }
765
766+ // Undocumented voodoo. Taken from Mozilla.
767+ #define ENABLE_ROMAN_KYBDS_ONLY -23
768+
769+ void fl_update_focus(void)
770+ {
771+ Fl_Widget *focus;
772+
773+ focus = Fl::grab();
774+ if (!focus)
775+ focus = Fl::focus();
776+ if (!focus)
777+ return;
778+
779+ if (focus->simple_keyboard())
780+ use_simple_keyboard = true;
781+ else
782+ use_simple_keyboard = false;
783+
784+ // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
785+ // Safari people seem to think implies turning off advanced IME stuff
786+ // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
787+ // in Safari/Webcore). Should be good enough for us then...
788+ #if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
789+ CFArrayRef inputSources = TISCreateASCIICapableInputSourceList();
790+ TSMSetDocumentProperty(TSMGetActiveDocument(),
791+ kTSMDocumentEnabledInputSourcesPropertyTag,
792+ sizeof(CFArrayRef), &inputSources);
793+ CFRelease(inputSources);
794+ #else
795+ KeyScript(use_simple_keyboard ? ENABLE_ROMAN_KYBDS_ONLY : smKeyEnableKybds);
796+ #endif
797+ }
798+
799 /*
800 * Mac keyboard lookup table
801***************
802*** 615,618 ****
803--- 650,657 ----
804 containsGLsubwindow = contains;
805 }
806+ - (BOOL)canBecomeKeyWindow
807+ {
808+ return YES;
809+ }
810 @end
811
812***************
813*** 844,847 ****
814--- 883,905 ----
815 @end
816
817+ static const char* cocoaDead2FLTK(const char *in)
818+ {
819+ if (strcmp(in, "\140") == 0) // GRAVE ACCENT
820+ return "\314\200"; // COMBINING GRAVE ACCENT
821+ if (strcmp(in, "\302\264") == 0) // ACUTE ACCENT
822+ return "\314\201"; // COMBINING ACUTE ACCENT
823+ if (strcmp(in, "\136") == 0) // CIRCUMFLEX ACCENT
824+ return "\314\202"; // COMBINING CIRCUMFLEX ACCENT
825+ if (strcmp(in, "\176") == 0) // TILDE
826+ return "\314\203"; // COMBINING TILDE
827+ if (strcmp(in, "\302\250") == 0) // DIAERESIS
828+ return "\314\210"; // COMBINING DIAERESIS
829+ // FIXME: OS X dead key behaviour isn't documented and I don't have
830+ // any more keyboards to test with...
831+
832+ // hope that OS X gave us something proper to begin with
833+ return in;
834+ }
835+
836 /*
837 Handle cocoa keyboard events
838***************
839*** 1034,1037 ****
840--- 1092,1099 ----
841 FLWindow *nsw = (FLWindow*)[notif object];
842 Fl_Window *window = [nsw getFl_Window];
843+ /* Fullscreen windows obscure all other windows so we need to return
844+ to a "normal" level when the user switches to another window */
845+ if (window->fullscreen_active())
846+ [nsw setLevel:NSNormalWindowLevel];
847 Fl::handle( FL_UNFOCUS, window);
848 fl_unlock_function();
849***************
850*** 1042,1045 ****
851--- 1104,1110 ----
852 FLWindow *nsw = (FLWindow*)[notif object];
853 Fl_Window *w = [nsw getFl_Window];
854+ /* Restore previous fullscreen level */
855+ if (w->fullscreen_active())
856+ [nsw setLevel:NSStatusWindowLevel];
857 if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle( FL_FOCUS, w);
858 fl_unlock_function();
859***************
860*** 1229,1235 ****
861--- 1294,1304 ----
862 @end
863
864+ static void clipboard_check(void);
865+
866 @implementation FLApplication
867 + (void)sendEvent:(NSEvent *)theEvent
868 {
869+ // update clipboard status
870+ clipboard_check();
871 NSEventType type = [theEvent type];
872 if (type == NSLeftMouseDown) {
873***************
874*** 1286,1291 ****
875 while (ign_event);
876
877- fl_default_cursor = [NSCursor arrowCursor];
878-
879 // bring the application into foreground without a 'CARB' resource
880 Boolean same_psn;
881--- 1355,1358 ----
882***************
883*** 1587,1590 ****
884--- 1654,1658 ----
885 - (BOOL)acceptsFirstResponder;
886 - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
887+ - (void)resetCursorRects;
888 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
889 - (void)mouseUp:(NSEvent *)theEvent;
890***************
891*** 1644,1647 ****
892--- 1712,1725 ----
893 return (first == w || !first->modal());
894 }
895+ - (void)resetCursorRects {
896+ Fl_Window *w = [(FLWindow*)[self window] getFl_Window];
897+ Fl_X *i = Fl_X::i(w);
898+ // We have to have at least one cursor rect for invalidateCursorRectsForView
899+ // to work, hence the "else" clause.
900+ if (i->cursor)
901+ [self addCursorRect:[self visibleRect] cursor:(NSCursor*)i->cursor];
902+ else
903+ [self addCursorRect:[self visibleRect] cursor:[NSCursor arrowCursor]];
904+ }
905 - (void)mouseUp:(NSEvent *)theEvent {
906 cocoaMouseHandler(theEvent);
907***************
908*** 1703,1708 ****
909 }
910 }
911 if (!no_text_key && !(Fl::e_state & FL_META) ) {
912! // Don't send cmd-<key> to interpretKeyEvents because it beeps.
913 // Then we can let the OS have a stab at it and see if it thinks it
914 // should result in some text
915--- 1781,1791 ----
916 }
917 }
918+ // Don't send cmd-<key> to interpretKeyEvents because it beeps.
919 if (!no_text_key && !(Fl::e_state & FL_META) ) {
920! // The simple keyboard model will ignore insertText, so we need to grab
921! // the symbol directly from the event. Note that we still use setMarkedText.
922! if (use_simple_keyboard)
923! [FLView prepareEtext:[theEvent charactersIgnoringModifiers]];
924!
925 // Then we can let the OS have a stab at it and see if it thinks it
926 // should result in some text
927***************
928*** 1883,1901 ****
929
930 if (!in_key_event) fl_lock_function();
931 [FLView prepareEtext:received];
932 // We can get called outside of key events (e.g. from the character
933! // palette). Transform such actions to FL_PASTE events.
934 if (!in_key_event) {
935 Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
936! Fl::handle(FL_PASTE, target);
937 // for some reason, the window does not redraw until the next mouse move or button push
938 // sending a 'redraw()' or 'awake()' does not solve the issue!
939 Fl::flush();
940 }
941 if (!in_key_event) fl_unlock_function();
942 }
943
944 - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection {
945! NSString *received;
946 if (newSelection.location == 0) {
947 [self unmarkText];
948--- 1966,1993 ----
949
950 if (!in_key_event) fl_lock_function();
951+
952+ // Simple keyboard widgets do not want these side channel inputs.
953+ if (use_simple_keyboard)
954+ goto end;
955+
956 [FLView prepareEtext:received];
957+
958 // We can get called outside of key events (e.g. from the character
959! // palette). We need to fake our own key event at that point.
960 if (!in_key_event) {
961 Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
962! Fl::e_keysym = Fl::e_original_keysym = 0;
963! Fl::handle(FL_KEYDOWN, target);
964 // for some reason, the window does not redraw until the next mouse move or button push
965 // sending a 'redraw()' or 'awake()' does not solve the issue!
966 Fl::flush();
967 }
968+
969+ end:
970 if (!in_key_event) fl_unlock_function();
971 }
972
973 - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection {
974! NSString *received, *current, *aggregate;
975 if (newSelection.location == 0) {
976 [self unmarkText];
977***************
978*** 1908,1916 ****
979 }
980 //NSLog(@"setMarkedText: %@ %d %d",received,newSelection.location,newSelection.length);
981 // This code creates the OS X behaviour of seeing dead keys as things
982 // are being composed.
983 next_compose_length = newSelection.location;
984! [FLView prepareEtext:received];
985! //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", received, Fl::e_length, next_compose_length);
986 }
987
988--- 2000,2044 ----
989 }
990 //NSLog(@"setMarkedText: %@ %d %d",received,newSelection.location,newSelection.length);
991+
992+ fl_lock_function();
993+
994+ // Simple keyboard widgets generally do not want these side channel
995+ // inputs, but we have no other way of getting dead keys so we make
996+ // an exception in that case.
997+ if (use_simple_keyboard) {
998+ if (in_key_event && (Fl::e_length == 0)) {
999+ [FLView prepareEtext:received];
1000+
1001+ Fl::e_text = (char*)cocoaDead2FLTK(Fl::e_text);
1002+ Fl::e_length = strlen(Fl::e_text);
1003+ }
1004+ goto end;
1005+ }
1006+
1007 // This code creates the OS X behaviour of seeing dead keys as things
1008 // are being composed.
1009+ //
1010+ // Note: The concatenation thing is because of how OS X deals with
1011+ // invalid sequences. At that point it will spit out one call
1012+ // to insertText with the now aborted sequence, and one new
1013+ // call to setMarkedText with the new sequence. Since we want
1014+ // both to be visible, we need to concatenate.
1015 next_compose_length = newSelection.location;
1016! current = [NSString stringWithUTF8String:Fl::e_text];
1017! aggregate = [current stringByAppendingString:received];
1018!
1019! [FLView prepareEtext:aggregate];
1020! //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", aggregate, Fl::e_length, next_compose_length);
1021!
1022! // We can get called outside of key events (e.g. from the character
1023! // palette). We need to fake our own key event at that point.
1024! if (!in_key_event) {
1025! Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
1026! Fl::e_keysym = Fl::e_original_keysym = 0;
1027! Fl::handle(FL_KEYDOWN, target);
1028! }
1029!
1030! end:
1031! fl_unlock_function();
1032 }
1033
1034***************
1035*** 1982,1985 ****
1036--- 2110,2129 ----
1037 @end
1038
1039+ void fullscreen_x(Fl_Window *w) {
1040+ w->_set_fullscreen();
1041+ /* On OS X < 10.6, it is necessary to recreate the window. This is done
1042+ with hide+show. */
1043+ w->hide();
1044+ w->show();
1045+ Fl::handle(FL_FULLSCREEN, w);
1046+ }
1047+
1048+ void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H) {
1049+ w->_clear_fullscreen();
1050+ w->hide();
1051+ w->resize(X, Y, W, H);
1052+ w->show();
1053+ Fl::handle(FL_FULLSCREEN, w);
1054+ }
1055
1056 /*
1057***************
1058*** 1997,2001 ****
1059 x->region = 0;
1060 x->subRegion = 0;
1061! x->cursor = fl_default_cursor;
1062 x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz
1063 Fl_Window *win = w->window();
1064--- 2141,2145 ----
1065 x->region = 0;
1066 x->subRegion = 0;
1067! x->cursor = NULL;
1068 x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz
1069 Fl_Window *win = w->window();
1070***************
1071*** 2099,2103 ****
1072 x->region = 0;
1073 x->subRegion = 0;
1074! x->cursor = fl_default_cursor;
1075 x->xidChildren = 0;
1076 x->xidNext = 0;
1077--- 2243,2247 ----
1078 x->region = 0;
1079 x->subRegion = 0;
1080! x->cursor = NULL;
1081 x->xidChildren = 0;
1082 x->xidNext = 0;
1083***************
1084*** 2105,2108 ****
1085--- 2249,2259 ----
1086
1087 NSRect srect = [[NSScreen mainScreen] frame];
1088+ if (w->flags() & Fl_Widget::FULLSCREEN) {
1089+ int sx, sy, sw, sh;
1090+ Fl::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h());
1091+ w->resize(sx, sy, sw, sh);
1092+ winstyle = NSBorderlessWindowMask;
1093+ winlevel = NSStatusWindowLevel;
1094+ }
1095 NSRect crect;
1096 crect.origin.x = w->x();
1097***************
1098*** 2553,2556 ****
1099--- 2704,2728 ----
1100 }
1101
1102+ extern void fl_trigger_clipboard_notify(int source);
1103+
1104+ void fl_clipboard_notify_change() {
1105+ // No need to do anything here...
1106+ }
1107+
1108+ static void clipboard_check(void)
1109+ {
1110+ PasteboardSyncFlags flags;
1111+
1112+ allocatePasteboard();
1113+ flags = PasteboardSynchronize(myPasteboard);
1114+
1115+ if (!(flags & kPasteboardModified))
1116+ return;
1117+ if (flags & kPasteboardClientIsOwner)
1118+ return;
1119+
1120+ fl_trigger_clipboard_notify(1);
1121+ }
1122+
1123 void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
1124 {
1125***************
1126*** 2677,2680 ****
1127--- 2849,2856 ----
1128 [(NSWindow *)xid close];
1129 }
1130+ if (cursor) {
1131+ [(NSCursor*)cursor release];
1132+ cursor = NULL;
1133+ }
1134 }
1135
1136***************
1137*** 2792,2857 ****
1138 }
1139
1140! static NSCursor *PrepareCursor(NSCursor *cursor, CGContextRef (*f)() )
1141 {
1142! if (cursor == nil) {
1143! CGContextRef c = f();
1144! NSImage *image = CGBitmapContextToNSImage(c);
1145! fl_delete_offscreen( (Fl_Offscreen)c );
1146! NSPoint pt = {[image size].width/2, [image size].height/2};
1147! cursor = [[NSCursor alloc] initWithImage:image hotSpot:pt];
1148 }
1149- return cursor;
1150- }
1151
1152- void Fl_X::set_cursor(Fl_Cursor c)
1153- {
1154- NSCursor *icrsr;
1155 switch (c) {
1156! case FL_CURSOR_CROSS: icrsr = [NSCursor crosshairCursor]; break;
1157! case FL_CURSOR_WAIT:
1158! static NSCursor *watch = nil;
1159! watch = PrepareCursor(watch, &Fl_X::watch_cursor_image);
1160! icrsr = watch;
1161! break;
1162! case FL_CURSOR_INSERT: icrsr = [NSCursor IBeamCursor]; break;
1163! case FL_CURSOR_N: icrsr = [NSCursor resizeUpCursor]; break;
1164! case FL_CURSOR_S: icrsr = [NSCursor resizeDownCursor]; break;
1165! case FL_CURSOR_NS: icrsr = [NSCursor resizeUpDownCursor]; break;
1166! case FL_CURSOR_HELP:
1167! static NSCursor *help = nil;
1168! help = PrepareCursor(help, &Fl_X::help_cursor_image);
1169! icrsr = help;
1170! break;
1171! case FL_CURSOR_HAND: icrsr = [NSCursor pointingHandCursor]; break;
1172! case FL_CURSOR_MOVE: icrsr = [NSCursor openHandCursor]; break;
1173! case FL_CURSOR_NE:
1174! case FL_CURSOR_SW:
1175! case FL_CURSOR_NESW:
1176! static NSCursor *nesw = nil;
1177! nesw = PrepareCursor(nesw, &Fl_X::nesw_cursor_image);
1178! icrsr = nesw;
1179! break;
1180! case FL_CURSOR_E: icrsr = [NSCursor resizeRightCursor]; break;
1181! case FL_CURSOR_W: icrsr = [NSCursor resizeLeftCursor]; break;
1182! case FL_CURSOR_WE: icrsr = [NSCursor resizeLeftRightCursor]; break;
1183! case FL_CURSOR_SE:
1184! case FL_CURSOR_NW:
1185! case FL_CURSOR_NWSE:
1186! static NSCursor *nwse = nil;
1187! nwse = PrepareCursor(nwse, &Fl_X::nwse_cursor_image);
1188! icrsr = nwse;
1189! break;
1190! case FL_CURSOR_NONE:
1191! static NSCursor *none = nil;
1192! none = PrepareCursor(none, &Fl_X::none_cursor_image);
1193! icrsr = none;
1194! break;
1195! case FL_CURSOR_ARROW:
1196! case FL_CURSOR_DEFAULT:
1197! default: icrsr = [NSCursor arrowCursor];
1198! break;
1199 }
1200! [icrsr set];
1201! cursor = icrsr;
1202 }
1203
1204--- 2968,3071 ----
1205 }
1206
1207! int Fl_X::set_cursor(Fl_Cursor c)
1208 {
1209! if (cursor) {
1210! [(NSCursor*)cursor release];
1211! cursor = NULL;
1212 }
1213
1214 switch (c) {
1215! case FL_CURSOR_ARROW: cursor = [NSCursor arrowCursor]; break;
1216! case FL_CURSOR_CROSS: cursor = [NSCursor crosshairCursor]; break;
1217! case FL_CURSOR_INSERT: cursor = [NSCursor IBeamCursor]; break;
1218! case FL_CURSOR_HAND: cursor = [NSCursor pointingHandCursor]; break;
1219! case FL_CURSOR_MOVE: cursor = [NSCursor openHandCursor]; break;
1220! case FL_CURSOR_NS: cursor = [NSCursor resizeUpDownCursor]; break;
1221! case FL_CURSOR_WE: cursor = [NSCursor resizeLeftRightCursor]; break;
1222! case FL_CURSOR_N: cursor = [NSCursor resizeUpCursor]; break;
1223! case FL_CURSOR_E: cursor = [NSCursor resizeRightCursor]; break;
1224! case FL_CURSOR_W: cursor = [NSCursor resizeLeftCursor]; break;
1225! case FL_CURSOR_S: cursor = [NSCursor resizeDownCursor]; break;
1226! default:
1227! return 0;
1228! }
1229!
1230! [(NSCursor*)cursor retain];
1231!
1232! [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]];
1233!
1234! return 1;
1235! }
1236!
1237! int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
1238! if (cursor) {
1239! [(NSCursor*)cursor release];
1240! cursor = NULL;
1241! }
1242!
1243! if ((hotx < 0) || (hotx >= image->w()))
1244! return 0;
1245! if ((hoty < 0) || (hoty >= image->h()))
1246! return 0;
1247!
1248! // OS X >= 10.6 can create a NSImage from a CGImage, but we need to
1249! // support older versions, hence this pesky handling.
1250!
1251! NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
1252! initWithBitmapDataPlanes:NULL
1253! pixelsWide:image->w()
1254! pixelsHigh:image->h()
1255! bitsPerSample:8
1256! samplesPerPixel:image->d()
1257! hasAlpha:!(image->d() & 1)
1258! isPlanar:NO
1259! colorSpaceName:(image->d()<=2) ? NSDeviceWhiteColorSpace : NSDeviceRGBColorSpace
1260! bytesPerRow:(image->w() * image->d())
1261! bitsPerPixel:(image->d()*8)];
1262!
1263! // Alpha needs to be premultiplied for this format
1264!
1265! const uchar *i = (const uchar*)*image->data();
1266! unsigned char *o = [bitmap bitmapData];
1267! for (int y = 0;y < image->h();y++) {
1268! if (image->d() & 1) {
1269! for (int x = 0;x < image->w();x++) {
1270! unsigned int alpha;
1271! if (image->d() == 4) {
1272! alpha = i[3];
1273! *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
1274! *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
1275! }
1276!
1277! alpha = i[1];
1278! *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
1279! *o++ = alpha;
1280! i++;
1281! }
1282! } else {
1283! // No alpha, so we can just copy everything directly.
1284! int len = image->w() * image->d();
1285! memcpy(o, i, len);
1286! o += len;
1287! i += len;
1288! }
1289! i += image->ld();
1290 }
1291!
1292! NSImage *nsimage = [[NSImage alloc]
1293! initWithSize:NSMakeSize(image->w(), image->h())];
1294!
1295! [nsimage addRepresentation:bitmap];
1296!
1297! cursor = [[NSCursor alloc]
1298! initWithImage:nsimage
1299! hotSpot:NSMakePoint(hotx, hoty)];
1300!
1301! [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]];
1302!
1303! [bitmap release];
1304! [nsimage release];
1305!
1306! return 1;
1307 }
1308
1309*** fltk-1.3.0/src/Fl_grab.cxx 2010-12-18 16:31:01.000000000 -0600
1310--- fltk-1.3.0.new/src/Fl_grab.cxx 2011-06-22 22:35:32.000000000 -0500
1311***************
1312*** 39,42 ****
1313--- 39,43 ----
1314
1315 extern void fl_fix_focus(); // in Fl.cxx
1316+ void fl_update_focus(void);
1317
1318 #ifdef WIN32
1319***************
1320*** 51,55 ****
1321--- 52,68 ----
1322 #endif
1323
1324+ #if !(defined(WIN32) || defined(__APPLE__))
1325+ extern int ewmh_supported(); // from Fl_x.cxx
1326+ #endif
1327+
1328 void Fl::grab(Fl_Window* win) {
1329+ Fl_Window *fullscreen_win = NULL;
1330+ for (Fl_Window *W = Fl::first_window(); W; W = Fl::next_window(W)) {
1331+ if (W->fullscreen_active()) {
1332+ fullscreen_win = W;
1333+ break;
1334+ }
1335+ }
1336+
1337 if (win) {
1338 if (!grab_) {
1339***************
1340*** 61,66 ****
1341 Fl_X::i(first_window())->set_key_window();
1342 #else
1343 XGrabPointer(fl_display,
1344! fl_xid(first_window()),
1345 1,
1346 ButtonPressMask|ButtonReleaseMask|
1347--- 74,80 ----
1348 Fl_X::i(first_window())->set_key_window();
1349 #else
1350+ Window xid = fullscreen_win ? fl_xid(fullscreen_win) : fl_xid(first_window());
1351 XGrabPointer(fl_display,
1352! xid,
1353 1,
1354 ButtonPressMask|ButtonReleaseMask|
1355***************
1356*** 72,76 ****
1357 fl_event_time);
1358 XGrabKeyboard(fl_display,
1359! fl_xid(first_window()),
1360 1,
1361 GrabModeAsync,
1362--- 86,90 ----
1363 fl_event_time);
1364 XGrabKeyboard(fl_display,
1365! xid,
1366 1,
1367 GrabModeAsync,
1368***************
1369*** 80,83 ****
1370--- 94,98 ----
1371 }
1372 grab_ = win;
1373+ fl_update_focus();
1374 } else {
1375 if (grab_) {
1376***************
1377*** 88,92 ****
1378--- 103,110 ----
1379 fl_capture = 0;
1380 #else
1381+ // We must keep the grab in the non-EWMH fullscreen case
1382+ if (!fullscreen_win || ewmh_supported()) {
1383 XUngrabKeyboard(fl_display, fl_event_time);
1384+ }
1385 XUngrabPointer(fl_display, fl_event_time);
1386 // this flush is done in case the picked menu item goes into
1387***************
1388*** 95,98 ****
1389--- 113,117 ----
1390 #endif
1391 grab_ = 0;
1392+ fl_update_focus();
1393 fl_fix_focus();
1394 }
1395*** fltk-1.3.0/src/Fl_win32.cxx 2011-05-30 07:33:51.000000000 -0500
1396--- fltk-1.3.0.new/src/Fl_win32.cxx 2011-06-22 22:35:32.000000000 -0500
1397***************
1398*** 99,102 ****
1399--- 99,104 ----
1400 Fl_Display_Device *Fl_Display_Device::_display = &fl_gdi_display; // the platform display
1401
1402+ bool use_simple_keyboard = false;
1403+
1404 // dynamic wsock dll handling api:
1405 #if defined(__CYGWIN__) && !defined(SOCKET)
1406***************
1407*** 132,135 ****
1408--- 134,139 ----
Pierre Ossman554b3ee2011-06-09 10:47:19 +00001409 */
DRC8e631682011-06-23 08:28:18 +00001410 static HMODULE s_imm_module = 0;
1411+ typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
1412+ static flTypeImmAssociateContextEx flImmAssociateContextEx = 0;
1413 typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
1414 static flTypeImmGetContext flImmGetContext = 0;
1415***************
1416*** 147,150 ****
1417--- 151,155 ----
1418 Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
1419 "Please check your input method manager library accessibility.");
1420+ flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
1421 flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
1422 flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
1423***************
1424*** 425,429 ****
1425 }
1426
1427! TranslateMessage(&fl_msg);
1428 DispatchMessageW(&fl_msg);
1429 have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
1430--- 430,439 ----
1431 }
1432
1433! // Don't bother with key to character translation as we do
1434! // it manually for simpley keyboard widgets. In fact, calling
1435! // TranslateMessage() just makes it more difficult as it sets
1436! // a bunch of internal state.
1437! if (!use_simple_keyboard)
1438! TranslateMessage(&fl_msg);
1439 DispatchMessageW(&fl_msg);
1440 have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
1441***************
1442*** 543,546 ****
1443--- 553,586 ----
1444 };
1445
1446+ void fl_update_clipboard(void) {
1447+ HWND hwnd = fl_xid(Fl::first_window());
1448+
1449+ if (!hwnd)
1450+ return;
1451+
1452+ if (!OpenClipboard(hwnd))
1453+ return;
1454+
1455+ EmptyClipboard();
1456+
1457+ int utf16_len = fl_utf8toUtf16(fl_selection_buffer[1],
1458+ fl_selection_length[1], 0, 0);
1459+
1460+ HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc.
1461+ LPVOID memLock = GlobalLock(hMem);
1462+
1463+ fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1],
1464+ (unsigned short*) memLock, utf16_len + 1);
1465+
1466+ GlobalUnlock(hMem);
1467+ SetClipboardData(CF_UNICODETEXT, hMem);
1468+
1469+ CloseClipboard();
1470+
1471+ // In case Windows managed to lob of a WM_DESTROYCLIPBOARD during
1472+ // the above.
1473+ fl_i_own_selection[1] = 1;
1474+ }
1475+
1476 // call this when you create a selection:
1477 void Fl::copy(const char *stuff, int len, int clipboard) {
1478***************
1479*** 560,582 ****
1480 fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
1481 fl_selection_length[clipboard] = len;
1482! if (clipboard) {
1483! // set up for "delayed rendering":
1484! if (OpenClipboard(NULL)) {
1485! // if the system clipboard works, use it
1486! int utf16_len = fl_utf8toUtf16(fl_selection_buffer[clipboard], fl_selection_length[clipboard], 0, 0);
1487! EmptyClipboard();
1488! HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc.
1489! LPVOID memLock = GlobalLock(hMem);
1490! fl_utf8toUtf16(fl_selection_buffer[clipboard], fl_selection_length[clipboard], (unsigned short*) memLock, utf16_len + 1);
1491! GlobalUnlock(hMem);
1492! SetClipboardData(CF_UNICODETEXT, hMem);
1493! CloseClipboard();
1494! GlobalFree(hMem);
1495! fl_i_own_selection[clipboard] = 0;
1496! } else {
1497! // only if it fails, instruct paste() to use the internal buffers
1498! fl_i_own_selection[clipboard] = 1;
1499! }
1500! }
1501 }
1502
1503--- 600,606 ----
1504 fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
1505 fl_selection_length[clipboard] = len;
1506! fl_i_own_selection[clipboard] = 1;
1507! if (clipboard)
1508! fl_update_clipboard();
1509 }
1510
1511***************
1512*** 631,634 ****
1513--- 655,690 ----
1514 }
1515
1516+ static HWND clipboard_wnd = 0;
1517+ static HWND next_clipboard_wnd = 0;
1518+
1519+ static bool initial_clipboard = true;
1520+
1521+ void fl_clipboard_notify_change() {
1522+ // No need to do anything here...
1523+ }
1524+
1525+ void fl_clipboard_notify_target(HWND wnd) {
1526+ if (clipboard_wnd)
1527+ return;
1528+
1529+ // We get one fake WM_DRAWCLIPBOARD immediately, which we therefore
1530+ // need to ignore.
1531+ initial_clipboard = true;
1532+
1533+ clipboard_wnd = wnd;
1534+ next_clipboard_wnd = SetClipboardViewer(wnd);
1535+ }
1536+
1537+ void fl_clipboard_notify_untarget(HWND wnd) {
1538+ if (wnd != clipboard_wnd)
1539+ return;
1540+
1541+ ChangeClipboardChain(wnd, next_clipboard_wnd);
1542+ clipboard_wnd = next_clipboard_wnd = 0;
1543+
1544+ if (Fl::first_window())
1545+ fl_clipboard_notify_target(fl_xid(Fl::first_window()));
1546+ }
1547+
1548 ////////////////////////////////////////////////////////////////
1549 char fl_is_ime = 0;
1550***************
1551*** 650,653 ****
1552--- 706,752 ----
1553 }
1554
1555+ void fl_update_focus(void)
1556+ {
1557+ Fl_Widget *focus;
1558+ Fl_Window *win;
1559+
1560+ get_imm_module();
1561+
1562+ focus = Fl::grab();
1563+ if (!focus)
1564+ focus = Fl::focus();
1565+ if (!focus)
1566+ return;
1567+
1568+ // Grabs are special in that events are sent to the first
1569+ // available window
1570+ if (focus == Fl::grab())
1571+ win = Fl::first_window();
1572+ else {
1573+ win = focus->as_window();
1574+ if (!win)
1575+ win = focus->window();
1576+ }
1577+
1578+ if (!win) {
1579+ Fl::warning("Cannot find window for widget receiving focus");
1580+ return;
1581+ }
1582+
1583+ // No Win32 window created yet
1584+ if (!Fl_X::i(win) || !fl_xid(win))
1585+ return;
1586+
1587+ if (focus->simple_keyboard()) {
1588+ use_simple_keyboard = true;
1589+ if (flImmGetContext(fl_xid(win)) != 0)
1590+ flImmAssociateContextEx(fl_xid(win), 0, 0);
1591+ } else {
1592+ use_simple_keyboard = false;
1593+ if (flImmGetContext(fl_xid(win)) == 0)
1594+ flImmAssociateContextEx(fl_xid(win), 0, IACE_DEFAULT);
1595+ }
1596+ }
1597+
1598 HWND fl_capture;
1599
1600***************
1601*** 797,800 ****
1602--- 896,920 ----
1603 }
1604
1605+ static xchar msdead2fltk(xchar in)
1606+ {
1607+ switch (in) {
1608+ case 0x0060: // GRAVE ACCENT
1609+ return 0x0300; // COMBINING GRAVE ACCENT
1610+ case 0x00b4: // ACUTE ACCENT
1611+ return 0x0301; // COMBINING ACUTE ACCENT
1612+ case 0x005e: // CIRCUMFLEX ACCENT
1613+ return 0x0302; // COMBINING CIRCUMFLEX ACCENT
1614+ case 0x007e: // TILDE
1615+ return 0x0303; // COMBINING TILDE
1616+ case 0x00a8: // DIAERESIS
1617+ return 0x0308; // COMBINING DIAERESIS
1618+ // FIXME: Windows dead key behaviour isn't documented and I don't have
1619+ // any more keyboards to test with...
1620+ }
1621+
1622+ // hope that Windows gave us something proper to begin with
1623+ return in;
1624+ }
1625+
1626 #if USE_COLORMAP
1627 extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
1628***************
1629*** 858,861 ****
1630--- 978,983 ----
1631 //fl_msg.lPrivate = ???
1632
1633+ MSG fl_orig_msg = fl_msg;
1634+
1635 Fl_Window *window = fl_find(hWnd);
1636
1637***************
1638*** 1037,1057 ****
1639 Fl::e_state = state;
1640 static char buffer[1024];
1641- if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
1642
1643 xchar u = (xchar) wParam;
1644 // Fl::e_length = fl_unicode2utf(&u, 1, buffer);
1645 Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
1646 buffer[Fl::e_length] = 0;
1647
1648!
1649! } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
1650! if (state & FL_NUM_LOCK) {
1651! // Convert to regular keypress...
1652! buffer[0] = Fl::e_keysym-FL_KP;
1653! Fl::e_length = 1;
1654! } else {
1655! // Convert to special keypress...
1656! buffer[0] = 0;
1657! Fl::e_length = 0;
1658 switch (Fl::e_keysym) {
1659 case FL_KP + '0' :
1660--- 1159,1238 ----
1661 Fl::e_state = state;
1662 static char buffer[1024];
1663
1664+ if (use_simple_keyboard) {
1665+ BYTE keystate[256];
1666+ WCHAR wbuf[8];
1667+ int ret;
1668+
1669+ // I'm not sure if we ever get WM_CHAR (& friends) without an initial
1670+ // WM_KEYDOWN (& friends), but if we do then we should not send such
1671+ // side band events to simple keyboard widgets.
1672+ if ((fl_orig_msg.message != WM_KEYDOWN) &&
1673+ (fl_orig_msg.message != WM_SYSKEYDOWN) &&
1674+ (fl_orig_msg.message != WM_KEYUP) &&
1675+ (fl_orig_msg.message != WM_SYSKEYUP))
1676+ break;
1677+
1678+ GetKeyboardState(keystate);
1679+
1680+ // Pressing Ctrl wreaks havoc with the symbol lookup, so turn that off.
1681+ // But AltGr shows up as Ctrl+Alt in Windows, so keep Ctrl if Alt is
1682+ // active.
1683+ if (!(keystate[VK_MENU] & (1<<31)))
1684+ keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0;
1685+
1686+ // We cannot inspect or modify Windows' internal state of the keyboard
1687+ // so we have to try to infer information from ToUnicode() and wedge
1688+ // things into a known state.
1689+ for (int i = 0;i < 2;i++) {
1690+ ret = ToUnicode(fl_orig_msg.wParam, 0, keystate, wbuf,
1691+ sizeof(wbuf)/sizeof(wbuf[0]), 0);
1692+
1693+ // No symbol for this key (or unexpected length)
1694+ if ((ret == 0) || (ret < -1)) {
1695+ buffer[0] = 0;
1696+ Fl::e_length = 0;
1697+ break;
1698+ }
1699+
1700+ // A dead key. Convert this to a Unicode combining character so
1701+ // that the application can tell the difference between dead and
1702+ // normal keys.
1703+ if (ret == -1) {
1704+ xchar u = (xchar) msdead2fltk(wbuf[0]);
1705+ Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
1706+ buffer[Fl::e_length] = 0;
1707+ break;
1708+ }
1709+
1710+ // If we have two characters (or more) from ToUnicode(), that's
1711+ // an invalid sequence. One character chould mean a proper symbol,
1712+ // or it could mean a composed one. In both cases we need to call
1713+ // ToUnicode() again to get something sane.
1714+ if (i == 0)
1715+ continue;
1716+
1717+ // We should now have something sane. Give whatever we have to the
1718+ // application.
1719+ Fl::e_length = fl_utf8fromwc(buffer, 1024, wbuf, ret);
1720+ buffer[Fl::e_length] = 0;
1721+ }
1722+ } else if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
1723 xchar u = (xchar) wParam;
1724 // Fl::e_length = fl_unicode2utf(&u, 1, buffer);
1725 Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
1726 buffer[Fl::e_length] = 0;
1727+ } else {
1728+ buffer[0] = 0;
1729+ Fl::e_length = 0;
1730+ }
1731
1732! // The keypad area is a bit odd in that we need to change the keysym
1733! // to properly indicate what the user meant, unlike other keys where
1734! // we normally change the text and keep keysym stable.
1735! if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
1736! // The initial mapping tables give us a keysym that corresponds to
1737! // numlock being on, so we only do something when it is off.
1738! if (!(state & FL_NUM_LOCK)) {
1739 switch (Fl::e_keysym) {
1740 case FL_KP + '0' :
1741***************
1742*** 1085,1112 ****
1743 Fl::e_keysym = FL_Delete;
1744 break;
1745- case FL_KP + '/' :
1746- case FL_KP + '*' :
1747- case FL_KP + '-' :
1748- case FL_KP + '+' :
1749- buffer[0] = Fl::e_keysym-FL_KP;
1750- Fl::e_length = 1;
1751- break;
1752 }
1753 }
1754- } else if ((lParam & (1<<31))==0) {
1755- #ifdef FLTK_PREVIEW_DEAD_KEYS
1756- if ((lParam & (1<<24))==0) { // clear if dead key (always?)
1757- xchar u = (xchar) wParam;
1758- Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
1759- buffer[Fl::e_length] = 0;
1760- } else { // set if "extended key" (never printable?)
1761- buffer[0] = 0;
1762- Fl::e_length = 0;
1763- }
1764- #else
1765- buffer[0] = 0;
1766- Fl::e_length = 0;
1767- #endif
1768 }
1769 Fl::e_text = buffer;
1770 if (lParam & (1<<31)) { // key up events.
1771--- 1266,1273 ----
1772 Fl::e_keysym = FL_Delete;
1773 break;
1774 }
1775 }
1776 }
1777+
1778 Fl::e_text = buffer;
1779 if (lParam & (1<<31)) { // key up events.
1780***************
1781*** 1126,1129 ****
1782--- 1287,1291 ----
1783 static int delta = 0; // running total of all motion
1784 delta += (SHORT)(HIWORD(wParam));
1785+ Fl::e_dx = 0;
1786 Fl::e_dy = -delta / WHEEL_DELTA;
1787 delta += Fl::e_dy * WHEEL_DELTA;
1788***************
1789*** 1132,1135 ****
1790--- 1294,1312 ----
1791 }
1792
1793+ // This is only defined on Vista and upwards...
1794+ #ifndef WM_MOUSEHWHEEL
1795+ #define WM_MOUSEHWHEEL 0x020E
1796+ #endif
1797+
1798+ case WM_MOUSEHWHEEL: {
1799+ static int delta = 0; // running total of all motion
1800+ delta += (SHORT)(HIWORD(wParam));
1801+ Fl::e_dy = 0;
1802+ Fl::e_dx = delta / WHEEL_DELTA;
1803+ delta -= Fl::e_dx * WHEEL_DELTA;
1804+ if (Fl::e_dx) Fl::handle(FL_MOUSEWHEEL, window);
1805+ return 0;
1806+ }
1807+
1808 case WM_GETMINMAXINFO:
1809 Fl_X::i(window)->set_minmax((LPMINMAXINFO)lParam);
1810***************
1811*** 1186,1216 ****
1812 return 1;
1813
1814! case WM_RENDERALLFORMATS:
1815! fl_i_own_selection[1] = 0;
1816! // Windoze seems unhappy unless I do these two steps. Documentation
1817! // seems to vary on whether opening the clipboard is necessary or
1818! // is in fact wrong:
1819! CloseClipboard();
1820! OpenClipboard(NULL);
1821! // fall through...
1822! case WM_RENDERFORMAT: {
1823! HANDLE h;
1824!
1825! // int l = fl_utf_nb_char((unsigned char*)fl_selection_buffer[1], fl_selection_length[1]);
1826! int l = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], NULL, 0); // Pass NULL buffer to query length required
1827! h = GlobalAlloc(GHND, (l+1) * sizeof(unsigned short));
1828! if (h) {
1829! unsigned short *g = (unsigned short*) GlobalLock(h);
1830! // fl_utf2unicode((unsigned char *)fl_selection_buffer[1], fl_selection_length[1], (xchar*)g);
1831! l = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], g, (l+1));
1832! g[l] = 0;
1833! GlobalUnlock(h);
1834! SetClipboardData(CF_UNICODETEXT, h);
1835 }
1836
1837! // Windoze also seems unhappy if I don't do this. Documentation very
1838! // unclear on what is correct:
1839! if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard();
1840! return 1;}
1841
1842 default:
1843--- 1363,1386 ----
1844 return 1;
1845
1846! case WM_CHANGECBCHAIN:
1847! if ((hWnd == clipboard_wnd) &&
1848! (next_clipboard_wnd == (HWND)wParam)) {
1849! next_clipboard_wnd = (HWND)lParam;
1850! return 0;
1851 }
1852+ break;
1853+
1854+ case WM_DRAWCLIPBOARD:
1855+ // When the clipboard moves between two FLTK windows,
1856+ // fl_i_own_selection will temporarily be false as we are
1857+ // processing this message. Hence the need to use fl_find().
1858+ if (!initial_clipboard && !fl_find(GetClipboardOwner()))
1859+ fl_trigger_clipboard_notify(1);
1860+ initial_clipboard = false;
1861
1862! if (next_clipboard_wnd)
1863! SendMessage(next_clipboard_wnd, WM_DRAWCLIPBOARD, wParam, lParam);
1864!
1865! return 0;
1866
1867 default:
1868***************
1869*** 1321,1324 ****
1870--- 1491,1499 ----
1871 Y+=yoff;
1872
1873+ if (w->flags() & Fl_Widget::FULLSCREEN) {
1874+ X = Y = 0;
1875+ bx = by = bt = 0;
1876+ }
1877+
1878 return ret;
1879 }
1880***************
1881*** 1371,1374 ****
1882--- 1546,1601 ----
1883 }
1884
1885+ static void make_fullscreen(Fl_Window *w, Window xid, int X, int Y, int W, int H) {
1886+ int sx, sy, sw, sh;
1887+ Fl::screen_xywh(sx, sy, sw, sh, X, Y, W, H);
1888+ DWORD flags = GetWindowLong(xid, GWL_STYLE);
1889+ flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
1890+ SetWindowLong(xid, GWL_STYLE, flags);
1891+ // SWP_NOSENDCHANGING is so that we can override size limits
1892+ SetWindowPos(xid, HWND_TOP, sx, sy, sw, sh, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
1893+ }
1894+
1895+ void fullscreen_x(Fl_Window *w) {
1896+ w->_set_fullscreen();
1897+ make_fullscreen(w, fl_xid(w), w->x(), w->y(), w->w(), w->h());
1898+ Fl::handle(FL_FULLSCREEN, w);
1899+ }
1900+
1901+ void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H) {
1902+ w->_clear_fullscreen();
1903+ DWORD style = GetWindowLong(fl_xid(w), GWL_STYLE);
1904+ // Remove the xid temporarily so that Fl_X::fake_X_wm() behaves like it
1905+ // does in Fl_X::make().
1906+ HWND xid = fl_xid(w);
1907+ Fl_X::i(w)->xid = NULL;
1908+ int x, y, bt, bx, by;
1909+ switch (Fl_X::fake_X_wm(w, x, y, bt, bx, by)) {
1910+ case 0:
1911+ break;
1912+ case 1:
1913+ style |= WS_CAPTION;
1914+ break;
1915+ case 2:
1916+ if (w->border()) {
1917+ style |= WS_THICKFRAME | WS_CAPTION;
1918+ }
1919+ break;
1920+ }
1921+ Fl_X::i(w)->xid = xid;
1922+ // Adjust for decorations (but not if that puts the decorations
1923+ // outside the screen)
1924+ if ((X != w->x()) || (Y != w->y())) {
1925+ X -= bx;
1926+ Y -= by+bt;
1927+ }
1928+ W += bx*2;
1929+ H += by*2+bt;
1930+ SetWindowLong(fl_xid(w), GWL_STYLE, style);
1931+ SetWindowPos(fl_xid(w), 0, X, Y, W, H,
1932+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
1933+ Fl::handle(FL_FULLSCREEN, w);
1934+ }
1935+
1936+
1937 ////////////////////////////////////////////////////////////////
1938
1939***************
1940*** 1409,1413 ****
1941 char fl_show_iconic; // hack for Fl_Window::iconic()
1942 // int fl_background_pixel = -1; // color to use for background
1943- HCURSOR fl_default_cursor;
1944 UINT fl_wake_msg = 0;
1945 int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
1946--- 1636,1639 ----
1947***************
1948*** 1457,1461 ****
1949 w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
1950 wcw.hIcon = wcw.hIconSm = (HICON)w->icon();
1951! wcw.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
1952 //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
1953 //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
1954--- 1683,1687 ----
1955 w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
1956 wcw.hIcon = wcw.hIconSm = (HICON)w->icon();
1957! wcw.hCursor = LoadCursor(NULL, IDC_ARROW);
1958 //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
1959 //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
1960***************
1961*** 1500,1515 ****
1962 switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) {
1963 // No border (used for menus)
1964! case 0: style |= WS_POPUP;
1965! styleEx |= WS_EX_TOOLWINDOW;
1966 break;
1967
1968 // Thin border and title bar
1969! case 1: style |= WS_DLGFRAME | WS_CAPTION; break;
1970
1971 // Thick, resizable border and title bar, with maximize button
1972! case 2: style |= WS_THICKFRAME | WS_MAXIMIZEBOX | WS_CAPTION ; break;
1973 }
1974 if (by+bt) {
1975- if (!w->modal()) style |= WS_SYSMENU | WS_MINIMIZEBOX;
1976 wp += 2*bx;
1977 hp += 2*by+bt;
1978--- 1726,1749 ----
1979 switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) {
1980 // No border (used for menus)
1981! case 0:
1982! style |= WS_POPUP;
1983! styleEx |= WS_EX_TOOLWINDOW;
1984 break;
1985
1986 // Thin border and title bar
1987! case 1:
1988! style |= WS_DLGFRAME | WS_CAPTION;
1989! if (!w->modal())
1990! style |= WS_SYSMENU | WS_MINIMIZEBOX;
1991! break;
1992
1993 // Thick, resizable border and title bar, with maximize button
1994! case 2:
1995! style |= WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_CAPTION;
1996! if (!w->modal())
1997! style |= WS_MINIMIZEBOX;
1998! break;
1999 }
2000 if (by+bt) {
2001 wp += 2*bx;
2002 hp += 2*by+bt;
2003***************
2004*** 1541,1545 ****
2005 x->region = 0;
2006 x->private_dc = 0;
2007! x->cursor = fl_default_cursor;
2008 if (!fl_codepage) fl_get_codepage();
2009
2010--- 1775,1779 ----
2011 x->region = 0;
2012 x->private_dc = 0;
2013! x->cursor = LoadCursor(NULL, IDC_ARROW);
2014 if (!fl_codepage) fl_get_codepage();
2015
2016***************
2017*** 1567,1573 ****
2018--- 1801,1821 ----
2019 if (lab) free(lab);
2020
2021+ if (w->flags() & Fl_Widget::FULLSCREEN) {
2022+ /* We need to make sure that the fullscreen is created on the
2023+ default monitor, ie the desktop where the shortcut is located
2024+ etc. This requires that CreateWindow is called with CW_USEDEFAULT
2025+ for x and y. We can then use GetWindowRect to determine which
2026+ monitor the window was placed on. */
2027+ RECT rect;
2028+ GetWindowRect(x->xid, &rect);
2029+ make_fullscreen(w, x->xid, rect.left, rect.top,
2030+ rect.right - rect.left, rect.bottom - rect.top);
2031+ }
2032+
2033 x->next = Fl_X::first;
2034 Fl_X::first = x;
2035
2036+ fl_clipboard_notify_target(x->xid);
2037+
2038 x->wait_for_expose = 1;
2039 if (fl_show_iconic) {showit = 0; fl_show_iconic = 0;}
2040***************
2041*** 1582,1586 ****
2042 // other windows from the code, or we lose the capture.
2043 ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
2044! (Fl::grab() || (style & WS_POPUP)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
2045
2046 // Register all windows for potential drag'n'drop operations
2047--- 1830,1834 ----
2048 // other windows from the code, or we lose the capture.
2049 ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
2050! (Fl::grab() || (styleEx & WS_EX_TOOLWINDOW)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
2051
2052 // Register all windows for potential drag'n'drop operations
2053***************
2054*** 1778,1781 ****
2055--- 2026,2152 ----
2056
2057 ////////////////////////////////////////////////////////////////
2058+
2059+ #ifndef IDC_HAND
2060+ # define IDC_HAND MAKEINTRESOURCE(32649)
2061+ #endif // !IDC_HAND
2062+
2063+ int Fl_X::set_cursor(Fl_Cursor c) {
2064+ LPSTR n;
2065+
2066+ if (c == FL_CURSOR_NONE)
2067+ cursor = NULL;
2068+ else {
2069+ switch (c) {
2070+ case FL_CURSOR_ARROW: n = IDC_ARROW; break;
2071+ case FL_CURSOR_CROSS: n = IDC_CROSS; break;
2072+ case FL_CURSOR_WAIT: n = IDC_WAIT; break;
2073+ case FL_CURSOR_INSERT: n = IDC_IBEAM; break;
2074+ case FL_CURSOR_HAND: n = IDC_HAND; break;
2075+ case FL_CURSOR_HELP: n = IDC_HELP; break;
2076+ case FL_CURSOR_MOVE: n = IDC_SIZEALL; break;
2077+ case FL_CURSOR_N:
2078+ case FL_CURSOR_S:
2079+ // FIXME: Should probably have fallbacks for these instead
2080+ case FL_CURSOR_NS: n = IDC_SIZENS; break;
2081+ case FL_CURSOR_NE:
2082+ case FL_CURSOR_SW:
2083+ // FIXME: Dito.
2084+ case FL_CURSOR_NESW: n = IDC_SIZENESW; break;
2085+ case FL_CURSOR_E:
2086+ case FL_CURSOR_W:
2087+ // FIXME: Dito.
2088+ case FL_CURSOR_WE: n = IDC_SIZEWE; break;
2089+ case FL_CURSOR_SE:
2090+ case FL_CURSOR_NW:
2091+ // FIXME: Dito.
2092+ case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break;
2093+ default:
2094+ return 0;
2095+ }
2096+
2097+ cursor = LoadCursor(NULL, n);
2098+ if (cursor == NULL)
2099+ return 0;
2100+ }
2101+
2102+ SetCursor(cursor);
2103+
2104+ return 1;
2105+ }
2106+
2107+ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
2108+ BITMAPV5HEADER bi;
2109+ HBITMAP bitmap, mask;
2110+ DWORD *bits;
2111+
2112+ if ((hotx < 0) || (hotx >= image->w()))
2113+ return 0;
2114+ if ((hoty < 0) || (hoty >= image->h()))
2115+ return 0;
2116+
2117+ memset(&bi, 0, sizeof(BITMAPV5HEADER));
2118+
2119+ bi.bV5Size = sizeof(BITMAPV5HEADER);
2120+ bi.bV5Width = image->w();
2121+ bi.bV5Height = image->h();
2122+ bi.bV5Planes = 1;
2123+ bi.bV5BitCount = 32;
2124+ bi.bV5Compression = BI_BITFIELDS;
2125+ bi.bV5RedMask = 0x00FF0000;
2126+ bi.bV5GreenMask = 0x0000FF00;
2127+ bi.bV5BlueMask = 0x000000FF;
2128+ bi.bV5AlphaMask = 0xFF000000;
2129+
2130+ HDC hdc;
2131+
2132+ hdc = GetDC(NULL);
2133+ bitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
2134+ ReleaseDC(NULL, hdc);
2135+
2136+ const uchar *i = (const uchar*)*image->data();
2137+ for (int y = 0;y < image->h();y++) {
2138+ for (int x = 0;x < image->w();x++) {
2139+ switch (image->d()) {
2140+ case 1:
2141+ *bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
2142+ break;
2143+ case 2:
2144+ *bits = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
2145+ break;
2146+ case 3:
2147+ *bits = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
2148+ break;
2149+ case 4:
2150+ *bits = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
2151+ break;
2152+ }
2153+ i += image->d();
2154+ bits++;
2155+ }
2156+ i += image->ld();
2157+ }
2158+
2159+ // A mask bitmap is still needed even though it isn't used
2160+ mask = CreateBitmap(image->w(),image->h(),1,1,NULL);
2161+
2162+ ICONINFO ii;
2163+
2164+ ii.fIcon = FALSE;
2165+ ii.xHotspot = hotx;
2166+ ii.yHotspot = hoty;
2167+ ii.hbmMask = mask;
2168+ ii.hbmColor = bitmap;
2169+
2170+ cursor = CreateIconIndirect(&ii);
2171+
2172+ DeleteObject(bitmap);
2173+ DeleteObject(mask);
2174+
2175+ SetCursor(cursor);
2176+
2177+ return 1;
2178+ }
2179+
2180+ ////////////////////////////////////////////////////////////////
2181 // Implement the virtual functions for the base Fl_Window class:
2182
2183*** fltk-1.3.0/src/Fl_x.cxx 2011-05-30 11:47:48.000000000 -0500
2184--- fltk-1.3.0.new/src/Fl_x.cxx 2011-06-22 22:35:32.000000000 -0500
2185***************
2186*** 53,56 ****
2187--- 53,65 ----
2188 # include <X11/Xlib.h>
2189 # include <X11/keysym.h>
2190+ # include <X11/cursorfont.h>
2191+
2192+ # if HAVE_XCURSOR
2193+ # include <X11/Xcursor/Xcursor.h>
2194+ # endif
2195+
2196+ # ifdef HAVE_XFIXES
2197+ # include <X11/extensions/Xfixes.h>
2198+ # endif
2199
2200 static Fl_Xlib_Graphics_Driver fl_xlib_driver;
2201***************
2202*** 301,306 ****
2203--- 310,318 ----
2204 XIM fl_xim_im = 0;
2205 XIC fl_xim_ic = 0;
2206+ Window fl_xim_win = 0;
2207 char fl_is_over_the_spot = 0;
2208 static XRectangle status_area;
2209+ static bool have_xfixes = false;
2210+ static int xfixes_event_base = 0;
2211
2212 static Atom WM_DELETE_WINDOW;
2213***************
2214*** 309,312 ****
2215--- 321,327 ----
2216 static Atom TARGETS;
2217 static Atom CLIPBOARD;
2218+ static Atom TIMESTAMP;
2219+ static Atom PRIMARY_TIMESTAMP;
2220+ static Atom CLIPBOARD_TIMESTAMP;
2221 Atom fl_XdndAware;
2222 Atom fl_XdndSelection;
2223***************
2224*** 329,332 ****
2225--- 344,350 ----
2226 Atom fl_NET_WM_NAME; // utf8 aware window label
2227 Atom fl_NET_WM_ICON_NAME; // utf8 aware window icon name
2228+ Atom fl_NET_SUPPORTING_WM_CHECK;
2229+ Atom fl_NET_WM_STATE;
2230+ Atom fl_NET_WM_STATE_FULLSCREEN;
2231
2232 /*
2233***************
2234*** 582,585 ****
2235--- 600,662 ----
2236 }
2237
2238+ void fl_xim_deactivate(void);
2239+
2240+ void fl_xim_activate(Window xid)
2241+ {
2242+ if (!fl_xim_im)
2243+ return;
2244+
2245+ // If the focused window has changed, then use the brute force method
2246+ // of completely recreating the input context.
2247+ if (fl_xim_win != xid) {
2248+ fl_xim_deactivate();
2249+
2250+ fl_new_ic();
2251+ fl_xim_win = xid;
2252+
2253+ XSetICValues(fl_xim_ic,
2254+ XNFocusWindow, fl_xim_win,
2255+ XNClientWindow, fl_xim_win,
2256+ NULL);
2257+ }
2258+
2259+ fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2260+ }
2261+
2262+ void fl_xim_deactivate(void)
2263+ {
2264+ if (!fl_xim_ic)
2265+ return;
2266+
2267+ XDestroyIC(fl_xim_ic);
2268+ fl_xim_ic = NULL;
2269+
2270+ fl_xim_win = 0;
2271+ }
2272+
2273+ extern Fl_Window *fl_xfocus;
2274+
2275+ void fl_update_focus(void)
2276+ {
2277+ Fl_Widget *focus;
2278+
2279+ focus = Fl::grab();
2280+ if (!focus)
2281+ focus = Fl::focus();
2282+ if (!focus)
2283+ return;
2284+
2285+ if (focus->simple_keyboard()) {
2286+ fl_xim_deactivate();
2287+ } else {
2288+ // fl_xfocus should always be set if something has focus, but let's
2289+ // play it safe
2290+ if (!fl_xfocus || !fl_xid(fl_xfocus))
2291+ return;
2292+
2293+ fl_xim_activate(fl_xid(fl_xfocus));
2294+ }
2295+ }
2296+
2297 void fl_open_display() {
2298 if (fl_display) return;
2299***************
2300*** 605,608 ****
2301--- 682,688 ----
2302 TARGETS = XInternAtom(d, "TARGETS", 0);
2303 CLIPBOARD = XInternAtom(d, "CLIPBOARD", 0);
2304+ TIMESTAMP = XInternAtom(d, "TIMESTAMP", 0);
2305+ PRIMARY_TIMESTAMP = XInternAtom(d, "PRIMARY_TIMESTAMP", 0);
2306+ CLIPBOARD_TIMESTAMP = XInternAtom(d, "CLIPBOARD_TIMESTAMP", 0);
2307 fl_XdndAware = XInternAtom(d, "XdndAware", 0);
2308 fl_XdndSelection = XInternAtom(d, "XdndSelection", 0);
2309***************
2310*** 626,629 ****
2311--- 706,712 ----
2312 fl_NET_WM_NAME = XInternAtom(d, "_NET_WM_NAME", 0);
2313 fl_NET_WM_ICON_NAME = XInternAtom(d, "_NET_WM_ICON_NAME", 0);
2314+ fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
2315+ fl_NET_WM_STATE = XInternAtom(d, "_NET_WM_STATE", 0);
2316+ fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
2317
2318 if (sizeof(Atom) < 4)
2319***************
2320*** 647,650 ****
2321--- 730,741 ----
2322 Fl::visual(FL_RGB);
2323 #endif
2324+
2325+ #ifdef HAVE_XFIXES
2326+ int error_base;
2327+ if (XFixesQueryExtension(d, &xfixes_event_base, &error_base))
2328+ have_xfixes = true;
2329+ else
2330+ have_xfixes = false;
2331+ #endif
2332 }
2333
2334***************
2335*** 769,772 ****
2336--- 860,888 ----
2337 }
2338
2339+
2340+ /*
2341+ Get window property value (32 bit format)
2342+ Returns zero on success, -1 on error
2343+ */
2344+ static int get_xwinprop(Window wnd, Atom prop, long max_length,
2345+ unsigned long *nitems, unsigned long **data) {
2346+ Atom actual;
2347+ int format;
2348+ unsigned long bytes_after;
2349+
2350+ if (Success != XGetWindowProperty(fl_display, wnd, prop, 0, max_length,
2351+ False, AnyPropertyType, &actual, &format,
2352+ nitems, &bytes_after, (unsigned char**)data)) {
2353+ return -1;
2354+ }
2355+
2356+ if (actual == None || format != 32) {
2357+ return -1;
2358+ }
2359+
2360+ return 0;
2361+ }
2362+
2363+
2364 ////////////////////////////////////////////////////////////////
2365 // Code for copying to clipboard and DnD out of the program:
2366***************
2367*** 788,791 ****
2368--- 904,995 ----
2369
2370 ////////////////////////////////////////////////////////////////
2371+ // Code for tracking clipboard changes:
2372+
2373+ static Time primary_timestamp = -1;
2374+ static Time clipboard_timestamp = -1;
2375+
2376+ extern bool fl_clipboard_notify_empty(void);
2377+ extern void fl_trigger_clipboard_notify(int source);
2378+
2379+ static void poll_clipboard_owner(void) {
2380+ Window xid;
2381+
2382+ // No polling needed with Xfixes
2383+ if (have_xfixes)
2384+ return;
2385+
2386+ // No one is interested, so no point polling
2387+ if (fl_clipboard_notify_empty())
2388+ return;
2389+
2390+ // We need a window for this to work
2391+ if (!Fl::first_window())
2392+ return;
2393+ xid = fl_xid(Fl::first_window());
2394+ if (!xid)
2395+ return;
2396+
2397+ // Request an update of the selection time for both the primary and
2398+ // clipboard selections. Magic continues when we get a SelectionNotify.
2399+ if (!fl_i_own_selection[0])
2400+ XConvertSelection(fl_display, XA_PRIMARY, TIMESTAMP, PRIMARY_TIMESTAMP,
2401+ xid, fl_event_time);
2402+ if (!fl_i_own_selection[1])
2403+ XConvertSelection(fl_display, CLIPBOARD, TIMESTAMP, CLIPBOARD_TIMESTAMP,
2404+ xid, fl_event_time);
2405+ }
2406+
2407+ static void clipboard_timeout(void *data)
2408+ {
2409+ // No one is interested, so stop polling
2410+ if (fl_clipboard_notify_empty())
2411+ return;
2412+
2413+ poll_clipboard_owner();
2414+
2415+ Fl::repeat_timeout(0.5, clipboard_timeout);
2416+ }
2417+
2418+ static void handle_clipboard_timestamp(int clipboard, Time time)
2419+ {
2420+ Time *timestamp;
2421+
2422+ timestamp = clipboard ? &clipboard_timestamp : &primary_timestamp;
2423+
2424+ if (!have_xfixes) {
2425+ // Initial scan, just store the value
2426+ if (*timestamp == (Time)-1) {
2427+ *timestamp = time;
2428+ return;
2429+ }
2430+ }
2431+
2432+ // Same selection
2433+ if (time == *timestamp)
2434+ return;
2435+
2436+ *timestamp = time;
2437+
2438+ // Something happened! Let's tell someone!
2439+ fl_trigger_clipboard_notify(clipboard);
2440+ }
2441+
2442+ void fl_clipboard_notify_change() {
2443+ // Reset the timestamps if we've going idle so that you don't
2444+ // get a bogus immediate trigger next time they're activated.
2445+ if (fl_clipboard_notify_empty()) {
2446+ primary_timestamp = -1;
2447+ clipboard_timestamp = -1;
2448+ } else {
2449+ if (!have_xfixes) {
2450+ poll_clipboard_owner();
2451+
2452+ if (!Fl::has_timeout(clipboard_timeout))
2453+ Fl::add_timeout(0.5, clipboard_timeout);
2454+ }
2455+ }
2456+ }
2457+
2458+ ////////////////////////////////////////////////////////////////
2459
2460 const XEvent* fl_xevent; // the current x event
2461***************
2462*** 865,872 ****
2463 fl_xevent = &thisevent;
2464 Window xid = xevent.xany.window;
2465- static Window xim_win = 0;
2466
2467 if (fl_xim_ic && xevent.type == DestroyNotify &&
2468! xid != xim_win && !fl_find(xid))
2469 {
2470 XIM xim_im;
2471--- 1069,1075 ----
2472 fl_xevent = &thisevent;
2473 Window xid = xevent.xany.window;
2474
2475 if (fl_xim_ic && xevent.type == DestroyNotify &&
2476! xid != fl_xim_win && !fl_find(xid))
2477 {
2478 XIM xim_im;
2479***************
2480*** 883,929 ****
2481 }
2482
2483! if (fl_xim_ic && (xevent.type == FocusIn))
2484! {
2485! #define POOR_XIM
2486! #ifdef POOR_XIM
2487! if (xim_win != xid)
2488! {
2489! xim_win = xid;
2490! XDestroyIC(fl_xim_ic);
2491! fl_xim_ic = NULL;
2492! fl_new_ic();
2493! XSetICValues(fl_xim_ic,
2494! XNFocusWindow, xevent.xclient.window,
2495! XNClientWindow, xid,
2496! NULL);
2497! }
2498! fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2499! #else
2500! if (Fl::first_window() && Fl::first_window()->modal()) {
2501! Window x = fl_xid(Fl::first_window());
2502! if (x != xim_win) {
2503! xim_win = x;
2504! XSetICValues(fl_xim_ic,
2505! XNFocusWindow, xim_win,
2506! XNClientWindow, xim_win,
2507! NULL);
2508! fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2509! }
2510! } else if (xim_win != xid && xid) {
2511! xim_win = xid;
2512! XSetICValues(fl_xim_ic,
2513! XNFocusWindow, xevent.xclient.window,
2514! XNClientWindow, xid,
2515! //XNFocusWindow, xim_win,
2516! //XNClientWindow, xim_win,
2517! NULL);
2518! fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2519! }
2520! #endif
2521 }
2522
2523- if ( XFilterEvent((XEvent *)&xevent, 0) )
2524- return(1);
2525-
2526 switch (xevent.type) {
2527
2528--- 1086,1094 ----
2529 }
2530
2531! if (fl_xim_ic) {
2532! if (XFilterEvent((XEvent *)&xevent, 0))
2533! return 1;
2534 }
2535
2536 switch (xevent.type) {
2537
2538***************
2539*** 937,941 ****
2540
2541 case SelectionNotify: {
2542- if (!fl_selection_requestor) return 0;
2543 static unsigned char* buffer = 0;
2544 if (buffer) {XFree(buffer); buffer = 0;}
2545--- 1102,1105 ----
2546***************
2547*** 953,956 ****
2548--- 1117,1133 ----
2549 &actual, &format, &count, &remaining,
2550 &portion)) break; // quit on error
2551+
2552+ if ((fl_xevent->xselection.property == PRIMARY_TIMESTAMP) ||
2553+ (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)) {
2554+ if (portion && format == 32 && count == 1) {
2555+ Time t = *(unsigned int*)portion;
2556+ if (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)
2557+ handle_clipboard_timestamp(1, t);
2558+ else
2559+ handle_clipboard_timestamp(0, t);
2560+ }
2561+ return true;
2562+ }
2563+
2564 if (actual == TARGETS || actual == XA_ATOM) {
2565 Atom type = XA_STRING;
2566***************
2567*** 989,992 ****
2568--- 1166,1172 ----
2569 convert_crlf(buffer, bytesread);
2570 }
2571+
2572+ if (!fl_selection_requestor) return 0;
2573+
2574 Fl::e_text = buffer ? (char*)buffer : (char *)"";
2575 Fl::e_length = bytesread;
2576***************
2577*** 1009,1012 ****
2578--- 1189,1193 ----
2579 int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD;
2580 fl_i_own_selection[clipboard] = 0;
2581+ poll_clipboard_owner();
2582 return 1;}
2583
2584***************
2585*** 1221,1224 ****
2586--- 1402,1408 ----
2587 if (fl_xim_ic) XSetICFocus(fl_xim_ic);
2588 event = FL_FOCUS;
2589+ // If the user has toggled from another application to this one,
2590+ // then it's a good time to check for clipboard changes.
2591+ poll_clipboard_owner();
2592 break;
2593
2594***************
2595*** 1261,1273 ****
2596 len = XLookupString((XKeyEvent*)&(xevent.xkey),
2597 buffer, buffer_len, &keysym, 0/*&compose*/);
2598! if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets
2599! // force it to type a character (not sure if this ever is needed):
2600! // if (!len) {buffer[0] = char(keysym); len = 1;}
2601! len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
2602! if (len < 1) len = 1;
2603! // ignore all effects of shift on the keysyms, which makes it a lot
2604! // easier to program shortcuts and is Windoze-compatible:
2605! keysym = XKeycodeToKeysym(fl_display, keycode, 0);
2606! }
2607 }
2608 // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not
2609--- 1445,1457 ----
2610 len = XLookupString((XKeyEvent*)&(xevent.xkey),
2611 buffer, buffer_len, &keysym, 0/*&compose*/);
2612! // XLookupString() is only defined to return Latin-1 (although it
2613! // often gives you more). To be safe, use our own lookups based on
2614! // keysym.
2615! len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
2616! if (len < 1)
2617! len = 1;
2618! // ignore all effects of shift on the keysyms, which makes it a lot
2619! // easier to program shortcuts and is Windoze-compatable:
2620! keysym = XKeycodeToKeysym(fl_display, keycode, 0);
2621 }
2622 // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not
2623***************
2624*** 1441,1444 ****
2625--- 1625,1629 ----
2626 Fl::e_keysym = FL_Button + xevent.xbutton.button;
2627 set_event_xy();
2628+ Fl::e_dx = Fl::e_dy = 0;
2629 if (xevent.xbutton.button == Button4) {
2630 Fl::e_dy = -1; // Up
2631***************
2632*** 1447,1450 ****
2633--- 1632,1641 ----
2634 Fl::e_dy = +1; // Down
2635 event = FL_MOUSEWHEEL;
2636+ } else if (xevent.xbutton.button == 6) {
2637+ Fl::e_dx = -1; // Left
2638+ event = FL_MOUSEWHEEL;
2639+ } else if (xevent.xbutton.button == 7) {
2640+ Fl::e_dx = +1; // Right
2641+ event = FL_MOUSEWHEEL;
2642 } else {
2643 Fl::e_state |= (FL_BUTTON1 << (xevent.xbutton.button-1));
2644***************
2645*** 1457,1460 ****
2646--- 1648,1676 ----
2647 break;
2648
2649+ case PropertyNotify:
2650+ if (xevent.xproperty.atom == fl_NET_WM_STATE) {
2651+ int fullscreen_state = 0;
2652+ if (xevent.xproperty.state != PropertyDelete) {
2653+ unsigned long nitems;
2654+ unsigned long *words = 0;
2655+ if (0 == get_xwinprop(xid, fl_NET_WM_STATE, 64, &nitems, &words) ) {
2656+ for (unsigned long item = 0; item < nitems; item++) {
2657+ if (words[item] == fl_NET_WM_STATE_FULLSCREEN) {
2658+ fullscreen_state = 1;
2659+ }
2660+ }
2661+ }
2662+ }
2663+ if (window->fullscreen_active() && !fullscreen_state) {
2664+ window->_clear_fullscreen();
2665+ event = FL_FULLSCREEN;
2666+ }
2667+ if (!window->fullscreen_active() && fullscreen_state) {
2668+ window->_set_fullscreen();
2669+ event = FL_FULLSCREEN;
2670+ }
2671+ }
2672+ break;
2673+
2674 case MotionNotify:
2675 set_event_xy();
2676***************
2677*** 1557,1560 ****
2678--- 1773,1795 ----
2679 }
2680
2681+ #ifdef HAVE_XFIXES
2682+ switch (xevent.type - xfixes_event_base) {
2683+ case XFixesSelectionNotify: {
2684+ // Someone feeding us bogus events?
2685+ if (!have_xfixes)
2686+ return true;
2687+
2688+ XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)&xevent;
2689+
2690+ if ((selection_notify->selection == XA_PRIMARY) && !fl_i_own_selection[0])
2691+ handle_clipboard_timestamp(0, selection_notify->selection_timestamp);
2692+ else if ((selection_notify->selection == CLIPBOARD) && !fl_i_own_selection[1])
2693+ handle_clipboard_timestamp(1, selection_notify->selection_timestamp);
2694+
2695+ return true;
2696+ }
2697+ }
2698+ #endif
2699+
2700 return Fl::handle(event, window);
2701 }
2702***************
2703*** 1596,1599 ****
2704--- 1831,1903 ----
2705 ////////////////////////////////////////////////////////////////
2706
2707+ #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2708+ #define _NET_WM_STATE_ADD 1 /* add/set property */
2709+ #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2710+
2711+ static void send_wm_state_event(Window wnd, int add, Atom prop) {
2712+ XEvent e;
2713+ e.xany.type = ClientMessage;
2714+ e.xany.window = wnd;
2715+ e.xclient.message_type = fl_NET_WM_STATE;
2716+ e.xclient.format = 32;
2717+ e.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2718+ e.xclient.data.l[1] = prop;
2719+ e.xclient.data.l[2] = 0;
2720+ e.xclient.data.l[3] = 0;
2721+ e.xclient.data.l[4] = 0;
2722+ XSendEvent(fl_display, RootWindow(fl_display, fl_screen),
2723+ 0, SubstructureNotifyMask | SubstructureRedirectMask,
2724+ &e);
2725+ }
2726+
2727+ int ewmh_supported() {
2728+ static int result = -1;
2729+
2730+ if (result == -1) {
2731+ result = 0;
2732+ unsigned long nitems;
2733+ unsigned long *words = 0;
2734+ if (0 == get_xwinprop(XRootWindow(fl_display, fl_screen), fl_NET_SUPPORTING_WM_CHECK, 64,
2735+ &nitems, &words) && nitems == 1) {
2736+ Window child = words[0];
2737+ if (0 == get_xwinprop(child, fl_NET_SUPPORTING_WM_CHECK, 64,
2738+ &nitems, &words) && nitems == 1) {
2739+ result = (child == words[0]);
2740+ }
2741+ }
2742+ }
2743+
2744+ return result;
2745+ }
2746+
2747+ /* Change an existing window to fullscreen */
2748+ void fullscreen_x(Fl_Window *w) {
2749+ if (ewmh_supported()) {
2750+ send_wm_state_event(fl_xid(w), 1, fl_NET_WM_STATE_FULLSCREEN);
2751+ } else {
2752+ w->_set_fullscreen();
2753+ w->hide();
2754+ w->show();
2755+ /* We want to grab the window, not a widget, so we cannot use Fl::grab */
2756+ XGrabKeyboard(fl_display, fl_xid(w), 1, GrabModeAsync, GrabModeAsync, fl_event_time);
2757+ Fl::handle(FL_FULLSCREEN, w);
2758+ }
2759+ }
2760+
2761+ void fullscreen_off_x(Fl_Window *w, int X, int Y, int W, int H) {
2762+ if (ewmh_supported()) {
2763+ send_wm_state_event(fl_xid(w), 0, fl_NET_WM_STATE_FULLSCREEN);
2764+ } else {
2765+ w->_clear_fullscreen();
2766+ /* The grab will be lost when the window is destroyed */
2767+ w->hide();
2768+ w->resize(X,Y,W,H);
2769+ w->show();
2770+ Fl::handle(FL_FULLSCREEN, w);
2771+ }
2772+ }
2773+
2774+ ////////////////////////////////////////////////////////////////
2775+
2776 // A subclass of Fl_Window may call this to associate an X window it
2777 // creates with the Fl_Window:
2778***************
2779*** 1631,1634 ****
2780--- 1935,1939 ----
2781 |ButtonPressMask|ButtonReleaseMask
2782 |EnterWindowMask|LeaveWindowMask
2783+ |PropertyChangeMask
2784 |PointerMotionMask;
2785
2786***************
2787*** 1702,1705 ****
2788--- 2007,2020 ----
2789 if (!win->border()) {attr.override_redirect = 1; mask |= CWOverrideRedirect;}
2790 }
2791+ // For the non-EWMH fullscreen case, we cannot use the code above,
2792+ // since we do not want save_under, do not want to turn off the
2793+ // border, and cannot grab without an existing window. Besides,
2794+ // there is no clear_override().
2795+ if (win->flags() & Fl_Widget::FULLSCREEN && !ewmh_supported()) {
2796+ attr.override_redirect = 1;
2797+ mask |= CWOverrideRedirect;
2798+ Fl::screen_xywh(X, Y, W, H, X, Y, W, H);
2799+ }
2800+
2801 if (fl_background_pixel >= 0) {
2802 attr.background_pixel = fl_background_pixel;
2803***************
2804*** 1761,1764 ****
2805--- 2076,2085 ----
2806 }
2807
2808+ // If asked for, create fullscreen
2809+ if (win->flags() & Fl_Widget::FULLSCREEN && ewmh_supported()) {
2810+ XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32,
2811+ PropModeAppend, (unsigned char*) &fl_NET_WM_STATE_FULLSCREEN, 1);
2812+ }
2813+
2814 // Make it receptive to DnD:
2815 long version = 4;
2816***************
2817*** 1790,1793 ****
2818--- 2111,2124 ----
2819 }
2820
2821+ #ifdef HAVE_XFIXES
2822+ // register for clipboard change notifications
2823+ if (have_xfixes && !win->parent()) {
2824+ XFixesSelectSelectionInput(fl_display, xp->xid, XA_PRIMARY,
2825+ XFixesSetSelectionOwnerNotifyMask);
2826+ XFixesSelectSelectionInput(fl_display, xp->xid, CLIPBOARD,
2827+ XFixesSetSelectionOwnerNotifyMask);
2828+ }
2829+ #endif
2830+
2831 XMapWindow(fl_display, xp->xid);
2832 if (showit) {
2833***************
2834*** 1798,1801 ****
2835--- 2129,2138 ----
2836 win->redraw();
2837 }
2838+
2839+ // non-EWMH fullscreen case, need grab
2840+ if (win->flags() & Fl_Widget::FULLSCREEN && !ewmh_supported()) {
2841+ XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync, fl_event_time);
2842+ }
2843+
2844 }
2845
2846***************
2847*** 1884,1887 ****
2848--- 2221,2312 ----
2849 ////////////////////////////////////////////////////////////////
2850
2851+ int Fl_X::set_cursor(Fl_Cursor c) {
2852+ unsigned int shape;
2853+ Cursor xc;
2854+
2855+ switch (c) {
2856+ case FL_CURSOR_ARROW: shape = XC_left_ptr; break;
2857+ case FL_CURSOR_CROSS: shape = XC_tcross; break;
2858+ case FL_CURSOR_WAIT: shape = XC_watch; break;
2859+ case FL_CURSOR_INSERT: shape = XC_xterm; break;
2860+ case FL_CURSOR_HAND: shape = XC_hand2; break;
2861+ case FL_CURSOR_HELP: shape = XC_question_arrow; break;
2862+ case FL_CURSOR_MOVE: shape = XC_fleur; break;
2863+ case FL_CURSOR_NS: shape = XC_sb_v_double_arrow; break;
2864+ case FL_CURSOR_WE: shape = XC_sb_h_double_arrow; break;
2865+ case FL_CURSOR_NE: shape = XC_top_right_corner; break;
2866+ case FL_CURSOR_N: shape = XC_top_side; break;
2867+ case FL_CURSOR_NW: shape = XC_top_left_corner; break;
2868+ case FL_CURSOR_E: shape = XC_right_side; break;
2869+ case FL_CURSOR_W: shape = XC_left_side; break;
2870+ case FL_CURSOR_SE: shape = XC_bottom_right_corner; break;
2871+ case FL_CURSOR_S: shape = XC_bottom_side; break;
2872+ case FL_CURSOR_SW: shape = XC_bottom_left_corner; break;
2873+ default:
2874+ return 0;
2875+ }
2876+
2877+ xc = XCreateFontCursor(fl_display, shape);
2878+ XDefineCursor(fl_display, xid, xc);
2879+ XFreeCursor(fl_display, xc);
2880+
2881+ return 1;
2882+ }
2883+
2884+ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
2885+ #if ! HAVE_XCURSOR
2886+ return 0;
2887+ #else
2888+ XcursorImage *cursor;
2889+ Cursor xc;
2890+
2891+ if ((hotx < 0) || (hotx >= image->w()))
2892+ return 0;
2893+ if ((hoty < 0) || (hoty >= image->h()))
2894+ return 0;
2895+
2896+ cursor = XcursorImageCreate(image->w(), image->h());
2897+ if (!cursor)
2898+ return 0;
2899+
2900+ const uchar *i = (const uchar*)*image->data();
2901+ XcursorPixel *o = cursor->pixels;
2902+ for (int y = 0;y < image->h();y++) {
2903+ for (int x = 0;x < image->w();x++) {
2904+ switch (image->d()) {
2905+ case 1:
2906+ *o = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
2907+ break;
2908+ case 2:
2909+ *o = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
2910+ break;
2911+ case 3:
2912+ *o = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
2913+ break;
2914+ case 4:
2915+ *o = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
2916+ break;
2917+ }
2918+ i += image->d();
2919+ o++;
2920+ }
2921+ i += image->ld();
2922+ }
2923+
2924+ cursor->xhot = hotx;
2925+ cursor->yhot = hoty;
2926+
2927+ xc = XcursorImageLoadCursor(fl_display, cursor);
2928+ XDefineCursor(fl_display, xid, xc);
2929+ XFreeCursor(fl_display, xc);
2930+
2931+ XcursorImageDestroy(cursor);
2932+
2933+ return 1;
2934+ #endif
2935+ }
2936+
2937+ ////////////////////////////////////////////////////////////////
2938+
2939 // returns pointer to the filename, or null if name ends with '/'
2940 const char *fl_filename_name(const char *name) {
2941*** fltk-1.3.0/src/fl_cursor.cxx 2010-12-18 16:31:01.000000000 -0600
2942--- fltk-1.3.0.new/src/fl_cursor.cxx 2011-06-22 22:35:32.000000000 -0500
2943***************
2944*** 34,331 ****
2945 #include <FL/Fl.H>
2946 #include <FL/Fl_Window.H>
2947 #include <FL/x.H>
2948- #if !defined(WIN32) && !defined(__APPLE__)
2949- # include <X11/cursorfont.h>
2950- #endif
2951 #include <FL/fl_draw.H>
2952
2953 /**
2954 Sets the cursor for the current window to the specified shape and colors.
2955 The cursors are defined in the <FL/Enumerations.H> header file.
2956 */
2957 void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
2958! if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg);
2959 }
2960 /**
2961! Sets the default window cursor as well as its color.
2962
2963! For back compatibility only.
2964 */
2965! void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
2966! // if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW;
2967!
2968 cursor_default = c;
2969! cursor_fg = fg;
2970! cursor_bg = bg;
2971
2972! cursor(c, fg, bg);
2973 }
2974
2975- #ifdef WIN32
2976
2977! # ifndef IDC_HAND
2978! # define IDC_HAND MAKEINTRESOURCE(32649)
2979! # endif // !IDC_HAND
2980
2981- void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) {
2982- if (!shown()) return;
2983 // the cursor must be set for the top level window, not for subwindows
2984 Fl_Window *w = window(), *toplevel = this;
2985! while (w) { toplevel = w; w = w->window(); }
2986! if (toplevel != this) { toplevel->cursor(c, c1, c2); return; }
2987! // now set the actual cursor
2988! if (c == FL_CURSOR_DEFAULT) {
2989! c = cursor_default;
2990! }
2991! if (c > FL_CURSOR_NESW) {
2992! i->cursor = 0;
2993! } else if (c == FL_CURSOR_DEFAULT) {
2994! i->cursor = fl_default_cursor;
2995! } else {
2996! LPSTR n;
2997! switch (c) {
2998! case FL_CURSOR_ARROW: n = IDC_ARROW; break;
2999! case FL_CURSOR_CROSS: n = IDC_CROSS; break;
3000! case FL_CURSOR_WAIT: n = IDC_WAIT; break;
3001! case FL_CURSOR_INSERT: n = IDC_IBEAM; break;
3002! case FL_CURSOR_HELP: n = IDC_HELP; break;
3003! case FL_CURSOR_HAND: {
3004! OSVERSIONINFO osvi;
3005!
3006! // Get the OS version: Windows 98 and 2000 have a standard
3007! // hand cursor.
3008! memset(&osvi, 0, sizeof(OSVERSIONINFO));
3009! osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
3010! GetVersionEx(&osvi);
3011!
3012! if (osvi.dwMajorVersion > 4 ||
3013! (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0 &&
3014! osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)) n = IDC_HAND;
3015! else n = IDC_UPARROW;
3016! } break;
3017! case FL_CURSOR_MOVE: n = IDC_SIZEALL; break;
3018! case FL_CURSOR_N:
3019! case FL_CURSOR_S:
3020! case FL_CURSOR_NS: n = IDC_SIZENS; break;
3021! case FL_CURSOR_NE:
3022! case FL_CURSOR_SW:
3023! case FL_CURSOR_NESW: n = IDC_SIZENESW; break;
3024! case FL_CURSOR_E:
3025! case FL_CURSOR_W:
3026! case FL_CURSOR_WE: n = IDC_SIZEWE; break;
3027! case FL_CURSOR_SE:
3028! case FL_CURSOR_NW:
3029! case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break;
3030! default: n = IDC_NO; break;
3031! }
3032! i->cursor = LoadCursor(NULL, n);
3033 }
3034- SetCursor(i->cursor);
3035- }
3036
3037! #elif defined(__APPLE__)
3038
3039! #ifdef __BIG_ENDIAN__
3040! # define E(x) x
3041! #elif defined __LITTLE_ENDIAN__
3042! // Don't worry. This will be resolved at compile time
3043! # define E(x) (x>>8)|((x<<8)&0xff00)
3044! #else
3045! # error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined"
3046! #endif
3047!
3048! extern Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h);
3049!
3050!
3051! CGContextRef Fl_X::help_cursor_image(void)
3052! {
3053! int w = 20, h = 20;
3054! Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
3055! fl_begin_offscreen(off);
3056! CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
3057! fl_rectf(0,0,w,h);
3058! fl_color(FL_BLACK);
3059! fl_font(FL_COURIER_BOLD, 20);
3060! fl_draw("?", 1, h-1);
3061! fl_end_offscreen();
3062! return (CGContextRef)off;
3063! }
3064
3065! CGContextRef Fl_X::none_cursor_image(void)
3066! {
3067! int w = 20, h = 20;
3068! Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
3069! fl_begin_offscreen(off);
3070! CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
3071! fl_rectf(0,0,w,h);
3072! fl_end_offscreen();
3073! return (CGContextRef)off;
3074! }
3075
3076! CGContextRef Fl_X::watch_cursor_image(void)
3077! {
3078! int w, h, r = 5;
3079! w = 2*r+6;
3080! h = 4*r;
3081! Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
3082! fl_begin_offscreen(off);
3083! CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
3084! fl_rectf(0,0,w,h);
3085! CGContextTranslateCTM( (CGContextRef)off, w/2, h/2);
3086! fl_color(FL_WHITE);
3087! fl_circle(0, 0, r+1);
3088! fl_color(FL_BLACK);
3089! fl_rectf(int(-r*0.7), int(-r*1.7), int(1.4*r), int(3.4*r));
3090! fl_rectf(r-1, -1, 3, 3);
3091! fl_color(FL_WHITE);
3092! fl_pie(-r, -r, 2*r, 2*r, 0, 360);
3093! fl_color(FL_BLACK);
3094! fl_circle(0,0,r);
3095! fl_xyline(0, 0, int(-r*.7));
3096! fl_xyline(0, 0, 0, int(-r*.7));
3097! fl_end_offscreen();
3098! return (CGContextRef)off;
3099! }
3100
3101! CGContextRef Fl_X::nesw_cursor_image(void)
3102! {
3103! int c = 7, r = 2*c;
3104! int w = r, h = r;
3105! Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
3106! fl_begin_offscreen(off);
3107! CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
3108! fl_rectf(0,0,w,h);
3109! CGContextTranslateCTM( (CGContextRef)off, 0, h);
3110! CGContextScaleCTM( (CGContextRef)off, 1, -1);
3111! fl_color(FL_BLACK);
3112! fl_polygon(0, 0, c, 0, 0, c);
3113! fl_polygon(r, r, r, r-c, r-c, r);
3114! fl_line_style(FL_SOLID, 2, 0);
3115! fl_line(0,1, r,r+1);
3116! fl_line_style(FL_SOLID, 0, 0);
3117! fl_end_offscreen();
3118! return (CGContextRef)off;
3119 }
3120
3121! CGContextRef Fl_X::nwse_cursor_image(void)
3122! {
3123! int c = 7, r = 2*c;
3124! int w = r, h = r;
3125! Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
3126! fl_begin_offscreen(off);
3127! CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
3128! fl_rectf(0,0,w,h);
3129! CGContextTranslateCTM( (CGContextRef)off, 0, h);
3130! CGContextScaleCTM( (CGContextRef)off, 1, -1);
3131! fl_color(FL_BLACK);
3132! fl_polygon(r-1, 0, r-1, c, r-1-c, 0);
3133! fl_polygon(-1, r, c-1, r, -1, r-c);
3134! fl_line_style(FL_SOLID, 2, 0);
3135! fl_line(r-1,1, -1,r+1);
3136! fl_line_style(FL_SOLID, 0, 0);
3137! fl_end_offscreen();
3138! return (CGContextRef)off;
3139! }
3140
3141! void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
3142! if (c == FL_CURSOR_DEFAULT) {
3143! c = cursor_default;
3144! }
3145! if (i) i->set_cursor(c);
3146! }
3147
3148! #else
3149
3150! // I like the MSWindows resize cursors, so I duplicate them here:
3151
3152! #define CURSORSIZE 16
3153! #define HOTXY 7
3154! static struct TableEntry {
3155! uchar bits[CURSORSIZE*CURSORSIZE/8];
3156! uchar mask[CURSORSIZE*CURSORSIZE/8];
3157! Cursor cursor;
3158! } table[] = {
3159! {{ // FL_CURSOR_NS
3160! 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
3161! 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
3162! 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
3163! {
3164! 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
3165! 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
3166! 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
3167! {{ // FL_CURSOR_EW
3168! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
3169! 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
3170! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3171! {
3172! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
3173! 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
3174! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
3175! {{ // FL_CURSOR_NWSE
3176! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
3177! 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
3178! 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3179! {
3180! 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
3181! 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
3182! 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
3183! {{ // FL_CURSOR_NESW
3184! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
3185! 0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
3186! 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3187! {
3188! 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
3189! 0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
3190! 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
3191! {{0}, {0}} // FL_CURSOR_NONE & unknown
3192! };
3193!
3194! void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
3195! if (!shown()) return;
3196! Cursor xc;
3197! int deleteit = 0;
3198! if (c == FL_CURSOR_DEFAULT) {
3199! c = cursor_default;
3200! fg = cursor_fg;
3201! bg = cursor_bg;
3202 }
3203
3204! if (!c) {
3205! xc = None;
3206! } else {
3207! if (c >= FL_CURSOR_NS) {
3208! TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
3209! if (!(q->cursor)) {
3210! XColor dummy = { 0 };
3211! Pixmap p = XCreateBitmapFromData(fl_display,
3212! RootWindow(fl_display, fl_screen), (const char*)(q->bits),
3213! CURSORSIZE, CURSORSIZE);
3214! Pixmap m = XCreateBitmapFromData(fl_display,
3215! RootWindow(fl_display, fl_screen), (const char*)(q->mask),
3216! CURSORSIZE, CURSORSIZE);
3217! q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy,
3218! HOTXY, HOTXY);
3219! XFreePixmap(fl_display, m);
3220! XFreePixmap(fl_display, p);
3221! }
3222! xc = q->cursor;
3223! } else {
3224! xc = XCreateFontCursor(fl_display, (c-1)*2);
3225! deleteit = 1;
3226! }
3227! XColor fgc;
3228! uchar r,g,b;
3229! Fl::get_color(fg,r,g,b);
3230! fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8;
3231! XColor bgc;
3232! Fl::get_color(bg,r,g,b);
3233! bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8;
3234! XRecolorCursor(fl_display, xc, &fgc, &bgc);
3235 }
3236- XDefineCursor(fl_display, fl_xid(this), xc);
3237- if (deleteit) XFreeCursor(fl_display, xc);
3238- }
3239
3240! #endif
3241
3242 //
3243--- 34,186 ----
3244 #include <FL/Fl.H>
3245 #include <FL/Fl_Window.H>
3246+ #include <FL/Fl_Pixmap.H>
3247+ #include <FL/Fl_RGB_Image.H>
3248 #include <FL/x.H>
3249 #include <FL/fl_draw.H>
3250
3251+ #include "fl_cursor_wait.xpm"
3252+ #include "fl_cursor_help.xpm"
3253+ #include "fl_cursor_nwse.xpm"
3254+ #include "fl_cursor_nesw.xpm"
3255+ #include "fl_cursor_none.xpm"
3256+
3257 /**
3258 Sets the cursor for the current window to the specified shape and colors.
3259 The cursors are defined in the <FL/Enumerations.H> header file.
3260 */
3261+ void fl_cursor(Fl_Cursor c) {
3262+ if (Fl::first_window()) Fl::first_window()->cursor(c);
3263+ }
3264+
3265+ /* For back compatibility only. */
3266 void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
3267! fl_cursor(c);
3268 }
3269+
3270+
3271 /**
3272! Sets the default window cursor. This is the cursor that will be used
3273! after the mouse pointer leaves a widget with a custom cursor set.
3274
3275! \see cursor(const Fl_RGB_Image*, int, int), default_cursor()
3276 */
3277! void Fl_Window::default_cursor(Fl_Cursor c) {
3278 cursor_default = c;
3279! cursor(c);
3280! }
3281!
3282
3283! void fallback_cursor(Fl_Window *w, Fl_Cursor c) {
3284! const char **xpm;
3285! int hotx, hoty;
3286!
3287! // The standard arrow is our final fallback, so something is broken
3288! // if we get called back here with that as an argument.
3289! if (c == FL_CURSOR_ARROW)
3290! return;
3291!
3292! switch (c) {
3293! case FL_CURSOR_WAIT:
3294! xpm = (const char**)fl_cursor_wait_xpm;
3295! hotx = 8;
3296! hoty = 15;
3297! break;
3298! case FL_CURSOR_HELP:
3299! xpm = (const char**)fl_cursor_help_xpm;
3300! hotx = 1;
3301! hoty = 3;
3302! break;
3303! case FL_CURSOR_NWSE:
3304! xpm = (const char**)fl_cursor_nwse_xpm;
3305! hotx = 7;
3306! hoty = 7;
3307! break;
3308! case FL_CURSOR_NESW:
3309! xpm = (const char**)fl_cursor_nesw_xpm;
3310! hotx = 7;
3311! hoty = 7;
3312! break;
3313! case FL_CURSOR_NONE:
3314! xpm = (const char**)fl_cursor_none_xpm;
3315! hotx = 0;
3316! hoty = 0;
3317! break;
3318! default:
3319! w->cursor(FL_CURSOR_ARROW);
3320! return;
3321! }
3322!
3323! Fl_Pixmap pxm(xpm);
3324! Fl_RGB_Image image(&pxm);
3325!
3326! w->cursor(&image, hotx, hoty);
3327 }
3328
3329
3330! void Fl_Window::cursor(Fl_Cursor c) {
3331! int ret;
3332
3333 // the cursor must be set for the top level window, not for subwindows
3334 Fl_Window *w = window(), *toplevel = this;
3335!
3336! while (w) {
3337! toplevel = w;
3338! w = w->window();
3339 }
3340
3341! if (toplevel != this) {
3342! toplevel->cursor(c);
3343! return;
3344! }
3345
3346! if (c == FL_CURSOR_DEFAULT)
3347! c = cursor_default;
3348
3349! if (!i)
3350! return;
3351
3352! ret = i->set_cursor(c);
3353! if (ret)
3354! return;
3355
3356! fallback_cursor(this, c);
3357 }
3358
3359! /**
3360! Changes the cursor for this window. This always calls the system, if
3361! you are changing the cursor a lot you may want to keep track of how
3362! you set it in a static variable and call this only if the new cursor
3363! is different.
3364
3365! The default cursor will be used if the provided image cannot be used
3366! as a cursor.
3367
3368! \see cursor(Fl_Cursor), default_cursor()
3369! */
3370! void Fl_Window::cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
3371! int ret;
3372
3373! // the cursor must be set for the top level window, not for subwindows
3374! Fl_Window *w = window(), *toplevel = this;
3375
3376! while (w) {
3377! toplevel = w;
3378! w = w->window();
3379 }
3380
3381! if (toplevel != this) {
3382! toplevel->cursor(image, hotx, hoty);
3383! return;
3384 }
3385
3386! if (!i)
3387! return;
3388!
3389! ret = i->set_cursor(image, hotx, hoty);
3390! if (ret)
3391! return;
3392!
3393! cursor(FL_CURSOR_DEFAULT);
3394! }
3395
3396 //
3397*** fltk-1.3.0/src/fl_draw_pixmap.cxx 2011-02-02 12:39:34.000000000 -0600
3398--- fltk-1.3.0.new/src/fl_draw_pixmap.cxx 2011-06-22 22:46:30.000000000 -0500
3399***************
3400*** 68,164 ****
3401 }
3402
3403- #ifdef U64
3404-
3405- // The callback from fl_draw_image to get a row of data passes this:
3406- struct pixmap_data {
3407- int w, h;
3408- const uchar*const* data;
3409- union {
3410- U64 colors[256];
3411- U64* byte1[256];
3412- };
3413- };
3414-
3415- // callback for 1 byte per pixel:
3416- static void cb1(void*v, int x, int y, int w, uchar* buf) {
3417- pixmap_data& d = *(pixmap_data*)v;
3418- const uchar* p = d.data[y]+x;
3419- U64* q = (U64*)buf;
3420- for (int X=w; X>0; X-=2, p += 2) {
3421- if (X>1) {
3422- # if WORDS_BIGENDIAN
3423- *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]];
3424- # else
3425- *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]];
3426- # endif
3427- } else {
3428- # if WORDS_BIGENDIAN
3429- *q++ = d.colors[p[0]]<<32;
3430- # else
3431- *q++ = d.colors[p[0]];
3432- # endif
3433- }
3434- }
3435- }
3436-
3437- // callback for 2 bytes per pixel:
3438- static void cb2(void*v, int x, int y, int w, uchar* buf) {
3439- pixmap_data& d = *(pixmap_data*)v;
3440- const uchar* p = d.data[y]+2*x;
3441- U64* q = (U64*)buf;
3442- for (int X=w; X>0; X-=2) {
3443- U64* colors = d.byte1[*p++];
3444- int index = *p++;
3445- if (X>1) {
3446- U64* colors1 = d.byte1[*p++];
3447- int index1 = *p++;
3448- # if WORDS_BIGENDIAN
3449- *q++ = (colors[index]<<32) | colors1[index1];
3450- # else
3451- *q++ = (colors1[index1]<<32) | colors[index];
3452- # endif
3453- } else {
3454- # if WORDS_BIGENDIAN
3455- *q++ = colors[index]<<32;
3456- # else
3457- *q++ = colors[index];
3458- # endif
3459- }
3460- }
3461- }
3462-
3463- #else // U32
3464-
3465- // The callback from fl_draw_image to get a row of data passes this:
3466- struct pixmap_data {
3467- int w, h;
3468- const uchar*const* data;
3469- union {
3470- U32 colors[256];
3471- U32* byte1[256];
3472- };
3473- };
3474-
3475- // callback for 1 byte per pixel:
3476- static void cb1(void*v, int x, int y, int w, uchar* buf) {
3477- pixmap_data& d = *(pixmap_data*)v;
3478- const uchar* p = d.data[y]+x;
3479- U32* q = (U32*)buf;
3480- for (int X=w; X--;) *q++ = d.colors[*p++];
3481- }
3482-
3483- // callback for 2 bytes per pixel:
3484- static void cb2(void*v, int x, int y, int w, uchar* buf) {
3485- pixmap_data& d = *(pixmap_data*)v;
3486- const uchar* p = d.data[y]+2*x;
3487- U32* q = (U32*)buf;
3488- for (int X=w; X--;) {
3489- U32* colors = d.byte1[*p++];
3490- *q++ = colors[*p++];
3491- }
3492- }
3493-
3494- #endif // U64 else U32
3495-
3496 uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here
3497
3498--- 68,71 ----
3499***************
3500*** 210,223 ****
3501 #endif
3502
3503! /**
3504! Draw XPM image data, with the top-left corner at the given position.
3505! \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
3506! */
3507! int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
3508! pixmap_data d;
3509! if (!fl_measure_pixmap(cdata, d.w, d.h)) return 0;
3510 const uchar*const* data = (const uchar*const*)(cdata+1);
3511 int transparent_index = -1;
3512 uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color
3513 #ifdef WIN32
3514 color_count = 0;
3515--- 117,134 ----
3516 #endif
3517
3518! int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg) {
3519! int w, h;
3520 const uchar*const* data = (const uchar*const*)(cdata+1);
3521 int transparent_index = -1;
3522 uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color
3523+
3524+ if (!fl_measure_pixmap(cdata, w, h))
3525+ return 0;
3526+
3527+ if ((chars_per_pixel < 1) || (chars_per_pixel > 2))
3528+ return 0;
3529+
3530+ uchar (*colors)[4] = new uchar [1<<(chars_per_pixel*8)][4];
3531+
3532 #ifdef WIN32
3533 color_count = 0;
3534***************
3535*** 225,229 ****
3536 #endif
3537
3538! if (ncolors < 0) { // FLTK (non standard) compressed colormap
3539 ncolors = -ncolors;
3540 const uchar *p = *data++;
3541--- 136,141 ----
3542 #endif
3543
3544! if (ncolors < 0) {
3545! // FLTK (non standard) compressed colormap
3546 ncolors = -ncolors;
3547 const uchar *p = *data++;
3548***************
3549*** 231,241 ****
3550 // it not be transparent):
3551 if (*p == ' ') {
3552! uchar* c = (uchar*)&d.colors[(int)' '];
3553! #ifdef U64
3554! *(U64*)c = 0;
3555! # if WORDS_BIGENDIAN
3556! c += 4;
3557! # endif
3558! #endif
3559 transparent_index = ' ';
3560 Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
3561--- 143,147 ----
3562 // it not be transparent):
3563 if (*p == ' ') {
3564! uchar* c = colors[(int)' '];
3565 transparent_index = ' ';
3566 Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
3567***************
3568*** 246,256 ****
3569 // read all the rest of the colors:
3570 for (int i=0; i < ncolors; i++) {
3571! uchar* c = (uchar*)&d.colors[*p++];
3572! #ifdef U64
3573! *(U64*)c = 0;
3574! # if WORDS_BIGENDIAN
3575! c += 4;
3576! # endif
3577! #endif
3578 #ifdef WIN32
3579 used_colors[3*color_count] = *p;
3580--- 152,156 ----
3581 // read all the rest of the colors:
3582 for (int i=0; i < ncolors; i++) {
3583! uchar* c = colors[*p++];
3584 #ifdef WIN32
3585 used_colors[3*color_count] = *p;
3586***************
3587*** 262,273 ****
3588 *c++ = *p++;
3589 *c++ = *p++;
3590- #ifdef __APPLE_QUARTZ__
3591 *c = 255;
3592- #else
3593- *c = 0;
3594- #endif
3595 }
3596! } else { // normal XPM colormap with names
3597! if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1));
3598 for (int i=0; i<ncolors; i++) {
3599 const uchar *p = *data++;
3600--- 162,169 ----
3601 *c++ = *p++;
3602 *c++ = *p++;
3603 *c = 255;
3604 }
3605! } else {
3606! // normal XPM colormap with names
3607 for (int i=0; i<ncolors; i++) {
3608 const uchar *p = *data++;
3609***************
3610*** 275,334 ****
3611 int ind = *p++;
3612 uchar* c;
3613! if (chars_per_pixel>1) {
3614! #ifdef U64
3615! U64* colors = d.byte1[ind];
3616! if (!colors) colors = d.byte1[ind] = new U64[256];
3617! #else
3618! U32* colors = d.byte1[ind];
3619! if (!colors) colors = d.byte1[ind] = new U32[256];
3620! #endif
3621! c = (uchar*)&colors[*p];
3622! ind = (ind<<8)|*p++;
3623! } else {
3624! c = (uchar *)&d.colors[ind];
3625! }
3626 // look for "c word", or last word if none:
3627 const uchar *previous_word = p;
3628 for (;;) {
3629! while (*p && isspace(*p)) p++;
3630! uchar what = *p++;
3631! while (*p && !isspace(*p)) p++;
3632! while (*p && isspace(*p)) p++;
3633! if (!*p) {p = previous_word; break;}
3634! if (what == 'c') break;
3635! previous_word = p;
3636! while (*p && !isspace(*p)) p++;
3637 }
3638- #ifdef U64
3639- *(U64*)c = 0;
3640- # if WORDS_BIGENDIAN
3641- c += 4;
3642- # endif
3643- #endif
3644- #ifdef __APPLE_QUARTZ__
3645- c[3] = 255;
3646- #endif
3647 int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]);
3648 if (parse) {
3649 #ifdef WIN32
3650! used_colors[3*color_count] = c[0];
3651! used_colors[3*color_count+1] = c[1];
3652! used_colors[3*color_count+2] = c[2];
3653! color_count++;
3654 #endif
3655! }
3656! else {
3657 // assume "None" or "#transparent" for any errors
3658! // "bg" should be transparent...
3659! Fl::get_color(bg, c[0], c[1], c[2]);
3660! #ifdef __APPLE_QUARTZ__
3661 c[3] = 0;
3662! #endif
3663! transparent_index = ind;
3664! transparent_c = c;
3665 }
3666 }
3667 }
3668- d.data = data;
3669 #ifdef WIN32
3670 if (transparent_c) {
3671--- 171,208 ----
3672 int ind = *p++;
3673 uchar* c;
3674! if (chars_per_pixel>1)
3675! ind = (ind<<8)|*p++;
3676! c = colors[ind];
3677 // look for "c word", or last word if none:
3678 const uchar *previous_word = p;
3679 for (;;) {
3680! while (*p && isspace(*p)) p++;
3681! uchar what = *p++;
3682! while (*p && !isspace(*p)) p++;
3683! while (*p && isspace(*p)) p++;
3684! if (!*p) {p = previous_word; break;}
3685! if (what == 'c') break;
3686! previous_word = p;
3687! while (*p && !isspace(*p)) p++;
3688 }
3689 int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]);
3690+ c[3] = 255;
3691 if (parse) {
3692 #ifdef WIN32
3693! used_colors[3*color_count] = c[0];
3694! used_colors[3*color_count+1] = c[1];
3695! used_colors[3*color_count+2] = c[2];
3696! color_count++;
3697 #endif
3698! } else {
3699 // assume "None" or "#transparent" for any errors
3700! // "bg" should be transparent...
3701! Fl::get_color(bg, c[0], c[1], c[2]);
3702 c[3] = 0;
3703! transparent_index = ind;
3704! transparent_c = c;
3705 }
3706 }
3707 }
3708 #ifdef WIN32
3709 if (transparent_c) {
3710***************
3711*** 340,425 ****
3712 }
3713 #endif
3714
3715 #ifdef __APPLE_QUARTZ__
3716 if (fl_graphics_driver->class_name() == Fl_Quartz_Graphics_Driver::class_id ) {
3717- bool transparent = (transparent_index>=0);
3718- transparent = true;
3719- U32 *array = new U32[d.w * d.h], *q = array;
3720- for (int Y = 0; Y < d.h; Y++) {
3721- const uchar* p = data[Y];
3722- if (chars_per_pixel <= 1) {
3723- for (int X = 0; X < d.w; X++) {
3724- *q++ = d.colors[*p++];
3725- }
3726- } else {
3727- for (int X = 0; X < d.w; X++) {
3728- U32* colors = (U32*)d.byte1[*p++];
3729- *q++ = colors[*p++];
3730- }
3731- }
3732- }
3733 CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
3734! CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, d.w * d.h * 4, 0L);
3735! CGImageRef img = CGImageCreate(d.w, d.h, 8, 4*8, 4*d.w,
3736! lut, transparent?kCGImageAlphaLast:kCGImageAlphaNoneSkipLast,
3737! src, 0L, false, kCGRenderingIntentDefault);
3738 CGColorSpaceRelease(lut);
3739 CGDataProviderRelease(src);
3740! CGRect rect = { { x, y} , { d.w, d.h } };
3741! Fl_X::q_begin_image(rect, 0, 0, d.w, d.h);
3742 CGContextDrawImage(fl_gc, rect, img);
3743 Fl_X::q_end_image();
3744 CGImageRelease(img);
3745! delete[] array;
3746! }
3747! else {
3748 #endif // __APPLE_QUARTZ__
3749-
3750 // build the mask bitmap used by Fl_Pixmap:
3751! if (fl_mask_bitmap && transparent_index >= 0) {
3752! int W = (d.w+7)/8;
3753! uchar* bitmap = new uchar[W * d.h];
3754 *fl_mask_bitmap = bitmap;
3755! for (int Y = 0; Y < d.h; Y++) {
3756! const uchar* p = data[Y];
3757! if (chars_per_pixel <= 1) {
3758! int dw = d.w;
3759! for (int X = 0; X < W; X++) {
3760! uchar b = (dw-->0 && *p++ != transparent_index);
3761! if (dw-->0 && *p++ != transparent_index) b |= 2;
3762! if (dw-->0 && *p++ != transparent_index) b |= 4;
3763! if (dw-->0 && *p++ != transparent_index) b |= 8;
3764! if (dw-->0 && *p++ != transparent_index) b |= 16;
3765! if (dw-->0 && *p++ != transparent_index) b |= 32;
3766! if (dw-->0 && *p++ != transparent_index) b |= 64;
3767! if (dw-->0 && *p++ != transparent_index) b |= 128;
3768! *bitmap++ = b;
3769! }
3770! } else {
3771! uchar b = 0, bit = 1;
3772! for (int X = 0; X < d.w; X++) {
3773! int ind = *p++;
3774! ind = (ind<<8) | (*p++);
3775! if (ind != transparent_index) b |= bit;
3776!
3777! if (bit < 128) bit <<= 1;
3778! else {
3779! *bitmap++ = b;
3780! b = 0;
3781! bit = 1;
3782! }
3783! }
3784!
3785! if (bit > 1) *bitmap++ = b;
3786 }
3787 }
3788 }
3789
3790! fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4);
3791 #ifdef __APPLE_QUARTZ__
3792 }
3793 #endif
3794
3795! if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i];
3796 return 1;
3797 }
3798--- 214,300 ----
3799 }
3800 #endif
3801+
3802+ U32 *q = (U32*)out;
3803+ for (int Y = 0; Y < h; Y++) {
3804+ const uchar* p = data[Y];
3805+ if (chars_per_pixel <= 1) {
3806+ for (int X = 0; X < w; X++)
3807+ memcpy(q++, colors[*p++], 4);
3808+ } else {
3809+ for (int X = 0; X < w; X++) {
3810+ int ind = (*p++)<<8;
3811+ ind |= *p++;
3812+ memcpy(q++, colors[ind], 4);
3813+ }
3814+ }
3815+ }
3816
3817+ delete [] colors;
3818+ return 1;
3819+ }
3820+
3821+ /**
3822+ Draw XPM image data, with the top-left corner at the given position.
3823+ \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
3824+ */
3825+ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
3826+ int w, h;
3827+
3828+ if (!fl_measure_pixmap(cdata, w, h))
3829+ return 0;
3830+
3831+ uchar *buffer = new uchar[w*h*4];
3832+
3833+ if (!fl_convert_pixmap(cdata, buffer, bg)) {
3834+ delete buffer;
3835+ return 0;
3836+ }
3837+
3838+ // FIXME: Hack until fl_draw_image() supports alpha properly
3839 #ifdef __APPLE_QUARTZ__
3840 if (fl_graphics_driver->class_name() == Fl_Quartz_Graphics_Driver::class_id ) {
3841 CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
3842! CGDataProviderRef src = CGDataProviderCreateWithData( 0L, buffer, w * h * 4, 0L);
3843! CGImageRef img = CGImageCreate(w, h, 8, 4*8, 4*w,
3844! lut, kCGImageAlphaLast,
3845! src, 0L, false, kCGRenderingIntentDefault);
3846 CGColorSpaceRelease(lut);
3847 CGDataProviderRelease(src);
3848! CGRect rect = { { x, y }, { w, h } };
3849! Fl_X::q_begin_image(rect, 0, 0, w, h);
3850 CGContextDrawImage(fl_gc, rect, img);
3851 Fl_X::q_end_image();
3852 CGImageRelease(img);
3853! } else {
3854 #endif // __APPLE_QUARTZ__
3855 // build the mask bitmap used by Fl_Pixmap:
3856! if (fl_mask_bitmap) {
3857! int W = (w+7)/8;
3858! uchar* bitmap = new uchar[W * h];
3859 *fl_mask_bitmap = bitmap;
3860! const uchar *p = &buffer[3];
3861! for (int Y = 0; Y < h; Y++) {
3862! int dw = w;
3863! for (int X = 0; X < W; X++) {
3864! uchar b = 0;
3865! for (int bit = 0x01;bit <= 0x80;bit<<=1) {
3866! if (dw-- < 0)
3867! break;
3868! if (*p > 127)
3869! b |= bit;
3870! p += 4;
3871! }
3872! *bitmap++ = b;
3873 }
3874 }
3875 }
3876
3877! fl_draw_image(buffer, x, y, w, h, 4);
3878!
3879 #ifdef __APPLE_QUARTZ__
3880 }
3881 #endif
3882
3883! delete buffer;
3884 return 1;
3885 }
3886*** fltk-1.3.0/src/xutf8/imKStoUCS.c 2009-03-13 17:43:43.000000000 -0500
3887--- fltk-1.3.0.new/src/xutf8/imKStoUCS.c 2011-06-22 22:35:31.000000000 -0500
3888***************
3889*** 267,270 ****
3890--- 267,276 ----
3891 };
3892
3893+ static unsigned short const keysym_to_unicode_fe50_fe60[] = {
3894+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0306, 0x0307, 0x0308, /* 0xfe50-0xfe57 */
3895+ 0x030a, 0x030b, 0x030c, 0x0327, 0x0328, 0x1da5, 0x3099, 0x309a, /* 0xfe58-0xfe5f */
3896+ 0x0323 /* 0xfe60-0xfe67 */
3897+ };
3898+
3899 unsigned int
3900 KeySymToUcs4(KeySym keysym)
3901***************
3902*** 316,319 ****
3903--- 322,327 ----
3904 else if (keysym > 0x209f && keysym < 0x20ad)
3905 return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
3906+ else if (keysym > 0xfe4f && keysym < 0xfe61)
3907+ return keysym_to_unicode_fe50_fe60[keysym - 0xfe50];
3908 else
3909 return 0;
3910*** fltk-1.3.0/test/cursor.cxx 2010-12-08 08:00:35.000000000 -0600
3911--- fltk-1.3.0.new/test/cursor.cxx 2011-06-22 22:35:32.000000000 -0500
3912***************
3913*** 33,38 ****
3914 #include <FL/Fl_Box.H>
3915
3916- Fl_Color fg = FL_BLACK;
3917- Fl_Color bg = FL_WHITE;
3918 Fl_Cursor cursor = FL_CURSOR_DEFAULT;
3919
3920--- 33,36 ----
3921***************
3922*** 42,46 ****
3923 cursor = (Fl_Cursor)(fl_intptr_t)v;
3924 cursor_slider->value(cursor);
3925! fl_cursor(cursor,fg,bg);
3926 }
3927
3928--- 40,44 ----
3929 cursor = (Fl_Cursor)(fl_intptr_t)v;
3930 cursor_slider->value(cursor);
3931! fl_cursor(cursor);
3932 }
3933
3934***************
3935*** 58,63 ****
3936 {"FL_CURSOR_NWSE",0,choice_cb,(void*)FL_CURSOR_NWSE},
3937 {"FL_CURSOR_NESW",0,choice_cb,(void*)FL_CURSOR_NESW},
3938- {"FL_CURSOR_NONE",0,choice_cb,(void*)FL_CURSOR_NONE},
3939- #if 0
3940 {"FL_CURSOR_N",0,choice_cb,(void*)FL_CURSOR_N},
3941 {"FL_CURSOR_NE",0,choice_cb,(void*)FL_CURSOR_NE},
3942--- 56,59 ----
3943***************
3944*** 68,72 ****
3945 {"FL_CURSOR_W",0,choice_cb,(void*)FL_CURSOR_W},
3946 {"FL_CURSOR_NW",0,choice_cb,(void*)FL_CURSOR_NW},
3947! #endif
3948 {0}
3949 };
3950--- 64,68 ----
3951 {"FL_CURSOR_W",0,choice_cb,(void*)FL_CURSOR_W},
3952 {"FL_CURSOR_NW",0,choice_cb,(void*)FL_CURSOR_NW},
3953! {"FL_CURSOR_NONE",0,choice_cb,(void*)FL_CURSOR_NONE},
3954 {0}
3955 };
3956***************
3957*** 75,91 ****
3958 Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3959 cursor = Fl_Cursor((int)slider->value());
3960! fl_cursor(cursor,fg,bg);
3961! }
3962!
3963! void setfg(Fl_Widget *o, void *) {
3964! Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3965! fg = Fl_Color((int)slider->value());
3966! fl_cursor(cursor,fg,bg);
3967! }
3968!
3969! void setbg(Fl_Widget *o, void *) {
3970! Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3971! bg = Fl_Color((int)slider->value());
3972! fl_cursor(cursor,fg,bg);
3973 }
3974
3975--- 71,75 ----
3976 Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3977 cursor = Fl_Cursor((int)slider->value());
3978! fl_cursor(cursor);
3979 }
3980
3981***************
3982*** 113,139 ****
3983 slider1.step(1);
3984 slider1.precision(0);
3985! slider1.bounds(0,100);
3986 slider1.value(0);
3987 slider1.callback(setcursor);
3988 slider1.value(cursor);
3989
3990- Fl_Hor_Value_Slider slider2(80,220,310,30,"fgcolor:");
3991- slider2.align(FL_ALIGN_LEFT);
3992- slider2.step(1);
3993- slider2.precision(0);
3994- slider2.bounds(0,255);
3995- slider2.value(0);
3996- slider2.callback(setfg);
3997- slider2.value(fg);
3998-
3999- Fl_Hor_Value_Slider slider3(80,260,310,30,"bgcolor:");
4000- slider3.align(FL_ALIGN_LEFT);
4001- slider3.step(1);
4002- slider3.precision(0);
4003- slider3.bounds(0,255);
4004- slider3.value(0);
4005- slider3.callback(setbg);
4006- slider3.value(bg);
4007-
4008 #if 0
4009 // draw the manual's diagram of cursors...
4010--- 97,105 ----
4011 slider1.step(1);
4012 slider1.precision(0);
4013! slider1.bounds(0,255);
4014 slider1.value(0);
4015 slider1.callback(setcursor);
4016 slider1.value(cursor);
4017
4018 #if 0
4019 // draw the manual's diagram of cursors...
4020*** fltk-1.3.0/test/fullscreen.cxx 2010-12-15 06:11:16.000000000 -0600
4021--- fltk-1.3.0.new/test/fullscreen.cxx 2011-06-22 22:35:32.000000000 -0500
4022***************
4023*** 61,66 ****
4024--- 61,69 ----
4025 #include <FL/Fl_Single_Window.H>
4026 #include <FL/Fl_Hor_Slider.H>
4027+ #include <FL/Fl_Input.H>
4028+ #include <FL/Fl_Menu_Button.H>
4029 #include <FL/Fl_Toggle_Light_Button.H>
4030 #include <FL/math.h>
4031+ #include <FL/fl_ask.H>
4032 #include <stdio.h>
4033
4034***************
4035*** 125,128 ****
4036--- 128,153 ----
4037 #endif
4038
4039+ class fullscreen_window : public Fl_Single_Window {
4040+
4041+ public:
4042+ fullscreen_window(int W, int H, const char *t=0);
4043+ int handle (int e);
4044+ Fl_Toggle_Light_Button *b3;
4045+
4046+ };
4047+
4048+ fullscreen_window::fullscreen_window(int W, int H, const char *t) : Fl_Single_Window(W, H, t) {
4049+
4050+ }
4051+
4052+ int fullscreen_window::handle(int e) {
4053+ if (e == FL_FULLSCREEN) {
4054+ printf("Recieved FL_FULLSCREEN event\n");
4055+ b3->value(fullscreen_active());
4056+ }
4057+ if (Fl_Single_Window::handle(e)) return 1;
4058+ return 0;
4059+ }
4060+
4061 void sides_cb(Fl_Widget *o, void *p) {
4062 shape_window *sw = (shape_window *)p;
4063***************
4064*** 162,172 ****
4065 pw = w->w();
4066 ph = w->h();
4067- #ifndef WIN32//necessary because fullscreen removes border
4068- border_button->value(0);
4069- border_button->do_callback();
4070- #endif
4071 w->fullscreen();
4072 } else {
4073! w->fullscreen_off(px,py,pw,ph);
4074 }
4075 }
4076--- 187,198 ----
4077 pw = w->w();
4078 ph = w->h();
4079 w->fullscreen();
4080+ w->override();
4081+ #ifndef WIN32 // update our border state in case border was turned off
4082+ border_button->value(w->border());
4083+ #endif
4084 } else {
4085! //w->fullscreen_off(px,py,pw,ph);
4086! w->fullscreen_off();
4087 }
4088 }
4089***************
4090*** 178,182 ****
4091 }
4092
4093! #define NUMB 5
4094
4095 int twowindow = 0;
4096--- 204,208 ----
4097 }
4098
4099! #define NUMB 6
4100
4101 int twowindow = 0;
4102***************
4103*** 194,198 ****
4104 Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help);
4105
4106! Fl_Single_Window window(300,300+30*NUMB); window.end();
4107
4108 shape_window sw(10,10,window.w()-20,window.h()-30*NUMB-20);
4109--- 220,224 ----
4110 Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help);
4111
4112! fullscreen_window window(300,300+30*NUMB); window.end();
4113
4114 shape_window sw(10,10,window.w()-20,window.h()-30*NUMB-20);
4115***************
4116*** 229,232 ****
4117--- 255,261 ----
4118 y+=30;
4119
4120+ Fl_Input i1(50,y,window.w()-60,30, "Input");
4121+ y+=30;
4122+
4123 Fl_Toggle_Light_Button b2(50,y,window.w()-60,30,"Border");
4124 b2.callback(border_cb,w);
4125***************
4126*** 235,240 ****
4127 y+=30;
4128
4129! Fl_Toggle_Light_Button b3(50,y,window.w()-60,30,"FullScreen");
4130! b3.callback(fullscreen_cb,w);
4131 y+=30;
4132
4133--- 264,269 ----
4134 y+=30;
4135
4136! window.b3 = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"FullScreen");
4137! window.b3->callback(fullscreen_cb,w);
4138 y+=30;
4139
4140***************
4141*** 243,247 ****
4142 y+=30;
4143
4144! if (initfull) {b3.set(); b3.do_callback();}
4145
4146 window.end();
4147--- 272,276 ----
4148 y+=30;
4149
4150! if (initfull) {window.b3->set(); window.b3->do_callback();}
4151
4152 window.end();