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