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