View | Details | Raw Unified | Return to bug 182006
Collapse All | Expand All

(-)x11-toolkits/fltk/Makefile (+1 lines)
Lines 3-8 Link Here
3
3
4
PORTNAME=	fltk
4
PORTNAME=	fltk
5
PORTVERSION=	1.3.2
5
PORTVERSION=	1.3.2
6
PORTREVISION=	1
6
CATEGORIES=	x11-toolkits
7
CATEGORIES=	x11-toolkits
7
MASTER_SITES=	http://fltk.org/pub/${PORTNAME}/${PORTVERSION}/
8
MASTER_SITES=	http://fltk.org/pub/${PORTNAME}/${PORTVERSION}/
8
DISTNAME=	${PORTNAME}-${PORTVERSION}-source
9
DISTNAME=	${PORTNAME}-${PORTVERSION}-source
(-)x11-toolkits/fltk/files/patch-00-tigervnc (+3903 lines)
Line 0 Link Here
1
diff -Nur CMakeLists.txt CMakeLists.txt
2
--- CMakeLists.txt	2012-09-13 16:19:01.000000000 +0200
3
+++ CMakeLists.txt	2013-07-17 19:37:45.782342898 +0200
4
@@ -515,6 +515,34 @@
5
 endif(OPTION_USE_XINERAMA)
6
 
7
 #######################################################################
8
+if(X11_Xfixes_FOUND)
9
+   option(OPTION_USE_XFIXES "use lib XFIXES" ON)
10
+endif(X11_Xfixes_FOUND)
11
+
12
+if(OPTION_USE_XFIXES)
13
+   set(HAVE_XFIXES ${X11_Xfixes_FOUND})
14
+   include_directories(${X11_Xfixes_INCLUDE_PATH})
15
+   list(APPEND FLTK_LDLIBS -lXfixes)
16
+   set(FLTK_XFIXES_FOUND TRUE)
17
+else()
18
+   set(FLTK_XFIXES_FOUND FALSE)
19
+endif(OPTION_USE_XFIXES)
20
+
21
+#######################################################################
22
+if(X11_Xcursor_FOUND)
23
+   option(OPTION_USE_XCURSOR "use lib XCURSOR" ON)
24
+endif(X11_Xcursor_FOUND)
25
+
26
+if(OPTION_USE_XCURSOR)
27
+   set(HAVE_XCURSOR ${X11_Xcursor_FOUND})
28
+   include_directories(${X11_Xcursor_INCLUDE_PATH})
29
+   list(APPEND FLTK_LDLIBS -lXcursor)
30
+   set(FLTK_XCURSOR_FOUND TRUE)
31
+else()
32
+   set(FLTK_XCURSOR_FOUND FALSE)
33
+endif(OPTION_USE_XCURSOR)
34
+
35
+#######################################################################
36
 if(X11_Xft_FOUND)
37
    option(OPTION_USE_XFT "use lib Xft" ON)
38
 endif(X11_Xft_FOUND)
39
diff -Nur configh.cmake.in configh.cmake.in
40
--- configh.cmake.in	2011-07-19 06:49:30.000000000 +0200
41
+++ configh.cmake.in	2013-07-17 19:37:45.782342898 +0200
42
@@ -108,6 +108,22 @@
43
 #define USE_XDBE HAVE_XDBE
44
 
45
 /*
46
+ * HAVE_XFIXES:
47
+ *
48
+ * Do we have the X fixes extension?
49
+ */
50
+
51
+#cmakedefine01 HAVE_XFIXES
52
+
53
+/*
54
+ * HAVE_XCURSOR:
55
+ *
56
+ * Do we have the X cursor library?
57
+ */
58
+
59
+#cmakedefine01 HAVE_XCURSOR
60
+
61
+/*
62
  * __APPLE_QUARTZ__:
63
  *
64
  * If __APPLE_QUARTZ__ is defined, FLTK will be
65
diff -Nur configh.in configh.in
66
--- configh.in	2011-10-04 11:21:47.000000000 +0200
67
+++ configh.in	2013-07-17 19:37:45.783342892 +0200
68
@@ -108,6 +108,22 @@
69
 #define USE_XDBE HAVE_XDBE
70
 
71
 /*
72
+ * HAVE_XFIXES:
73
+ *
74
+ * Do we have the X fixes extension?
75
+ */
76
+
77
+#define HAVE_XFIXES 0
78
+
79
+/*
80
+ * HAVE_XCURSOR:
81
+ *
82
+ * Do we have the X cursor library?
83
+ */
84
+
85
+#define HAVE_XCURSOR 0
86
+
87
+/*
88
  * __APPLE_QUARTZ__:
89
  *
90
  * All Apple implementations are now based on Quartz and Cocoa,
91
diff -Nur configure.in configure.in
92
--- configure.in	2012-11-06 22:13:54.000000000 +0100
93
+++ configure.in	2013-07-17 19:37:45.784342888 +0200
94
@@ -997,6 +997,26 @@
95
 		LIBS="-lXext $LIBS")
96
 	fi
97
 
98
+	dnl Check for the Xfixes extension unless disabled...
99
+        AC_ARG_ENABLE(xfixes, [  --enable-xfixes       turn on Xfixes support [default=yes]])
100
+
101
+	if test x$enable_xfixes != xno; then
102
+	    AC_CHECK_HEADER(X11/extensions/Xfixes.h, AC_DEFINE(HAVE_XFIXES),,
103
+	        [#include <X11/Xlib.h>])
104
+	    AC_CHECK_LIB(Xfixes, XFixesQueryExtension,
105
+		LIBS="-lXfixes $LIBS")
106
+	fi
107
+
108
+	dnl Check for the Xcursor library unless disabled...
109
+        AC_ARG_ENABLE(xcursor, [  --enable-xcursor        turn on Xcursor support [default=yes]])
110
+
111
+	if test x$enable_xcursor != xno; then
112
+	    AC_CHECK_HEADER(X11/Xcursor/Xcursor.h, AC_DEFINE(HAVE_XCURSOR),,
113
+	        [#include <X11/Xlib.h>])
114
+	    AC_CHECK_LIB(Xcursor, XcursorImageCreate,
115
+		LIBS="-lXcursor $LIBS")
116
+	fi
117
+
118
 	dnl Check for overlay visuals...
119
 	AC_PATH_PROG(XPROP, xprop)
120
 	AC_CACHE_CHECK(for X overlay visuals, ac_cv_have_overlay,
121
diff -Nur FL/Enumerations.H FL/Enumerations.H
122
--- FL/Enumerations.H	2012-12-09 19:45:57.000000000 +0100
123
+++ FL/Enumerations.H	2013-07-17 19:37:45.785342886 +0200
124
@@ -879,35 +879,36 @@
125
 
126
 /** The following constants define the mouse cursors that are available in FLTK.
127
 
128
-    The double-headed arrows are bitmaps provided by FLTK on X, the others
129
-    are provided by system-defined cursors.
130
+    Cursors are provided by the system when available, or bitmaps built into
131
+    FLTK as a fallback.
132
 
133
     \todo enum Fl_Cursor needs maybe an image.
134
 */
135
 enum Fl_Cursor {
136
   FL_CURSOR_DEFAULT	=  0, /**< the default cursor, usually an arrow. */
137
-  FL_CURSOR_ARROW	= 35, /**< an arrow pointer. */
138
-  FL_CURSOR_CROSS	= 66, /**< crosshair. */
139
-  FL_CURSOR_WAIT	= 76, /**< watch or hourglass. */
140
-  FL_CURSOR_INSERT	= 77, /**< I-beam. */
141
-  FL_CURSOR_HAND	= 31, /**< hand (uparrow on MSWindows). */
142
-  FL_CURSOR_HELP	= 47, /**< question mark. */
143
-  FL_CURSOR_MOVE	= 27, /**< 4-pointed arrow. */
144
-  // fltk provides bitmaps for these:
145
-  FL_CURSOR_NS		= 78, /**< up/down arrow. */
146
-  FL_CURSOR_WE		= 79, /**< left/right arrow. */
147
-  FL_CURSOR_NWSE	= 80, /**< diagonal arrow. */
148
-  FL_CURSOR_NESW	= 81, /**< diagonal arrow. */
149
-  FL_CURSOR_NONE	=255, /**< invisible. */
150
-  // for back compatibility (non MSWindows ones):
151
-  FL_CURSOR_N		= 70, /**< for back compatibility. */
152
-  FL_CURSOR_NE		= 69, /**< for back compatibility. */
153
-  FL_CURSOR_E		= 49, /**< for back compatibility. */
154
-  FL_CURSOR_SE		=  8, /**< for back compatibility. */
155
-  FL_CURSOR_S		=  9, /**< for back compatibility. */
156
-  FL_CURSOR_SW		=  7, /**< for back compatibility. */
157
-  FL_CURSOR_W		= 36, /**< for back compatibility. */
158
-  FL_CURSOR_NW		= 68 /**< for back compatibility. */
159
+  FL_CURSOR_ARROW   = 1,    /**< an arrow pointer. */
160
+  FL_CURSOR_CROSS   = 2,    /**< crosshair. */
161
+  FL_CURSOR_WAIT    = 3,    /**< busy indicator (e.g. hourglass). */
162
+  FL_CURSOR_INSERT  = 4,    /**< I-beam. */
163
+  FL_CURSOR_HAND    = 5,    /**< pointing hand. */
164
+  FL_CURSOR_HELP    = 6,    /**< question mark pointer. */
165
+  FL_CURSOR_MOVE    = 7,    /**< 4-pointed arrow or hand. */
166
+
167
+  /* Resize indicators */
168
+  FL_CURSOR_NS      = 101,  /**< up/down resize. */
169
+  FL_CURSOR_WE      = 102,  /**< left/right resize. */
170
+  FL_CURSOR_NWSE    = 103,  /**< diagonal resize. */
171
+  FL_CURSOR_NESW    = 104,  /**< diagonal resize. */
172
+  FL_CURSOR_NE      = 110,  /**< upwards, right resize. */
173
+  FL_CURSOR_N       = 111,  /**< upwards resize. */
174
+  FL_CURSOR_NW      = 112,  /**< upwards, left resize. */
175
+  FL_CURSOR_E       = 113,  /**< leftwards resize. */
176
+  FL_CURSOR_W       = 114,  /**< rightwards resize. */
177
+  FL_CURSOR_SE      = 115,  /**< downwards, right resize. */
178
+  FL_CURSOR_S       = 116,  /**< downwards resize. */
179
+  FL_CURSOR_SW      = 117,  /**< downwards, left resize. */
180
+
181
+  FL_CURSOR_NONE    = 255,  /**< invisible. */
182
 };
183
 /*@}*/		// group: Cursors  
184
 
185
diff -Nur FL/fl_draw.H FL/fl_draw.H
186
--- FL/fl_draw.H	2012-05-08 18:15:34.000000000 +0200
187
+++ FL/fl_draw.H	2013-07-17 19:37:45.785342886 +0200
188
@@ -751,7 +751,8 @@
189
 FL_EXPORT unsigned int fl_old_shortcut(const char* s);
190
 FL_EXPORT void fl_overlay_rect(int x,int y,int w,int h);
191
 FL_EXPORT void fl_overlay_clear();
192
-FL_EXPORT void fl_cursor(Fl_Cursor, Fl_Color fg=FL_BLACK, Fl_Color bg=FL_WHITE);
193
+FL_EXPORT void fl_cursor(Fl_Cursor);
194
+FL_EXPORT void fl_cursor(Fl_Cursor, Fl_Color fg, Fl_Color bg=FL_WHITE);
195
 FL_EXPORT const char* fl_expand_text(const char* from, char* buf, int maxbuf,
196
                                      double maxw, int& n, double &width,
197
                                      int wrap, int draw_symbols = 0);
198
diff -Nur FL/Fl.H FL/Fl.H
199
--- FL/Fl.H	2012-10-18 14:56:31.000000000 +0200
200
+++ FL/Fl.H	2013-07-17 19:38:09.574341653 +0200
201
@@ -109,6 +109,9 @@
202
     \see Fl::event_dispatch(Fl_Event_Dispatch) */
203
 typedef int (*Fl_Event_Dispatch)(int event, Fl_Window *w);
204
 
205
+/** Signature of add_clipboard_notify functions passed as parameters */
206
+typedef void (*Fl_Clipboard_Notify_Handler)(int source, void *data);
207
+
208
 /** @} */ /* group callback_functions */
209
 
210
 
211
@@ -746,6 +749,19 @@
212
   */
213
   static void paste(Fl_Widget &receiver, int source /*=0*/); // platform dependent
214
   /**
215
+  FLTK will call the registered callback whenever there is a change to the
216
+  selection buffer or the clipboard. The source argument indicates which
217
+  of the two has changed. Only changes by other applications are reported.
218
+  \note Some systems require polling to monitor the clipboard and may
219
+  therefore have some delay in detecting changes.
220
+  */
221
+  static void add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data);
222
+  /**
223
+  Stop calling the specified callback when there are changes to the selection
224
+  buffer or the clipboard.
225
+  */
226
+  static void remove_clipboard_notify(Fl_Clipboard_Notify_Handler h);
227
+  /**
228
     Initiate a Drag And Drop operation. The selection buffer should be
229
     filled with relevant data before calling this method. FLTK will
230
     then initiate the system wide drag and drop handling. Dropped data
231
@@ -792,6 +808,8 @@
232
   static void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my);
233
   static void screen_xywh(int &X, int &Y, int &W, int &H, int n); 
234
   static void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh);
235
+  static int screen_num(int x, int y);
236
+  static int screen_num(int x, int y, int w, int h);
237
   static void screen_dpi(float &h, float &v, int n=0);
238
   static void screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my);
239
   static void screen_work_area(int &X, int &Y, int &W, int &H, int n);
240
diff -Nur FL/Fl_Image.H FL/Fl_Image.H
241
--- FL/Fl_Image.H	2012-11-09 17:02:08.000000000 +0100
242
+++ FL/Fl_Image.H	2013-07-17 19:37:37.910343301 +0200
243
@@ -26,6 +26,7 @@
244
 #include <stdlib.h>
245
 
246
 class Fl_Widget;
247
+class Fl_Pixmap;
248
 struct Fl_Menu_Item;
249
 struct Fl_Label;
250
 
251
@@ -203,6 +204,7 @@
252
   */
253
   Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0) :
254
     Fl_Image(W,H,D), array(bits), alloc_array(0), id_(0), mask_(0) {data((const char **)&array, 1); ld(LD);}
255
+  Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg=FL_GRAY);
256
   virtual ~Fl_RGB_Image();
257
   virtual Fl_Image *copy(int W, int H);
258
   Fl_Image *copy() { return copy(w(), h()); }
259
diff -Nur FL/Fl_Widget.H FL/Fl_Widget.H
260
--- FL/Fl_Widget.H	2012-04-23 22:12:06.000000000 +0200
261
+++ FL/Fl_Widget.H	2013-07-17 19:37:07.411344886 +0200
262
@@ -171,6 +171,7 @@
263
         GROUP_RELATIVE  = 1<<16,  ///< position this widget relative to the parent group, not to the window
264
         COPIED_TOOLTIP  = 1<<17,  ///< the widget tooltip is internally copied, its destruction is handled by the widget
265
         FULLSCREEN      = 1<<18,  ///< a fullscreen window (Fl_Window)
266
+        SIMPLE_KEYBOARD = 1<<19,  ///< the widget wants simple, consistent keypresses and not advanced input (like character composition and CJK input)
267
         // (space for more flags)
268
         USERFLAG3       = 1<<29,  ///< reserved for 3rd party extensions
269
         USERFLAG2       = 1<<30,  ///< reserved for 3rd party extensions
270
@@ -776,6 +777,35 @@
271
    */
272
   void clear_changed() {flags_ &= ~CHANGED;}
273
 
274
+  /** 
275
+      Returns if the widget sees a simplified keyboard model or not.
276
+
277
+      Normally widgets get a full-featured keyboard model that is geared
278
+      towards text input. This includes support for compose sequences and
279
+      advanced input methods, commonly used for asian writing system. This
280
+      system however has downsides in that extra graphic can be presented
281
+      to the user and that a physical key press doesn't correspond directly
282
+      to a FLTK event.
283
+
284
+      Widgets that need a direct correspondence between actual key events
285
+      and those seen by the widget can swith to the simplified keyboard
286
+      model.
287
+
288
+     \retval 0 if the widget uses the normal keyboard model
289
+     \see set_changed(), clear_changed()
290
+   */
291
+  unsigned int simple_keyboard() const {return flags_&SIMPLE_KEYBOARD;}
292
+
293
+  /** Marks a widget to use the simple keyboard model.
294
+      \see changed(), clear_changed()
295
+   */
296
+  void set_simple_keyboard() {flags_ |= SIMPLE_KEYBOARD;}
297
+
298
+  /** Marks a widget to use the normal keyboard model.
299
+      \see changed(), set_changed()
300
+   */
301
+  void set_normal_keyboard() {flags_ &= ~SIMPLE_KEYBOARD;}
302
+
303
   /** Gives the widget the keyboard focus.
304
       Tries to make this widget be the Fl::focus() widget, by first sending 
305
       it an FL_FOCUS event, and if it returns non-zero, setting 
306
diff -Nur FL/Fl_Window.H FL/Fl_Window.H
307
--- FL/Fl_Window.H	2012-11-06 21:46:14.000000000 +0100
308
+++ FL/Fl_Window.H	2013-07-17 19:38:17.318341233 +0200
309
@@ -22,12 +22,17 @@
310
 #ifndef Fl_Window_H
311
 #define Fl_Window_H
312
 
313
+#ifdef WIN32
314
+#include <windows.h>
315
+#endif
316
+
317
 #include "Fl_Group.H"
318
 
319
 #define FL_WINDOW 0xF0		///< window type id all subclasses have type() >= this
320
 #define FL_DOUBLE_WINDOW 0xF1   ///< double window type id
321
 
322
 class Fl_X;
323
+class Fl_RGB_Image;
324
 
325
 /**
326
   This widget produces an actual window.  This can either be a main
327
@@ -49,7 +54,7 @@
328
 class FL_EXPORT Fl_Window : public Fl_Group {
329
 
330
   static char *default_xclass_;
331
-  // Note: we must use separate statements for each of the following 4 variables,
332
+  // Note: we must use separate statements for each of the following 8 variables,
333
   // with the static attribute, otherwise MS VC++ 2008/2010 complains :-(
334
   // AlbrechtS 04/2012
335
 #if FLTK_ABI_VERSION < 10301
336
@@ -68,20 +73,45 @@
337
   static // when these members are static, ABI compatibility with 1.3.0 is respected
338
 #endif
339
   int no_fullscreen_h;
340
+#if FLTK_ABI_VERSION < 10302
341
+  static // when these members are static, ABI compatibility with 1.3.0 is respected
342
+#endif
343
+  int fullscreen_screen_top;
344
+#if FLTK_ABI_VERSION < 10302
345
+  static // when these members are static, ABI compatibility with 1.3.0 is respected
346
+#endif
347
+  int fullscreen_screen_bottom;
348
+#if FLTK_ABI_VERSION < 10302
349
+  static // when these members are static, ABI compatibility with 1.3.0 is respected
350
+#endif
351
+  int fullscreen_screen_left;
352
+#if FLTK_ABI_VERSION < 10302
353
+  static // when these members are static, ABI compatibility with 1.3.0 is respected
354
+#endif
355
+  int fullscreen_screen_right;
356
 
357
   friend class Fl_X;
358
   Fl_X *i; // points at the system-specific stuff
359
 
360
+  struct icon_data {
361
+    const void *legacy_icon;
362
+    Fl_RGB_Image **icons;
363
+    int count;
364
+#ifdef WIN32
365
+    HICON big_icon;
366
+    HICON small_icon;
367
+#endif
368
+  };
369
+
370
   const char* iconlabel_;
371
   char* xclass_;
372
-  const void* icon_;
373
+  struct icon_data *icon_;
374
   // size_range stuff:
375
   int minw, minh, maxw, maxh;
376
   int dw, dh, aspect;
377
   uchar size_range_set;
378
   // cursor stuff
379
   Fl_Cursor cursor_default;
380
-  Fl_Color cursor_fg, cursor_bg;
381
   void size_range_();
382
   void _Fl_Window(); // constructor innards
383
   void fullscreen_x(); // platform-specific part of sending a window to full screen
384
@@ -121,6 +151,8 @@
385
   */
386
   int force_position() const { return ((flags() & FORCE_POSITION)?1:0); }
387
 
388
+  void free_icons();
389
+
390
 public:
391
 
392
   /**
393
@@ -350,6 +382,18 @@
394
   static const char *default_xclass();
395
   const char* xclass() const;
396
   void xclass(const char* c);
397
+
398
+  static void default_icon(const Fl_RGB_Image*);
399
+  static void default_icons(const Fl_RGB_Image*[], int);
400
+  void icon(const Fl_RGB_Image*);
401
+  void icons(const Fl_RGB_Image*[], int);
402
+
403
+#ifdef WIN32
404
+  static void default_icons(HICON big_icon, HICON small_icon);
405
+  void icons(HICON big_icon, HICON small_icon);
406
+#endif
407
+
408
+  /* for legacy compatibility */
409
   const void* icon() const;
410
   void icon(const void * ic);
411
 
412
@@ -402,13 +446,15 @@
413
   */
414
   void show(int argc, char **argv);
415
   /**
416
-    Makes the window completely fill the screen, without any window
417
-    manager border visible.  You must use fullscreen_off() to undo
418
-    this. 
419
+    Makes the window completely fill one or more screens, without any
420
+    window manager border visible.  You must use fullscreen_off() to
421
+    undo this. 
422
 
423
     \note On some platforms, this can result in the keyboard being
424
     grabbed. The window may also be recreated, meaning hide() and
425
     show() will be called.
426
+
427
+    \see void Fl_Window::fullscreen_screens()
428
   */
429
   void fullscreen();
430
   /**
431
@@ -425,6 +471,17 @@
432
   */
433
   unsigned int fullscreen_active() const { return flags() & FULLSCREEN; }
434
   /**
435
+    Sets which screens should be used when this window is in fullscreen
436
+    mode. The window will be resized to the top of the screen with index
437
+    \p top, the bottom of the screen with index \p bottom, etc. 
438
+
439
+    If this method is never called, or if any argument is < 0, then the
440
+    window will be resized to fill the screen it is currently on.
441
+
442
+    \see void Fl_Window::fullscreen()
443
+    */
444
+  void fullscreen_screens(int top, int bottom, int left, int right);
445
+  /**
446
     Iconifies the window.  If you call this when shown() is false
447
     it will show() it as an icon.  If the window is already
448
     iconified this does nothing.
449
@@ -466,14 +523,17 @@
450
     is different.
451
 
452
     The type Fl_Cursor is an enumeration defined in <FL/Enumerations.H>.
453
-    (Under X you can get any XC_cursor value by passing 
454
-    Fl_Cursor((XC_foo/2)+1)).  The colors only work on X, they are
455
-    not implemented on WIN32.
456
 
457
-    For back compatibility only.
458
+    \see cursor(const Fl_RGB_Image*, int, int), default_cursor()
459
   */
460
-  void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); // platform dependent
461
-  void default_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE);
462
+  void cursor(Fl_Cursor);
463
+  void cursor(const Fl_RGB_Image*, int, int);
464
+  void default_cursor(Fl_Cursor);
465
+
466
+  /* for legacy compatibility */
467
+  void cursor(Fl_Cursor c, Fl_Color, Fl_Color=FL_WHITE);
468
+  void default_cursor(Fl_Cursor c, Fl_Color, Fl_Color=FL_WHITE);
469
+
470
   static void default_callback(Fl_Window*, void* v);
471
   
472
   /** Returns the window width including any frame added by the window manager.
473
diff -Nur FL/mac.H FL/mac.H
474
--- FL/mac.H	2012-11-13 15:45:42.000000000 +0100
475
+++ FL/mac.H	2013-07-17 19:38:01.694342066 +0200
476
@@ -120,7 +120,11 @@
477
   void collapse(void);
478
   WindowRef window_ref(void);
479
   void set_key_window(void);
480
-  void set_cursor(Fl_Cursor);
481
+  // OS X doesn't have per window icons
482
+  static void set_default_icons(const Fl_RGB_Image*[], int) {};
483
+  void set_icons() {};
484
+  int set_cursor(Fl_Cursor);
485
+  int set_cursor(const Fl_RGB_Image*, int, int);
486
   static CGImageRef CGImage_from_window_rect(Fl_Window *win, int x, int y, int w, int h);
487
   static unsigned char *bitmap_from_window_rect(Fl_Window *win, int x, int y, int w, int h, int *bytesPerPixel);
488
   static Fl_Region intersect_region_and_rect(Fl_Region current, int x,int y,int w, int h);
489
diff -Nur FL/win32.H FL/win32.H
490
--- FL/win32.H	2012-03-12 12:55:50.000000000 +0100
491
+++ FL/win32.H	2013-07-17 19:38:17.318341233 +0200
492
@@ -73,16 +73,23 @@
493
   int wait_for_expose;
494
   HDC private_dc; // used for OpenGL
495
   HCURSOR cursor;
496
+  int custom_cursor;
497
   HDC saved_hdc;  // saves the handle of the DC currently loaded
498
   // static variables, static functions and member functions
499
   static Fl_X* first;
500
   static Fl_X* i(const Fl_Window* w) {return w->i;}
501
   static int fake_X_wm(const Fl_Window* w,int &X, int &Y,
502
 		                 int &bt,int &bx,int &by);
503
+  void make_fullscreen(int X, int Y, int W, int H);
504
   void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
505
   void flush() {w->flush();}
506
   void set_minmax(LPMINMAXINFO minmax);
507
   void mapraise();
508
+  static void set_default_icons(const Fl_RGB_Image*[], int);
509
+  static void set_default_icons(HICON, HICON);
510
+  void set_icons();
511
+  int set_cursor(Fl_Cursor);
512
+  int set_cursor(const Fl_RGB_Image*, int, int);
513
   static Fl_X* make(Fl_Window*);
514
 };
515
 extern FL_EXPORT HCURSOR fl_default_cursor;
516
diff -Nur FL/x.H FL/x.H
517
--- FL/x.H	2012-03-23 17:47:53.000000000 +0100
518
+++ FL/x.H	2013-07-17 19:38:01.695342062 +0200
519
@@ -154,6 +154,10 @@
520
   static Fl_X* i(const Fl_Window* wi) {return wi->i;}
521
   void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
522
   void sendxjunk();
523
+  static void set_default_icons(const Fl_RGB_Image*[], int);
524
+  void set_icons();
525
+  int set_cursor(Fl_Cursor);
526
+  int set_cursor(const Fl_RGB_Image*, int, int);
527
   static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, Colormap=fl_colormap);
528
   static Fl_X* set_xid(Fl_Window*, Window);
529
   // kludges to get around protection:
530
diff -Nur src/CMakeLists.txt src/CMakeLists.txt
531
--- src/CMakeLists.txt	2011-01-12 10:24:03.000000000 +0100
532
+++ src/CMakeLists.txt	2013-07-17 19:37:45.788342890 +0200
533
@@ -239,6 +239,14 @@
534
    target_link_libraries(fltk ${X11_Xinerama_LIB})
535
 endif(HAVE_XINERAMA)
536
 
537
+if(HAVE_XFIXES)
538
+   target_link_libraries(fltk ${X11_Xfixes_LIB})
539
+endif(HAVE_XFIXES)
540
+
541
+if(HAVE_XCURSOR)
542
+   target_link_libraries(fltk ${X11_Xcursor_LIB})
543
+endif(HAVE_XCURSOR)
544
+
545
 if(USE_XFT)
546
    target_link_libraries(fltk ${X11_Xft_LIB})
547
 endif(USE_XFT)
548
diff -Nur src/Fl_cocoa.mm src/Fl_cocoa.mm
549
--- src/Fl_cocoa.mm	2012-11-30 19:20:36.000000000 +0100
550
+++ src/Fl_cocoa.mm	2013-07-17 19:38:17.320341239 +0200
551
@@ -97,7 +97,6 @@
552
 CGContextRef fl_gc = 0;
553
 void *fl_system_menu;                   // this is really a NSMenu*
554
 Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0;
555
-void *fl_default_cursor;		// this is really a NSCursor*
556
 void *fl_capture = 0;			// (NSWindow*) we need this to compensate for a missing(?) mouse capture
557
 bool fl_show_iconic;                    // true if called from iconize() - shows the next created window in collapsed state
558
 //int fl_disable_transient_for;           // secret method of removing TRANSIENT_FOR
559
@@ -663,12 +662,9 @@
560
     return NO;	// prevent the caption to be redrawn as active on click
561
 		//  when another modal window is currently the key win
562
 
563
-  return !(w->tooltip_window() || w->menu_window());
564
+  return !w->tooltip_window();
565
 }
566
 
567
-// TODO see if we really need a canBecomeMainWindow ...
568
-#if 0
569
-
570
 - (BOOL)canBecomeMainWindow
571
 {
572
   if (Fl::modal_ && (Fl::modal_ != w))
573
@@ -677,7 +673,6 @@
574
 
575
   return !(w->tooltip_window() || w->menu_window());
576
 }
577
-#endif
578
 
579
 @end
580
 
581
@@ -1333,8 +1328,6 @@
582
 					  dequeue:YES];
583
     while (ign_event);
584
     
585
-    fl_default_cursor = [NSCursor arrowCursor];
586
-
587
     // bring the application into foreground without a 'CARB' resource
588
     Boolean same_psn;
589
     ProcessSerialNumber cur_psn, front_psn;
590
@@ -1639,6 +1632,7 @@
591
 - (void)drawRect:(NSRect)rect;
592
 - (BOOL)acceptsFirstResponder;
593
 - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
594
+- (void)resetCursorRects;
595
 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
596
 - (void)mouseUp:(NSEvent *)theEvent;
597
 - (void)rightMouseUp:(NSEvent *)theEvent;
598
@@ -1696,6 +1690,16 @@
599
   Fl_Window *first = Fl::first_window();
600
   return (first == w || !first->modal());
601
 }
602
+- (void)resetCursorRects {
603
+  Fl_Window *w = [(FLWindow*)[self window] getFl_Window];
604
+  Fl_X *i = Fl_X::i(w);
605
+  // We have to have at least one cursor rect for invalidateCursorRectsForView
606
+  // to work, hence the "else" clause.
607
+  if (i->cursor)
608
+    [self addCursorRect:[self visibleRect] cursor:(NSCursor*)i->cursor];
609
+  else
610
+    [self addCursorRect:[self visibleRect] cursor:[NSCursor arrowCursor]];
611
+}
612
 - (void)mouseUp:(NSEvent *)theEvent {
613
   cocoaMouseHandler(theEvent);
614
 }
615
@@ -2069,7 +2073,7 @@
616
     x->other_xid = 0;
617
     x->region = 0;
618
     x->subRegion = 0;
619
-    x->cursor = fl_default_cursor;
620
+    x->cursor = NULL;
621
     x->gc = 0;			// stay 0 for Quickdraw; fill with CGContext for Quartz
622
     Fl_Window *win = w->window();
623
     Fl_X *xo = Fl_X::i(win);
624
@@ -2165,16 +2169,39 @@
625
     x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows
626
     x->region = 0;
627
     x->subRegion = 0;
628
-    x->cursor = fl_default_cursor;
629
+    x->cursor = NULL;
630
     x->xidChildren = 0;
631
     x->xidNext = 0;
632
     x->gc = 0;
633
 	  
634
     NSRect crect;
635
     if (w->fullscreen_active()) {
636
-      int sx, sy, sw, sh;
637
-      Fl::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h());
638
-      w->resize(sx, sy, sw, sh);
639
+      int top, bottom, left, right;
640
+      int sx, sy, sw, sh, X, Y, W, H;
641
+
642
+      top = w->fullscreen_screen_top;
643
+      bottom = w->fullscreen_screen_bottom;
644
+      left = w->fullscreen_screen_left;
645
+      right = w->fullscreen_screen_right;
646
+
647
+      if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
648
+        top = Fl::screen_num(w->x(), w->y(), w->w(), w->h());
649
+        bottom = top;
650
+        left = top;
651
+        right = top;
652
+      }
653
+
654
+      Fl::screen_xywh(sx, sy, sw, sh, top);
655
+      Y = sy;
656
+      Fl::screen_xywh(sx, sy, sw, sh, bottom);
657
+      H = sy + sh - Y;
658
+      Fl::screen_xywh(sx, sy, sw, sh, left);
659
+      X = sx;
660
+      Fl::screen_xywh(sx, sy, sw, sh, right);
661
+      W = sx + sw - X;
662
+
663
+      w->resize(X, Y, W, H);
664
+
665
       winstyle = NSBorderlessWindowMask;
666
       winlevel = NSStatusWindowLevel;
667
     }
668
@@ -2692,6 +2719,10 @@
669
     Fl_X::relink(w, w->window() );
670
     w->redraw();
671
   }
672
+  if (cursor) {
673
+    [(NSCursor*)cursor release];
674
+    cursor = NULL;
675
+  }
676
 }
677
 
678
 void Fl_X::unmap() {
679
@@ -2796,68 +2827,106 @@
680
   return [image autorelease];
681
 }
682
 
683
-static NSCursor *PrepareCursor(NSCursor *cursor, CGContextRef (*f)() )
684
+int Fl_X::set_cursor(Fl_Cursor c)
685
 {
686
-  if (cursor == nil) {
687
-    CGContextRef c = f();
688
-    NSImage *image = CGBitmapContextToNSImage(c);
689
-    fl_delete_offscreen( (Fl_Offscreen)c ); 
690
-    NSPoint pt = {[image size].width/2, [image size].height/2};
691
-    cursor = [[NSCursor alloc] initWithImage:image hotSpot:pt];
692
+  if (cursor) {
693
+    [(NSCursor*)cursor release];
694
+    cursor = NULL;
695
   }
696
-  return cursor;
697
-}
698
 
699
-void Fl_X::set_cursor(Fl_Cursor c)
700
-{
701
-  NSCursor *icrsr;
702
   switch (c) {
703
-    case FL_CURSOR_CROSS:  icrsr = [NSCursor crosshairCursor]; break;
704
-    case FL_CURSOR_WAIT:
705
-      static NSCursor *watch = nil;
706
-      watch = PrepareCursor(watch,  &Fl_X::watch_cursor_image);
707
-      icrsr = watch;
708
-      break;
709
-    case FL_CURSOR_INSERT: icrsr = [NSCursor IBeamCursor]; break;
710
-    case FL_CURSOR_N:      icrsr = [NSCursor resizeUpCursor]; break;
711
-    case FL_CURSOR_S:      icrsr = [NSCursor resizeDownCursor]; break;
712
-    case FL_CURSOR_NS:     icrsr = [NSCursor resizeUpDownCursor]; break;
713
-    case FL_CURSOR_HELP:   
714
-      static NSCursor *help = nil;
715
-      help = PrepareCursor(help,  &Fl_X::help_cursor_image);
716
-      icrsr = help;
717
-      break;
718
-    case FL_CURSOR_HAND:   icrsr = [NSCursor pointingHandCursor]; break;
719
-    case FL_CURSOR_MOVE:   icrsr = [NSCursor openHandCursor]; break;
720
-    case FL_CURSOR_NE:
721
-    case FL_CURSOR_SW:
722
-    case FL_CURSOR_NESW:   
723
-      static NSCursor *nesw = nil;
724
-      nesw = PrepareCursor(nesw,  &Fl_X::nesw_cursor_image);
725
-      icrsr = nesw;
726
-      break;
727
-    case FL_CURSOR_E:      icrsr = [NSCursor resizeRightCursor]; break;
728
-    case FL_CURSOR_W:      icrsr = [NSCursor resizeLeftCursor]; break;
729
-    case FL_CURSOR_WE:     icrsr = [NSCursor resizeLeftRightCursor]; break;
730
-    case FL_CURSOR_SE:
731
-    case FL_CURSOR_NW:
732
-    case FL_CURSOR_NWSE:   
733
-      static NSCursor *nwse = nil;
734
-      nwse = PrepareCursor(nwse,  &Fl_X::nwse_cursor_image);
735
-      icrsr = nwse;
736
-      break;
737
-    case FL_CURSOR_NONE:   
738
-      static NSCursor *none = nil;
739
-      none = PrepareCursor(none,  &Fl_X::none_cursor_image);
740
-      icrsr = none; 
741
-      break;
742
-    case FL_CURSOR_ARROW:
743
-    case FL_CURSOR_DEFAULT:
744
-    default:			   icrsr = [NSCursor arrowCursor];
745
-      break;
746
+  case FL_CURSOR_ARROW:   cursor = [NSCursor arrowCursor]; break;
747
+  case FL_CURSOR_CROSS:   cursor = [NSCursor crosshairCursor]; break;
748
+  case FL_CURSOR_INSERT:  cursor = [NSCursor IBeamCursor]; break;
749
+  case FL_CURSOR_HAND:    cursor = [NSCursor pointingHandCursor]; break;
750
+  case FL_CURSOR_MOVE:    cursor = [NSCursor openHandCursor]; break;
751
+  case FL_CURSOR_NS:      cursor = [NSCursor resizeUpDownCursor]; break;
752
+  case FL_CURSOR_WE:      cursor = [NSCursor resizeLeftRightCursor]; break;
753
+  case FL_CURSOR_N:       cursor = [NSCursor resizeUpCursor]; break;
754
+  case FL_CURSOR_E:       cursor = [NSCursor resizeRightCursor]; break;
755
+  case FL_CURSOR_W:       cursor = [NSCursor resizeLeftCursor]; break;
756
+  case FL_CURSOR_S:       cursor = [NSCursor resizeDownCursor]; break;
757
+  default:
758
+    return 0;
759
+  }
760
+
761
+  [(NSCursor*)cursor retain];
762
+
763
+  [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]];
764
+
765
+  return 1;
766
+}
767
+
768
+int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
769
+  if (cursor) {
770
+    [(NSCursor*)cursor release];
771
+    cursor = NULL;
772
+  }
773
+
774
+  if ((hotx < 0) || (hotx >= image->w()))
775
+    return 0;
776
+  if ((hoty < 0) || (hoty >= image->h()))
777
+    return 0;
778
+
779
+  // OS X >= 10.6 can create a NSImage from a CGImage, but we need to
780
+  // support older versions, hence this pesky handling.
781
+
782
+  NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
783
+                              initWithBitmapDataPlanes:NULL
784
+                              pixelsWide:image->w()
785
+                              pixelsHigh:image->h()
786
+                              bitsPerSample:8
787
+                              samplesPerPixel:image->d()
788
+                              hasAlpha:!(image->d() & 1)
789
+                              isPlanar:NO
790
+                              colorSpaceName:(image->d()<=2) ? NSDeviceWhiteColorSpace : NSDeviceRGBColorSpace
791
+                              bytesPerRow:(image->w() * image->d())
792
+                              bitsPerPixel:(image->d()*8)];
793
+
794
+  // Alpha needs to be premultiplied for this format
795
+
796
+  const uchar *i = (const uchar*)*image->data();
797
+  unsigned char *o = [bitmap bitmapData];
798
+  for (int y = 0;y < image->h();y++) {
799
+    if (image->d() & 1) {
800
+      for (int x = 0;x < image->w();x++) {
801
+        unsigned int alpha;
802
+        if (image->d() == 4) {
803
+          alpha = i[3];
804
+          *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
805
+          *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
806
+        }
807
+
808
+        alpha = i[1];
809
+        *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
810
+        *o++ = alpha;
811
+        i++;
812
+  }
813
+    } else {
814
+      // No alpha, so we can just copy everything directly.
815
+      int len = image->w() * image->d();
816
+      memcpy(o, i, len);
817
+      o += len;
818
+      i += len;
819
+    }
820
+    i += image->ld();
821
   }
822
-  [icrsr set];
823
-  cursor = icrsr;
824
+
825
+  NSImage *nsimage = [[NSImage alloc]
826
+                      initWithSize:NSMakeSize(image->w(), image->h())];
827
+
828
+  [nsimage addRepresentation:bitmap];
829
+
830
+  cursor = [[NSCursor alloc]
831
+            initWithImage:nsimage
832
+            hotSpot:NSMakePoint(hotx, hoty)];
833
+
834
+  [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]];
835
+
836
+  [bitmap release];
837
+  [nsimage release];
838
+
839
+  return 1;
840
 }
841
 
842
 @interface FLaboutItemTarget : NSObject 
843
diff -Nur src/fl_cursor.cxx src/fl_cursor.cxx
844
--- src/fl_cursor.cxx	2012-03-12 12:55:50.000000000 +0100
845
+++ src/fl_cursor.cxx	2013-07-17 19:37:45.791342890 +0200
846
@@ -24,297 +24,165 @@
847
 
848
 #include <FL/Fl.H>
849
 #include <FL/Fl_Window.H>
850
+#include <FL/Fl_Pixmap.H>
851
+#include <FL/Fl_RGB_Image.H>
852
 #include <FL/x.H>
853
-#if !defined(WIN32) && !defined(__APPLE__)
854
-#  include <X11/cursorfont.h>
855
-#endif
856
 #include <FL/fl_draw.H>
857
 
858
+#include "fl_cursor_wait.xpm"
859
+#include "fl_cursor_help.xpm"
860
+#include "fl_cursor_nwse.xpm"
861
+#include "fl_cursor_nesw.xpm"
862
+#include "fl_cursor_none.xpm"
863
+
864
 /**
865
   Sets the cursor for the current window to the specified shape and colors.
866
   The cursors are defined in the <FL/Enumerations.H> header file. 
867
   */
868
+void fl_cursor(Fl_Cursor c) {
869
+  if (Fl::first_window()) Fl::first_window()->cursor(c);
870
+}
871
+
872
+/* For back compatibility only. */
873
 void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
874
-  if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg);
875
+  fl_cursor(c);
876
 }
877
+
878
+
879
 /** 
880
-    Sets the default window cursor as well as its color.
881
+    Sets the default window cursor. This is the cursor that will be used
882
+    after the mouse pointer leaves a widget with a custom cursor set.
883
 
884
-    For back compatibility only.
885
+    \see cursor(const Fl_RGB_Image*, int, int), default_cursor()
886
 */
887
-void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
888
-//  if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW;
889
-
890
+void Fl_Window::default_cursor(Fl_Cursor c) {
891
   cursor_default = c;
892
-  cursor_fg      = fg;
893
-  cursor_bg      = bg;
894
+  cursor(c);
895
+}
896
+
897
+
898
+void fallback_cursor(Fl_Window *w, Fl_Cursor c) {
899
+  const char **xpm;
900
+  int hotx, hoty;
901
+
902
+  // The standard arrow is our final fallback, so something is broken
903
+  // if we get called back here with that as an argument.
904
+  if (c == FL_CURSOR_ARROW)
905
+    return;
906
+
907
+  switch (c) {
908
+  case FL_CURSOR_WAIT:
909
+    xpm = (const char**)fl_cursor_wait_xpm;
910
+    hotx = 8;
911
+    hoty = 15;
912
+    break;
913
+  case FL_CURSOR_HELP:
914
+    xpm = (const char**)fl_cursor_help_xpm;
915
+    hotx = 1;
916
+    hoty = 3;
917
+    break;
918
+  case FL_CURSOR_NWSE:
919
+    xpm = (const char**)fl_cursor_nwse_xpm;
920
+    hotx = 7;
921
+    hoty = 7;
922
+    break;
923
+  case FL_CURSOR_NESW:
924
+    xpm = (const char**)fl_cursor_nesw_xpm;
925
+    hotx = 7;
926
+    hoty = 7;
927
+    break;
928
+  case FL_CURSOR_NONE:
929
+    xpm = (const char**)fl_cursor_none_xpm;
930
+    hotx = 0;
931
+    hoty = 0;
932
+    break;
933
+  default:
934
+    w->cursor(FL_CURSOR_ARROW);
935
+    return;
936
+  }
937
 
938
-  cursor(c, fg, bg);
939
+  Fl_Pixmap pxm(xpm);
940
+  Fl_RGB_Image image(&pxm);
941
+
942
+  w->cursor(&image, hotx, hoty);
943
 }
944
 
945
-#ifdef WIN32
946
 
947
-#  ifndef IDC_HAND
948
-#    define IDC_HAND	MAKEINTRESOURCE(32649)
949
-#  endif // !IDC_HAND
950
+void Fl_Window::cursor(Fl_Cursor c) {
951
+  int ret;
952
 
953
-void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) {
954
-  if (!shown()) return;
955
   // the cursor must be set for the top level window, not for subwindows
956
   Fl_Window *w = window(), *toplevel = this;
957
-  while (w) { toplevel = w; w = w->window(); }
958
-  if (toplevel != this) { toplevel->cursor(c, c1, c2); return; }
959
-  // now set the actual cursor
960
-  if (c == FL_CURSOR_DEFAULT) {
961
-    c = cursor_default;
962
-  }
963
-  if (c > FL_CURSOR_NESW) {
964
-    i->cursor = 0;
965
-  } else if (c == FL_CURSOR_DEFAULT) {
966
-    i->cursor = fl_default_cursor;
967
-  } else {
968
-    LPSTR n;
969
-    switch (c) {
970
-    case FL_CURSOR_ARROW:	n = IDC_ARROW; break;
971
-    case FL_CURSOR_CROSS:	n = IDC_CROSS; break;
972
-    case FL_CURSOR_WAIT:	n = IDC_WAIT; break;
973
-    case FL_CURSOR_INSERT:	n = IDC_IBEAM; break;
974
-    case FL_CURSOR_HELP:	n = IDC_HELP; break;
975
-    case FL_CURSOR_HAND: {
976
-          OSVERSIONINFO osvi;
977
-
978
-          // Get the OS version: Windows 98 and 2000 have a standard
979
-	  // hand cursor.
980
-          memset(&osvi, 0, sizeof(OSVERSIONINFO));
981
-          osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
982
-          GetVersionEx(&osvi);
983
-
984
-          if (osvi.dwMajorVersion > 4 ||
985
-  	      (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0 &&
986
-  	       osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)) n = IDC_HAND;
987
-          else n = IDC_UPARROW;
988
-	} break;
989
-    case FL_CURSOR_MOVE:	n = IDC_SIZEALL; break;
990
-    case FL_CURSOR_N:
991
-    case FL_CURSOR_S:
992
-    case FL_CURSOR_NS:		n = IDC_SIZENS; break;
993
-    case FL_CURSOR_NE:
994
-    case FL_CURSOR_SW:
995
-    case FL_CURSOR_NESW:	n = IDC_SIZENESW; break;
996
-    case FL_CURSOR_E:
997
-    case FL_CURSOR_W:
998
-    case FL_CURSOR_WE:		n = IDC_SIZEWE; break;
999
-    case FL_CURSOR_SE:
1000
-    case FL_CURSOR_NW:
1001
-    case FL_CURSOR_NWSE:	n = IDC_SIZENWSE; break;
1002
-    default:			n = IDC_NO; break;
1003
-    }
1004
-    i->cursor = LoadCursor(NULL, n);
1005
+
1006
+  while (w) {
1007
+    toplevel = w;
1008
+    w = w->window();
1009
   }
1010
-  SetCursor(i->cursor);
1011
-}
1012
 
1013
-#elif defined(__APPLE__)
1014
+  if (toplevel != this) {
1015
+    toplevel->cursor(c);
1016
+    return;
1017
+  }
1018
 
1019
-#ifdef __BIG_ENDIAN__
1020
-# define E(x) x
1021
-#elif defined __LITTLE_ENDIAN__
1022
-// Don't worry. This will be resolved at compile time
1023
-# define E(x) (x>>8)|((x<<8)&0xff00)
1024
-#else
1025
-# error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined"
1026
-#endif
1027
-
1028
-CGContextRef Fl_X::help_cursor_image(void)
1029
-{
1030
-  int w = 20, h = 20;
1031
-  Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h);
1032
-  fl_begin_offscreen(off);
1033
-  CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
1034
-  fl_rectf(0,0,w,h);
1035
-  fl_color(FL_BLACK);
1036
-  fl_font(FL_COURIER_BOLD, 20);
1037
-  fl_draw("?", 1, h-1);
1038
-  fl_end_offscreen();
1039
-  return (CGContextRef)off;
1040
-}
1041
+  if (c == FL_CURSOR_DEFAULT)
1042
+    c = cursor_default;
1043
 
1044
-CGContextRef Fl_X::none_cursor_image(void)
1045
-{
1046
-  int w = 20, h = 20;
1047
-  Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h);
1048
-  fl_begin_offscreen(off);
1049
-  CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
1050
-  fl_rectf(0,0,w,h);
1051
-  fl_end_offscreen();
1052
-  return (CGContextRef)off;
1053
-}
1054
+  if (!i)
1055
+    return;
1056
 
1057
-CGContextRef Fl_X::watch_cursor_image(void)
1058
-{
1059
-  int w, h, r = 5;
1060
-  w = 2*r+6;
1061
-  h = 4*r;
1062
-  Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h);
1063
-  fl_begin_offscreen(off);
1064
-  CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
1065
-  fl_rectf(0,0,w,h);
1066
-  CGContextTranslateCTM( (CGContextRef)off, w/2, h/2);
1067
-  fl_color(FL_WHITE);
1068
-  fl_circle(0, 0, r+1);
1069
-  fl_color(FL_BLACK);
1070
-  fl_rectf(int(-r*0.7), int(-r*1.7), int(1.4*r), int(3.4*r));
1071
-  fl_rectf(r-1, -1, 3, 3);
1072
-  fl_color(FL_WHITE);
1073
-  fl_pie(-r, -r, 2*r, 2*r, 0, 360);
1074
-  fl_color(FL_BLACK);
1075
-  fl_circle(0,0,r);
1076
-  fl_xyline(0, 0, int(-r*.7));
1077
-  fl_xyline(0, 0, 0, int(-r*.7));
1078
-  fl_end_offscreen();
1079
-  return (CGContextRef)off;
1080
-}
1081
+  ret = i->set_cursor(c);
1082
+  if (ret)
1083
+    return;
1084
 
1085
-CGContextRef Fl_X::nesw_cursor_image(void)
1086
-{
1087
-  int c = 7, r = 2*c;
1088
-  int w = r, h = r;
1089
-  Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h);
1090
-  fl_begin_offscreen(off);
1091
-  CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
1092
-  fl_rectf(0,0,w,h);
1093
-  CGContextTranslateCTM( (CGContextRef)off, 0, h);
1094
-  CGContextScaleCTM( (CGContextRef)off, 1, -1);
1095
-  fl_color(FL_BLACK);
1096
-  fl_polygon(0, 0, c, 0, 0, c);
1097
-  fl_polygon(r, r, r, r-c, r-c, r);
1098
-  fl_line_style(FL_SOLID, 2, 0);
1099
-  fl_line(0,1, r,r+1);
1100
-  fl_line_style(FL_SOLID, 0, 0);
1101
-  fl_end_offscreen();
1102
-  return (CGContextRef)off;
1103
+  fallback_cursor(this, c);
1104
 }
1105
 
1106
-CGContextRef Fl_X::nwse_cursor_image(void)
1107
-{
1108
-  int c = 7, r = 2*c;
1109
-  int w = r, h = r;
1110
-  Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h);
1111
-  fl_begin_offscreen(off);
1112
-  CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
1113
-  fl_rectf(0,0,w,h);
1114
-  CGContextTranslateCTM( (CGContextRef)off, 0, h);
1115
-  CGContextScaleCTM( (CGContextRef)off, 1, -1);
1116
-  fl_color(FL_BLACK);
1117
-  fl_polygon(r-1, 0, r-1, c, r-1-c, 0);
1118
-  fl_polygon(-1, r, c-1, r, -1, r-c);
1119
-  fl_line_style(FL_SOLID, 2, 0);
1120
-  fl_line(r-1,1, -1,r+1);
1121
-  fl_line_style(FL_SOLID, 0, 0);
1122
-  fl_end_offscreen();
1123
-  return (CGContextRef)off;
1124
-}
1125
-
1126
-void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
1127
-  if (c == FL_CURSOR_DEFAULT) {
1128
-    c = cursor_default;
1129
-  }
1130
-  if (i) i->set_cursor(c);
1131
-}
1132
+/**
1133
+  Changes the cursor for this window.  This always calls the system, if
1134
+  you are changing the cursor a lot you may want to keep track of how
1135
+  you set it in a static variable and call this only if the new cursor
1136
+  is different.
1137
 
1138
-#else
1139
+  The default cursor will be used if the provided image cannot be used
1140
+  as a cursor.
1141
 
1142
-// I like the MSWindows resize cursors, so I duplicate them here:
1143
+  \see cursor(Fl_Cursor), default_cursor()
1144
+*/
1145
+void Fl_Window::cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
1146
+  int ret;
1147
 
1148
-#define CURSORSIZE 16
1149
-#define HOTXY 7
1150
-static struct TableEntry {
1151
-  uchar bits[CURSORSIZE*CURSORSIZE/8];
1152
-  uchar mask[CURSORSIZE*CURSORSIZE/8];
1153
-  Cursor cursor;
1154
-} table[] = {
1155
-  {{	// FL_CURSOR_NS
1156
-   0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
1157
-   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
1158
-   0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
1159
-   {
1160
-   0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
1161
-   0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
1162
-   0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
1163
-  {{	// FL_CURSOR_EW
1164
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
1165
-   0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
1166
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1167
-   {
1168
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
1169
-   0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
1170
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
1171
-  {{	// FL_CURSOR_NWSE
1172
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
1173
-   0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
1174
-   0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1175
-   {
1176
-   0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
1177
-   0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
1178
-   0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
1179
-  {{	// FL_CURSOR_NESW
1180
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
1181
-   0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
1182
-   0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1183
-   {
1184
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
1185
-   0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
1186
-   0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
1187
-  {{0}, {0}} // FL_CURSOR_NONE & unknown
1188
-};
1189
+  // the cursor must be set for the top level window, not for subwindows
1190
+  Fl_Window *w = window(), *toplevel = this;
1191
 
1192
-void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
1193
-  if (!shown()) return;
1194
-  Cursor xc;
1195
-  int deleteit = 0;
1196
-  if (c == FL_CURSOR_DEFAULT) {
1197
-    c  = cursor_default;
1198
-    fg = cursor_fg;
1199
-    bg = cursor_bg;
1200
+  while (w) {
1201
+    toplevel = w;
1202
+    w = w->window();
1203
   }
1204
 
1205
-  if (!c) {
1206
-    xc = None;
1207
-  } else {
1208
-    if (c >= FL_CURSOR_NS) {
1209
-      TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
1210
-      if (!(q->cursor)) {
1211
-	XColor dummy = { 0 };
1212
-	Pixmap p = XCreateBitmapFromData(fl_display,
1213
-	  RootWindow(fl_display, fl_screen), (const char*)(q->bits),
1214
-	  CURSORSIZE, CURSORSIZE);
1215
-	Pixmap m = XCreateBitmapFromData(fl_display,
1216
-	  RootWindow(fl_display, fl_screen), (const char*)(q->mask),
1217
-	  CURSORSIZE, CURSORSIZE);
1218
-	q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy,
1219
-					HOTXY, HOTXY);
1220
-	XFreePixmap(fl_display, m);
1221
-	XFreePixmap(fl_display, p);
1222
-      }
1223
-      xc = q->cursor;
1224
-    } else {
1225
-      xc = XCreateFontCursor(fl_display, (c-1)*2);
1226
-      deleteit = 1;
1227
-    }
1228
-    XColor fgc;
1229
-    uchar r,g,b;
1230
-    Fl::get_color(fg,r,g,b);
1231
-    fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8;
1232
-    XColor bgc;
1233
-    Fl::get_color(bg,r,g,b);
1234
-    bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8;
1235
-    XRecolorCursor(fl_display, xc, &fgc, &bgc);
1236
+  if (toplevel != this) {
1237
+    toplevel->cursor(image, hotx, hoty);
1238
+    return;
1239
   }
1240
-  XDefineCursor(fl_display, fl_xid(this), xc);
1241
-  if (deleteit) XFreeCursor(fl_display, xc);
1242
+
1243
+  if (!i)
1244
+    return;
1245
+
1246
+  ret = i->set_cursor(image, hotx, hoty);
1247
+  if (ret)
1248
+    return;
1249
+
1250
+  cursor(FL_CURSOR_DEFAULT);
1251
 }
1252
 
1253
-#endif
1254
+/* For back compatibility only. */
1255
+void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
1256
+  cursor(c);
1257
+};
1258
+
1259
+void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
1260
+  default_cursor(c);
1261
+};
1262
+
1263
 
1264
 //
1265
 // End of "$Id: fl_cursor.cxx 9278 2012-03-12 11:55:50Z manolo $".
1266
diff -Nur src/fl_cursor_help.xpm src/fl_cursor_help.xpm
1267
--- src/fl_cursor_help.xpm	1970-01-01 01:00:00.000000000 +0100
1268
+++ src/fl_cursor_help.xpm	2013-07-17 19:37:45.792342890 +0200
1269
@@ -0,0 +1,95 @@
1270
+/* XPM */
1271
+static const char * fl_cursor_help_xpm[] = {
1272
+"16 27 65 1",
1273
+" 	c None",
1274
+".	c #FFFFFF",
1275
+"+	c #E2E2E2",
1276
+"@	c #1C1C1C",
1277
+"#	c #E7E7E7",
1278
+"$	c #000000",
1279
+"%	c #212121",
1280
+"&	c #EAEAEA",
1281
+"*	c #262626",
1282
+"=	c #EDEDED",
1283
+"-	c #2C2C2C",
1284
+";	c #F0F0F0",
1285
+">	c #333333",
1286
+",	c #F1F1F1",
1287
+"'	c #393939",
1288
+")	c #F3F3F3",
1289
+"!	c #404040",
1290
+"~	c #484848",
1291
+"{	c #F4F4F4",
1292
+"]	c #050505",
1293
+"^	c #202020",
1294
+"/	c #707070",
1295
+"(	c #F5F5F5",
1296
+"_	c #040404",
1297
+":	c #E1E1E1",
1298
+"<	c #EEEEEE",
1299
+"[	c #EFEFEF",
1300
+"}	c #FEFEFE",
1301
+"|	c #3D3D3D",
1302
+"1	c #7E7E7E",
1303
+"2	c #696969",
1304
+"3	c #414141",
1305
+"4	c #131313",
1306
+"5	c #080808",
1307
+"6	c #454545",
1308
+"7	c #F2F2F2",
1309
+"8	c #878787",
1310
+"9	c #7D7D7D",
1311
+"0	c #101010",
1312
+"a	c #111111",
1313
+"b	c #FDFDFD",
1314
+"c	c #8A8A8A",
1315
+"d	c #E6E6E6",
1316
+"e	c #7B7B7B",
1317
+"f	c #4C4C4C",
1318
+"g	c #5C5C5C",
1319
+"h	c #9F9F9F",
1320
+"i	c #F9F9F9",
1321
+"j	c #F7F7F7",
1322
+"k	c #B1B1B1",
1323
+"l	c #2E2E2E",
1324
+"m	c #767676",
1325
+"n	c #DCDCDC",
1326
+"o	c #DEDEDE",
1327
+"p	c #C7C7C7",
1328
+"q	c #1B1B1B",
1329
+"r	c #6B6B6B",
1330
+"s	c #575757",
1331
+"t	c #797979",
1332
+"u	c #020202",
1333
+"v	c #010101",
1334
+"w	c #FBFBFB",
1335
+"x	c #D7D7D7",
1336
+"y	c #D8D8D8",
1337
+"z	c #060606",
1338
+"                ",
1339
+".               ",
1340
+".+              ",
1341
+".@#             ",
1342
+".$%&            ",
1343
+".$$*=           ",
1344
+".$$$-;          ",
1345
+".$$$$>,         ",
1346
+".$$$$$')        ",
1347
+".$$$$$$!)       ",
1348
+".$$$$$$$~{      ",
1349
+".$$$$]^^^/(     ",
1350
+".$$$$_:(<<[}    ",
1351
+".$$|1$2<        ",
1352
+".$3,(45[        ",
1353
+".67 78$9,       ",
1354
+".7   {0a( ....  ",
1355
+"b    ,c5[defgh, ",
1356
+"      )ijk_la$m.",
1357
+"         no.p$q.",
1358
+"           .r$s.",
1359
+"          .t$-= ",
1360
+"          7uv+  ",
1361
+"          wxy.  ",
1362
+"          :$z.  ",
1363
+"          :$z.  ",
1364
+"          ....  "};
1365
diff -Nur src/fl_cursor_nesw.xpm src/fl_cursor_nesw.xpm
1366
--- src/fl_cursor_nesw.xpm	1970-01-01 01:00:00.000000000 +0100
1367
+++ src/fl_cursor_nesw.xpm	2013-07-17 19:37:45.792342890 +0200
1368
@@ -0,0 +1,46 @@
1369
+/* XPM */
1370
+static const char * fl_cursor_nesw_xpm[] = {
1371
+"15 15 28 1",
1372
+" 	c None",
1373
+".	c #FFFFFF",
1374
+"+	c #767676",
1375
+"@	c #000000",
1376
+"#	c #4E4E4E",
1377
+"$	c #0C0C0C",
1378
+"%	c #494949",
1379
+"&	c #4D4D4D",
1380
+"*	c #1B1B1B",
1381
+"=	c #515151",
1382
+"-	c #646464",
1383
+";	c #363636",
1384
+">	c #6A6A6A",
1385
+",	c #545454",
1386
+"'	c #585858",
1387
+")	c #242424",
1388
+"!	c #797979",
1389
+"~	c #2E2E2E",
1390
+"{	c #444444",
1391
+"]	c #3B3B3B",
1392
+"^	c #0A0A0A",
1393
+"/	c #595959",
1394
+"(	c #F7F7F7",
1395
+"_	c #080808",
1396
+":	c #6B6B6B",
1397
+"<	c #FDFDFD",
1398
+"[	c #FCFCFC",
1399
+"}	c #FEFEFE",
1400
+"     ..........",
1401
+"      .+@@@@@@.",
1402
+"       .#@@@@@.",
1403
+"        .$@@@@.",
1404
+"       .%@@@@@.",
1405
+".     .&@@@*@@.",
1406
+"..   .=@@@-.;@.",
1407
+".>. .,@@@'. .).",
1408
+".@!.'@@@#.   ..",
1409
+".@@~@@@{.     .",
1410
+".@@@@@].       ",
1411
+".@@@@^.        ",
1412
+".@@@@@/(       ",
1413
+".______:(      ",
1414
+"<[[[[[[[[}     "};
1415
diff -Nur src/fl_cursor_none.xpm src/fl_cursor_none.xpm
1416
--- src/fl_cursor_none.xpm	1970-01-01 01:00:00.000000000 +0100
1417
+++ src/fl_cursor_none.xpm	2013-07-17 19:37:45.793342890 +0200
1418
@@ -0,0 +1,19 @@
1419
+/* XPM */
1420
+static const char * fl_cursor_none_xpm[] = {
1421
+"15 15 1 1",
1422
+" 	c None",
1423
+"               ",
1424
+"               ",
1425
+"               ",
1426
+"               ",
1427
+"               ",
1428
+"               ",
1429
+"               ",
1430
+"               ",
1431
+"               ",
1432
+"               ",
1433
+"               ",
1434
+"               ",
1435
+"               ",
1436
+"               ",
1437
+"               "};
1438
diff -Nur src/fl_cursor_nwse.xpm src/fl_cursor_nwse.xpm
1439
--- src/fl_cursor_nwse.xpm	1970-01-01 01:00:00.000000000 +0100
1440
+++ src/fl_cursor_nwse.xpm	2013-07-17 19:37:45.793342890 +0200
1441
@@ -0,0 +1,46 @@
1442
+/* XPM */
1443
+static const char * fl_cursor_nwse_xpm[] = {
1444
+"15 15 28 1",
1445
+" 	c None",
1446
+".	c #FFFFFF",
1447
+"+	c #000000",
1448
+"@	c #767676",
1449
+"#	c #4E4E4E",
1450
+"$	c #0C0C0C",
1451
+"%	c #494949",
1452
+"&	c #1B1B1B",
1453
+"*	c #4D4D4D",
1454
+"=	c #363636",
1455
+"-	c #646464",
1456
+";	c #515151",
1457
+">	c #242424",
1458
+",	c #585858",
1459
+"'	c #545454",
1460
+")	c #6A6A6A",
1461
+"!	c #797979",
1462
+"~	c #444444",
1463
+"{	c #2E2E2E",
1464
+"]	c #3B3B3B",
1465
+"^	c #0A0A0A",
1466
+"/	c #F7F7F7",
1467
+"(	c #595959",
1468
+"_	c #6B6B6B",
1469
+":	c #080808",
1470
+"<	c #FEFEFE",
1471
+"[	c #FCFCFC",
1472
+"}	c #FDFDFD",
1473
+"..........     ",
1474
+".++++++@.      ",
1475
+".+++++#.       ",
1476
+".++++$.        ",
1477
+".+++++%.       ",
1478
+".++&+++*.     .",
1479
+".+=.-+++;.   ..",
1480
+".>. .,+++'. .).",
1481
+"..   .#+++,.!+.",
1482
+".     .~+++{++.",
1483
+"       .]+++++.",
1484
+"        .^++++.",
1485
+"       /(+++++.",
1486
+"      /_::::::.",
1487
+"     <[[[[[[[[}"};
1488
diff -Nur src/fl_cursor_wait.xpm src/fl_cursor_wait.xpm
1489
--- src/fl_cursor_wait.xpm	1970-01-01 01:00:00.000000000 +0100
1490
+++ src/fl_cursor_wait.xpm	2013-07-17 19:37:45.793342890 +0200
1491
@@ -0,0 +1,72 @@
1492
+/* XPM */
1493
+static const char * fl_cursor_wait_xpm[] = {
1494
+"17 32 37 1",
1495
+" 	c None",
1496
+".	c #FFFFFF",
1497
+"+	c #2E2E2E",
1498
+"@	c #202020",
1499
+"#	c #F1F1F1",
1500
+"$	c #2D2D2D",
1501
+"%	c #000000",
1502
+"&	c #EDEDED",
1503
+"*	c #585858",
1504
+"=	c #575757",
1505
+"-	c #FBFBFB",
1506
+";	c #848484",
1507
+">	c #B8B8B8",
1508
+",	c #E5E5E5",
1509
+"'	c #F7F7F7",
1510
+")	c #181818",
1511
+"!	c #F0F0F0",
1512
+"~	c #616161",
1513
+"{	c #B7B7B7",
1514
+"]	c #F5F5F5",
1515
+"^	c #050505",
1516
+"/	c #D4D4D4",
1517
+"(	c #EEEEEE",
1518
+"_	c #595959",
1519
+":	c #7B7B7B",
1520
+"<	c #E9E9E9",
1521
+"[	c #131313",
1522
+"}	c #E3E3E3",
1523
+"|	c #767676",
1524
+"1	c #505050",
1525
+"2	c #F3F3F3",
1526
+"3	c #2A2A2A",
1527
+"4	c #070707",
1528
+"5	c #343434",
1529
+"6	c #939393",
1530
+"7	c #191919",
1531
+"8	c #6A6A6A",
1532
+".................",
1533
+".+@@@@@@@@@@@@@+.",
1534
+".................",
1535
+" #$%%%%%%%%%%%$# ",
1536
+" &*%%%%%%%%%%%=& ",
1537
+" -;%%%%%%%%%%%;- ",
1538
+"  >%%%%%%%%%%%>  ",
1539
+"  ,%%%%%%%%%%%,  ",
1540
+"  ')%%%%%%%%%)'  ",
1541
+"  !~%%%%%%%%%~!  ",
1542
+"   {%%%%%%%%%{   ",
1543
+"   ]^/...../^]   ",
1544
+"   (_:.....:_(   ",
1545
+"    <[}...}[<    ",
1546
+"    !|1...1|!    ",
1547
+"     2[3.3[2     ",
1548
+"     2[%.%[2     ",
1549
+"    !|%%.%%|!    ",
1550
+"    <4%%.%%4<    ",
1551
+"   (_%%%.%%%_(   ",
1552
+"   ]^%%%.%%%^]   ",
1553
+"   {%%%%.%%%%{   ",
1554
+"  !~%%%%.%%%%~!  ",
1555
+"  ')%%%%.%%%%)'  ",
1556
+"  ,%%56{.{65%%,  ",
1557
+"  >%*.......*%>  ",
1558
+" -;7&.......&7;- ",
1559
+" &*8.........8=& ",
1560
+" #$%%%%%%%%%%%$# ",
1561
+".................",
1562
+".+@@@@@@@@@@@@@+.",
1563
+"................."};
1564
diff -Nur src/Fl.cxx src/Fl.cxx
1565
--- src/Fl.cxx	2012-08-16 22:59:36.000000000 +0200
1566
+++ src/Fl.cxx	2013-07-17 19:38:01.696342059 +0200
1567
@@ -70,6 +70,8 @@
1568
 extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle);
1569
 #endif // WIN32
1570
 
1571
+extern void fl_update_focus(void);
1572
+
1573
 //
1574
 // Globals...
1575
 //
1576
@@ -435,6 +437,69 @@
1577
 #endif
1578
 
1579
 ////////////////////////////////////////////////////////////////
1580
+// Clipboard notifications
1581
+
1582
+struct Clipboard_Notify {
1583
+  Fl_Clipboard_Notify_Handler handler;
1584
+  void *data;
1585
+  struct Clipboard_Notify *next;
1586
+};
1587
+
1588
+static struct Clipboard_Notify *clip_notify_list = NULL;
1589
+
1590
+extern void fl_clipboard_notify_change(); // in Fl_<platform>.cxx
1591
+
1592
+void Fl::add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data) {
1593
+  struct Clipboard_Notify *node;
1594
+
1595
+  remove_clipboard_notify(h);
1596
+
1597
+  node = new Clipboard_Notify;
1598
+
1599
+  node->handler = h;
1600
+  node->data = data;
1601
+  node->next = clip_notify_list;
1602
+
1603
+  clip_notify_list = node;
1604
+
1605
+  fl_clipboard_notify_change();
1606
+}
1607
+
1608
+void Fl::remove_clipboard_notify(Fl_Clipboard_Notify_Handler h) {
1609
+  struct Clipboard_Notify *node, **prev;
1610
+
1611
+  node = clip_notify_list;
1612
+  prev = &clip_notify_list;
1613
+  while (node != NULL) {
1614
+    if (node->handler == h) {
1615
+      *prev = node->next;
1616
+      delete node;
1617
+
1618
+      fl_clipboard_notify_change();
1619
+
1620
+      return;
1621
+    }
1622
+
1623
+    prev = &node->next;
1624
+    node = node->next;
1625
+  }
1626
+}
1627
+
1628
+bool fl_clipboard_notify_empty(void) {
1629
+  return clip_notify_list == NULL;
1630
+}
1631
+
1632
+void fl_trigger_clipboard_notify(int source) {
1633
+  struct Clipboard_Notify *node;
1634
+
1635
+  node = clip_notify_list;
1636
+  while (node != NULL) {
1637
+    node->handler(source, node->data);
1638
+    node = node->next;
1639
+  }
1640
+}
1641
+
1642
+////////////////////////////////////////////////////////////////
1643
 // wait/run/check/ready:
1644
 
1645
 void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions
1646
@@ -876,6 +941,8 @@
1647
       fl_oldfocus = p;
1648
     }
1649
     e_number = old_event;
1650
+    // let the platform code do what it needs
1651
+    fl_update_focus();
1652
   }
1653
 }
1654
 
1655
@@ -1464,6 +1531,8 @@
1656
   if (xclass_) {
1657
     free(xclass_);
1658
   }
1659
+  free_icons();
1660
+  delete icon_;
1661
 }
1662
 
1663
 // FL_SHOW and FL_HIDE are called whenever the visibility of this widget
1664
diff -Nur src/fl_draw_pixmap.cxx src/fl_draw_pixmap.cxx
1665
--- src/fl_draw_pixmap.cxx	2012-04-22 05:09:31.000000000 +0200
1666
+++ src/fl_draw_pixmap.cxx	2013-07-17 19:37:37.911343302 +0200
1667
@@ -58,99 +58,6 @@
1668
   return 1;
1669
 }
1670
 
1671
-#ifdef U64
1672
-
1673
-// The callback from fl_draw_image to get a row of data passes this:
1674
-struct pixmap_data {
1675
-  int w, h;
1676
-  const uchar*const* data;
1677
-  union {
1678
-    U64 colors[256];
1679
-    U64* byte1[256];
1680
-  };
1681
-};
1682
-
1683
-// callback for 1 byte per pixel:
1684
-static void cb1(void*v, int x, int y, int w, uchar* buf) {
1685
-  pixmap_data& d = *(pixmap_data*)v;
1686
-  const uchar* p = d.data[y]+x;
1687
-  U64* q = (U64*)buf;
1688
-  for (int X=w; X>0; X-=2, p += 2) {
1689
-    if (X>1) {
1690
-#  if WORDS_BIGENDIAN
1691
-      *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]];
1692
-#  else
1693
-      *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]];
1694
-#  endif
1695
-    } else {
1696
-#  if WORDS_BIGENDIAN
1697
-      *q++ = d.colors[p[0]]<<32;
1698
-#  else
1699
-      *q++ = d.colors[p[0]];
1700
-#  endif
1701
-    }
1702
-  }
1703
-}
1704
-
1705
-// callback for 2 bytes per pixel:
1706
-static void cb2(void*v, int x, int y, int w, uchar* buf) {
1707
-  pixmap_data& d = *(pixmap_data*)v;
1708
-  const uchar* p = d.data[y]+2*x;
1709
-  U64* q = (U64*)buf;
1710
-  for (int X=w; X>0; X-=2) {
1711
-    U64* colors = d.byte1[*p++];
1712
-    int index = *p++;
1713
-    if (X>1) {
1714
-      U64* colors1 = d.byte1[*p++];
1715
-      int index1 = *p++;
1716
-#  if WORDS_BIGENDIAN
1717
-      *q++ = (colors[index]<<32) | colors1[index1];
1718
-#  else
1719
-      *q++ = (colors1[index1]<<32) | colors[index];
1720
-#  endif
1721
-    } else {
1722
-#  if WORDS_BIGENDIAN
1723
-      *q++ = colors[index]<<32;
1724
-#  else
1725
-      *q++ = colors[index];
1726
-#  endif
1727
-    }
1728
-  }
1729
-}
1730
-
1731
-#else // U32
1732
-
1733
-// The callback from fl_draw_image to get a row of data passes this:
1734
-struct pixmap_data {
1735
-  int w, h;
1736
-  const uchar*const* data;
1737
-  union {
1738
-    U32 colors[256];
1739
-    U32* byte1[256];
1740
-  };
1741
-};
1742
-
1743
-// callback for 1 byte per pixel:
1744
-static void cb1(void*v, int x, int y, int w, uchar* buf) {
1745
-  pixmap_data& d = *(pixmap_data*)v;
1746
-  const uchar* p = d.data[y]+x;
1747
-  U32* q = (U32*)buf;
1748
-  for (int X=w; X--;) *q++ = d.colors[*p++];
1749
-}
1750
-
1751
-// callback for 2 bytes per pixel:
1752
-static void cb2(void*v, int x, int y, int w, uchar* buf) {
1753
-  pixmap_data& d = *(pixmap_data*)v;
1754
-  const uchar* p = d.data[y]+2*x;
1755
-  U32* q = (U32*)buf;
1756
-  for (int X=w; X--;) {
1757
-    U32* colors = d.byte1[*p++];
1758
-    *q++ = colors[*p++];
1759
-  }
1760
-}
1761
-
1762
-#endif // U64 else U32
1763
-
1764
 uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here
1765
 
1766
 /**
1767
@@ -200,34 +107,33 @@
1768
 }
1769
 #endif
1770
 
1771
-/**
1772
-  Draw XPM image data, with the top-left corner at the given position.
1773
-  \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
1774
-  */
1775
-int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
1776
-  pixmap_data d;
1777
-  if (!fl_measure_pixmap(cdata, d.w, d.h)) return 0;
1778
+int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg) {
1779
+  int w, h;
1780
   const uchar*const* data = (const uchar*const*)(cdata+1);
1781
   int transparent_index = -1;
1782
+
1783
+  if (!fl_measure_pixmap(cdata, w, h))
1784
+    return 0;
1785
+
1786
+  if ((chars_per_pixel < 1) || (chars_per_pixel > 2))
1787
+    return 0;
1788
+
1789
+  uchar colors[1<<(chars_per_pixel*8)][4];
1790
+
1791
 #ifdef WIN32
1792
   uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color
1793
   color_count = 0;
1794
   used_colors = (uchar *)malloc(abs(ncolors)*3*sizeof(uchar));
1795
 #endif
1796
 
1797
-  if (ncolors < 0) {	// FLTK (non standard) compressed colormap
1798
+  if (ncolors < 0) {
1799
+    // FLTK (non standard) compressed colormap
1800
     ncolors = -ncolors;
1801
     const uchar *p = *data++;
1802
     // if first color is ' ' it is transparent (put it later to make
1803
     // it not be transparent):
1804
     if (*p == ' ') {
1805
-      uchar* c = (uchar*)&d.colors[(int)' '];
1806
-#ifdef U64
1807
-      *(U64*)c = 0;
1808
-#  if WORDS_BIGENDIAN
1809
-      c += 4;
1810
-#  endif
1811
-#endif
1812
+      uchar* c = colors[(int)' '];
1813
       transparent_index = ' ';
1814
       Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
1815
 #ifdef WIN32
1816
@@ -238,13 +144,7 @@
1817
     }
1818
     // read all the rest of the colors:
1819
     for (int i=0; i < ncolors; i++) {
1820
-      uchar* c = (uchar*)&d.colors[*p++];
1821
-#ifdef U64
1822
-      *(U64*)c = 0;
1823
-#  if WORDS_BIGENDIAN
1824
-      c += 4;
1825
-#  endif
1826
-#endif
1827
+      uchar* c = colors[*p++];
1828
 #ifdef WIN32
1829
       used_colors[3*color_count] = *p;
1830
       used_colors[3*color_count+1] = *(p+1);
1831
@@ -254,69 +154,44 @@
1832
       *c++ = *p++;
1833
       *c++ = *p++;
1834
       *c++ = *p++;
1835
-#ifdef __APPLE_QUARTZ__
1836
       *c = 255;
1837
-#else
1838
-      *c = 0;
1839
-#endif
1840
     }
1841
-  } else {	// normal XPM colormap with names
1842
-    if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1));
1843
+  } else {
1844
+    // normal XPM colormap with names
1845
     for (int i=0; i<ncolors; i++) {
1846
       const uchar *p = *data++;
1847
       // the first 1 or 2 characters are the color index:
1848
       int ind = *p++;
1849
       uchar* c;
1850
-      if (chars_per_pixel>1) {
1851
-#ifdef U64
1852
-	U64* colors = d.byte1[ind];
1853
-	if (!colors) colors = d.byte1[ind] = new U64[256];
1854
-#else
1855
-	U32* colors = d.byte1[ind];
1856
-	if (!colors) colors = d.byte1[ind] = new U32[256];
1857
-#endif
1858
-	c = (uchar*)&colors[*p];
1859
-	ind = (ind<<8)|*p++;
1860
-      } else {
1861
-	c = (uchar *)&d.colors[ind];
1862
-      }
1863
+      if (chars_per_pixel>1)
1864
+        ind = (ind<<8)|*p++;
1865
+      c = colors[ind];
1866
       // look for "c word", or last word if none:
1867
       const uchar *previous_word = p;
1868
       for (;;) {
1869
-	while (*p && isspace(*p)) p++;
1870
-	uchar what = *p++;
1871
-	while (*p && !isspace(*p)) p++;
1872
-	while (*p && isspace(*p)) p++;
1873
-	if (!*p) {p = previous_word; break;}
1874
-	if (what == 'c') break;
1875
-	previous_word = p;
1876
-	while (*p && !isspace(*p)) p++;
1877
+        while (*p && isspace(*p)) p++;
1878
+        uchar what = *p++;
1879
+        while (*p && !isspace(*p)) p++;
1880
+        while (*p && isspace(*p)) p++;
1881
+        if (!*p) {p = previous_word; break;}
1882
+        if (what == 'c') break;
1883
+        previous_word = p;
1884
+        while (*p && !isspace(*p)) p++;
1885
       }
1886
-#ifdef U64
1887
-      *(U64*)c = 0;
1888
-#  if WORDS_BIGENDIAN
1889
-      c += 4;
1890
-#  endif
1891
-#endif
1892
-#ifdef __APPLE_QUARTZ__
1893
-      c[3] = 255;
1894
-#endif
1895
       int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]);
1896
+      c[3] = 255;
1897
       if (parse) {
1898
 #ifdef WIN32
1899
-	used_colors[3*color_count] = c[0];
1900
-	used_colors[3*color_count+1] = c[1];
1901
-	used_colors[3*color_count+2] = c[2];
1902
-	color_count++;
1903
+        used_colors[3*color_count] = c[0];
1904
+        used_colors[3*color_count+1] = c[1];
1905
+        used_colors[3*color_count+2] = c[2];
1906
+        color_count++;
1907
 #endif
1908
-	}
1909
-      else {
1910
+      } else {
1911
         // assume "None" or "#transparent" for any errors
1912
-	// "bg" should be transparent...
1913
-	Fl::get_color(bg, c[0], c[1], c[2]);
1914
-#ifdef __APPLE_QUARTZ__
1915
+        // "bg" should be transparent...
1916
+        Fl::get_color(bg, c[0], c[1], c[2]);
1917
         c[3] = 0;
1918
-#endif
1919
 	transparent_index = ind;
1920
 #ifdef WIN32
1921
 	transparent_c = c;
1922
@@ -324,7 +199,6 @@
1923
       }
1924
     }
1925
   }
1926
-  d.data = data;
1927
 #ifdef WIN32
1928
   if (transparent_c) {
1929
     make_unused_color(transparent_c[0], transparent_c[1], transparent_c[2]);
1930
@@ -334,77 +208,76 @@
1931
     make_unused_color(r, g, b);
1932
   }
1933
 #endif
1934
+
1935
+  U32 *q = (U32*)out;
1936
+  for (int Y = 0; Y < h; Y++) {
1937
+    const uchar* p = data[Y];
1938
+    if (chars_per_pixel <= 1) {
1939
+      for (int X = 0; X < w; X++)
1940
+        memcpy(q++, colors[*p++], 4);
1941
+    } else {
1942
+      for (int X = 0; X < w; X++) {
1943
+        int ind = (*p++)<<8;
1944
+        ind |= *p++;
1945
+        memcpy(q++, colors[ind], 4);
1946
+      }
1947
+    }
1948
+  }
1949
   
1950
+  return 1;
1951
+}
1952
+
1953
+/**
1954
+  Draw XPM image data, with the top-left corner at the given position.
1955
+  \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
1956
+  */
1957
+int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
1958
+  int w, h;
1959
+
1960
+  if (!fl_measure_pixmap(cdata, w, h))
1961
+    return 0;
1962
+
1963
+  uchar buffer[w*h*4];
1964
+
1965
+  if (!fl_convert_pixmap(cdata, buffer, bg))
1966
+    return 0;
1967
+
1968
+  // FIXME: Hack until fl_draw_image() supports alpha properly
1969
 #ifdef  __APPLE_QUARTZ__
1970
   if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) {
1971
-    U32 *array = new U32[d.w * d.h], *q = array;
1972
-    for (int Y = 0; Y < d.h; Y++) {
1973
-      const uchar* p = data[Y];
1974
-      if (chars_per_pixel <= 1) {
1975
-	for (int X = 0; X < d.w; X++) {
1976
-	  *q++ = d.colors[*p++];
1977
-	}
1978
-      } else {
1979
-	for (int X = 0; X < d.w; X++) {
1980
-	  U32* colors = (U32*)d.byte1[*p++];
1981
-	  *q++ = colors[*p++];
1982
-	}
1983
-      }
1984
-    }
1985
-    Fl_RGB_Image* rgb = new Fl_RGB_Image((uchar*)array, d.w, d.h, 4);
1986
+    Fl_RGB_Image* rgb = new Fl_RGB_Image(buffer, w, h, 4);
1987
     rgb->draw(x, y);
1988
     delete rgb;
1989
-    delete[] array;
1990
-    }
1991
-  else {
1992
+  } else {
1993
 #endif // __APPLE_QUARTZ__
1994
-
1995
   // build the mask bitmap used by Fl_Pixmap:
1996
-  if (fl_mask_bitmap && transparent_index >= 0) {
1997
-    int W = (d.w+7)/8;
1998
-    uchar* bitmap = new uchar[W * d.h];
1999
+  if (fl_mask_bitmap) {
2000
+    int W = (w+7)/8;
2001
+    uchar* bitmap = new uchar[W * h];
2002
     *fl_mask_bitmap = bitmap;
2003
-    for (int Y = 0; Y < d.h; Y++) {
2004
-      const uchar* p = data[Y];
2005
-      if (chars_per_pixel <= 1) {
2006
-	int dw = d.w;
2007
-	for (int X = 0; X < W; X++) {
2008
-	  uchar b = (dw-->0 && *p++ != transparent_index);
2009
-	  if (dw-->0 && *p++ != transparent_index) b |= 2;
2010
-	  if (dw-->0 && *p++ != transparent_index) b |= 4;
2011
-	  if (dw-->0 && *p++ != transparent_index) b |= 8;
2012
-	  if (dw-->0 && *p++ != transparent_index) b |= 16;
2013
-	  if (dw-->0 && *p++ != transparent_index) b |= 32;
2014
-	  if (dw-->0 && *p++ != transparent_index) b |= 64;
2015
-	  if (dw-->0 && *p++ != transparent_index) b |= 128;
2016
+    const uchar *p = &buffer[3];
2017
+    uchar b = 0;
2018
+    for (int Y = 0; Y < h; Y++) {
2019
+      b = 0;
2020
+      for (int X = 0, bit = 1; X < w; X++, p += 4) {
2021
+	if (*p > 127) b |= bit;
2022
+	bit <<= 1;
2023
+	if (bit > 0x80 || X == w-1) {
2024
 	  *bitmap++ = b;
2025
-	}
2026
-      } else {
2027
-        uchar b = 0, bit = 1;
2028
-	for (int X = 0; X < d.w; X++) {
2029
-	  int ind = *p++;
2030
-	  ind = (ind<<8) | (*p++);
2031
-	  if (ind != transparent_index) b |= bit;
2032
-
2033
-          if (bit < 128) bit <<= 1;
2034
-	  else {
2035
-	    *bitmap++ = b;
2036
-	    b = 0;
2037
-	    bit = 1;
2038
+	  bit = 1;
2039
+	  b = 0;
2040
 	  }
2041
 	}
2042
-
2043
-        if (bit > 1) *bitmap++ = b;
2044
       }
2045
-    }
2046
+    
2047
   }
2048
 
2049
-  fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4);
2050
+  fl_draw_image(buffer, x, y, w, h, 4);
2051
+
2052
 #ifdef __APPLE_QUARTZ__
2053
     }
2054
 #endif
2055
 
2056
-  if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i];
2057
   return 1;
2058
 }
2059
 
2060
diff -Nur src/Fl_grab.cxx src/Fl_grab.cxx
2061
--- src/Fl_grab.cxx	2012-03-23 17:47:53.000000000 +0100
2062
+++ src/Fl_grab.cxx	2013-07-17 19:37:07.411344886 +0200
2063
@@ -29,6 +29,7 @@
2064
 // override_redirect, it does similar things on WIN32.
2065
 
2066
 extern void fl_fix_focus(); // in Fl.cxx
2067
+void fl_update_focus(void);
2068
 
2069
 #ifdef WIN32
2070
 // We have to keep track of whether we have captured the mouse, since
2071
@@ -80,6 +81,7 @@
2072
 #endif
2073
     }
2074
     grab_ = win;
2075
+    fl_update_focus();
2076
   } else {
2077
     if (grab_) {
2078
 #ifdef WIN32
2079
@@ -98,6 +100,7 @@
2080
       XFlush(fl_display);
2081
 #endif
2082
       grab_ = 0;
2083
+      fl_update_focus();
2084
       fl_fix_focus();
2085
     }
2086
   }
2087
diff -Nur src/Fl_Image.cxx src/Fl_Image.cxx
2088
--- src/Fl_Image.cxx	2012-11-09 17:02:08.000000000 +0100
2089
+++ src/Fl_Image.cxx	2013-07-17 19:37:37.911343302 +0200
2090
@@ -165,7 +165,22 @@
2091
 //
2092
 size_t Fl_RGB_Image::max_size_ = ~((size_t)0);
2093
 
2094
-/**  The destructor free all memory and server resources that are used by  the image. */
2095
+int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
2096
+
2097
+/** The constructor creates a new RGBA image from the specified Fl_Pixmap. 
2098
+ 
2099
+ The RGBA image is built fully opaque except for the transparent area
2100
+ of the pixmap that is assigned the \par bg color with full transparency */
2101
+Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg):
2102
+  Fl_Image(pxm->w(), pxm->h(), 4), id_(0), mask_(0)
2103
+{
2104
+  array = new uchar[w() * h() * d()];
2105
+  alloc_array = 1;
2106
+  fl_convert_pixmap(pxm->data(), (uchar*)array, bg);
2107
+  data((const char **)&array, 1);
2108
+}
2109
+
2110
+/**  The destructor frees all memory and server resources that are used by the image. */
2111
 Fl_RGB_Image::~Fl_RGB_Image() {
2112
   uncache();
2113
   if (alloc_array) delete[] (uchar *)array;
2114
diff -Nur src/Fl_win32.cxx src/Fl_win32.cxx
2115
--- src/Fl_win32.cxx	2012-06-21 10:52:29.000000000 +0200
2116
+++ src/Fl_win32.cxx	2013-07-17 19:38:17.322341239 +0200
2117
@@ -942,6 +942,10 @@
2118
     break;
2119
 
2120
   case WM_SETFOCUS:
2121
+    if ((Fl::modal_) && (Fl::modal_ != window)) {
2122
+      SetFocus(fl_xid(Fl::modal_));
2123
+      return 0;
2124
+    }
2125
     Fl::handle(FL_FOCUS, window);
2126
     break;
2127
 
2128
@@ -1333,7 +1337,6 @@
2129
   Y+=yoff;
2130
 
2131
   if (w->fullscreen_active()) {
2132
-    X = Y = 0;
2133
     bx = by = bt = 0;
2134
   }
2135
 
2136
@@ -1387,19 +1390,42 @@
2137
   }
2138
 }
2139
 
2140
-static void make_fullscreen(Fl_Window *w, Window xid, int X, int Y, int W, int H) {
2141
+void Fl_X::make_fullscreen(int X, int Y, int W, int H) {
2142
+  int top, bottom, left, right;
2143
   int sx, sy, sw, sh;
2144
-  Fl::screen_xywh(sx, sy, sw, sh, X, Y, W, H);
2145
+
2146
+  top = w->fullscreen_screen_top;
2147
+  bottom = w->fullscreen_screen_bottom;
2148
+  left = w->fullscreen_screen_left;
2149
+  right = w->fullscreen_screen_right;
2150
+
2151
+  if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
2152
+    top = Fl::screen_num(X, Y, W, H);
2153
+    bottom = top;
2154
+    left = top;
2155
+    right = top;
2156
+  }
2157
+
2158
+  Fl::screen_xywh(sx, sy, sw, sh, top);
2159
+  Y = sy;
2160
+  Fl::screen_xywh(sx, sy, sw, sh, bottom);
2161
+  H = sy + sh - Y;
2162
+  Fl::screen_xywh(sx, sy, sw, sh, left);
2163
+  X = sx;
2164
+  Fl::screen_xywh(sx, sy, sw, sh, right);
2165
+  W = sx + sw - X;
2166
+
2167
   DWORD flags = GetWindowLong(xid, GWL_STYLE);
2168
   flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
2169
   SetWindowLong(xid, GWL_STYLE, flags);
2170
+
2171
   // SWP_NOSENDCHANGING is so that we can override size limits
2172
-  SetWindowPos(xid, HWND_TOP, sx, sy, sw, sh, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
2173
+  SetWindowPos(xid, HWND_TOP, X, Y, W, H, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
2174
 }
2175
 
2176
 void Fl_Window::fullscreen_x() {
2177
   _set_fullscreen();
2178
-  make_fullscreen(this, fl_xid(this), x(), y(), w(), h());
2179
+  i->make_fullscreen(x(), y(), w(), h());
2180
   Fl::handle(FL_FULLSCREEN, this);
2181
 }
2182
 
2183
@@ -1477,7 +1503,6 @@
2184
 
2185
 char fl_show_iconic;	// hack for Fl_Window::iconic()
2186
 // int fl_background_pixel = -1; // color to use for background
2187
-HCURSOR fl_default_cursor;
2188
 UINT fl_wake_msg = 0;
2189
 int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
2190
 
2191
@@ -1526,7 +1551,7 @@
2192
     if (!w->icon())
2193
       w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
2194
     wcw.hIcon = wcw.hIconSm = (HICON)w->icon();
2195
-    wcw.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
2196
+    wcw.hCursor = LoadCursor(NULL, IDC_ARROW);
2197
     //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
2198
     //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
2199
     wcw.hbrBackground = NULL;
2200
@@ -1618,7 +1643,8 @@
2201
   x->setwindow(w);
2202
   x->region = 0;
2203
   x->private_dc = 0;
2204
-  x->cursor = fl_default_cursor;
2205
+  x->cursor = LoadCursor(NULL, IDC_ARROW);
2206
+  x->custom_cursor = 0;
2207
   if (!fl_codepage) fl_get_codepage();
2208
 
2209
   WCHAR *lab = NULL;
2210
@@ -1644,6 +1670,8 @@
2211
   );
2212
   if (lab) free(lab);
2213
 
2214
+  x->set_icons();
2215
+
2216
   if (w->fullscreen_active()) {
2217
   /* We need to make sure that the fullscreen is created on the
2218
      default monitor, ie the desktop where the shortcut is located
2219
@@ -1652,8 +1680,8 @@
2220
      monitor the window was placed on. */
2221
     RECT rect;
2222
     GetWindowRect(x->xid, &rect);
2223
-    make_fullscreen(w, x->xid, rect.left, rect.top, 
2224
-                    rect.right - rect.left, rect.bottom - rect.top);
2225
+    x->make_fullscreen(rect.left, rect.top, 
2226
+                       rect.right - rect.left, rect.bottom - rect.top);
2227
   }
2228
 
2229
   x->next = Fl_X::first;
2230
@@ -1668,6 +1696,11 @@
2231
     Fl::e_number = old_event;
2232
     w->redraw(); // force draw to happen
2233
   }
2234
+
2235
+  // Needs to be done before ShowWindow() to get the correct behaviour
2236
+  // when we get WM_SETFOCUS.
2237
+  if (w->modal()) {Fl::modal_ = w; fl_fix_focus();}
2238
+
2239
   // If we've captured the mouse, we dont want to activate any
2240
   // other windows from the code, or we lose the capture.
2241
   ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
2242
@@ -1685,7 +1718,6 @@
2243
     }
2244
   }
2245
 
2246
-  if (w->modal()) {Fl::modal_ = w; fl_fix_focus();}
2247
   return x;
2248
 }
2249
 
2250
@@ -1867,6 +1899,285 @@
2251
 }
2252
 
2253
 ////////////////////////////////////////////////////////////////
2254
+
2255
+static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon=true,
2256
+                           int hotx = 0, int hoty = 0) {
2257
+  BITMAPV5HEADER bi;
2258
+  HBITMAP bitmap, mask;
2259
+  DWORD *bits;
2260
+  HICON icon;
2261
+
2262
+  if (!is_icon) {
2263
+  if ((hotx < 0) || (hotx >= image->w()))
2264
+      return NULL;
2265
+  if ((hoty < 0) || (hoty >= image->h()))
2266
+      return NULL;
2267
+  }
2268
+
2269
+  memset(&bi, 0, sizeof(BITMAPV5HEADER));
2270
+
2271
+  bi.bV5Size        = sizeof(BITMAPV5HEADER);
2272
+  bi.bV5Width       = image->w();
2273
+  bi.bV5Height      = -image->h(); // Negative for top-down
2274
+  bi.bV5Planes      = 1;
2275
+  bi.bV5BitCount    = 32;
2276
+  bi.bV5Compression = BI_BITFIELDS;
2277
+  bi.bV5RedMask     = 0x00FF0000;
2278
+  bi.bV5GreenMask   = 0x0000FF00;
2279
+  bi.bV5BlueMask    = 0x000000FF;
2280
+  bi.bV5AlphaMask   = 0xFF000000;
2281
+
2282
+  HDC hdc;
2283
+
2284
+  hdc = GetDC(NULL);
2285
+  bitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
2286
+  ReleaseDC(NULL, hdc);
2287
+
2288
+  if (bits == NULL)
2289
+    return NULL;
2290
+
2291
+  const uchar *i = (const uchar*)*image->data();
2292
+  for (int y = 0;y < image->h();y++) {
2293
+    for (int x = 0;x < image->w();x++) {
2294
+      switch (image->d()) {
2295
+      case 1:
2296
+        *bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
2297
+        break;
2298
+      case 2:
2299
+        *bits = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
2300
+        break;
2301
+      case 3:
2302
+        *bits = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
2303
+        break;
2304
+      case 4:
2305
+        *bits = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
2306
+        break;
2307
+      }
2308
+      i += image->d();
2309
+      bits++;
2310
+    }
2311
+    i += image->ld();
2312
+  }
2313
+
2314
+  // A mask bitmap is still needed even though it isn't used
2315
+  mask = CreateBitmap(image->w(),image->h(),1,1,NULL);
2316
+  if (mask == NULL) {
2317
+    DeleteObject(bitmap);
2318
+    return NULL;
2319
+  }
2320
+
2321
+  ICONINFO ii;
2322
+
2323
+  ii.fIcon    = is_icon;
2324
+  ii.xHotspot = hotx;
2325
+  ii.yHotspot = hoty;
2326
+  ii.hbmMask  = mask;
2327
+  ii.hbmColor = bitmap;
2328
+
2329
+  icon = CreateIconIndirect(&ii);
2330
+
2331
+  DeleteObject(bitmap);
2332
+  DeleteObject(mask);
2333
+
2334
+  if (icon == NULL)
2335
+    return NULL;
2336
+
2337
+  return icon;
2338
+}
2339
+
2340
+////////////////////////////////////////////////////////////////
2341
+
2342
+static HICON default_big_icon = NULL;
2343
+static HICON default_small_icon = NULL;
2344
+
2345
+const Fl_RGB_Image *find_best_icon(int ideal_width, 
2346
+                                   const Fl_RGB_Image *icons[], int count) {
2347
+  const Fl_RGB_Image *best;
2348
+
2349
+  best = NULL;
2350
+
2351
+  for (int i = 0;i < count;i++) {
2352
+    if (best == NULL)
2353
+      best = icons[i];
2354
+    else {
2355
+      if (best->w() < ideal_width) {
2356
+        if (icons[i]->w() > best->w())
2357
+          best = icons[i];
2358
+      } else {
2359
+        if ((icons[i]->w() >= ideal_width) &&
2360
+            (icons[i]->w() < best->w()))
2361
+          best = icons[i];
2362
+      }
2363
+    }
2364
+  }
2365
+
2366
+  return best;
2367
+}
2368
+
2369
+void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) {
2370
+  const Fl_RGB_Image *best_big, *best_small;
2371
+
2372
+  if (default_big_icon != NULL)
2373
+    DestroyIcon(default_big_icon);
2374
+  if (default_small_icon != NULL)
2375
+    DestroyIcon(default_small_icon);
2376
+
2377
+  best_big = find_best_icon(GetSystemMetrics(SM_CXICON), icons, count);
2378
+  best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), icons, count);
2379
+
2380
+  if (best_big != NULL)
2381
+    default_big_icon = image_to_icon(best_big);
2382
+  else
2383
+    default_big_icon = NULL;
2384
+
2385
+  if (best_small != NULL)
2386
+    default_small_icon = image_to_icon(best_small);
2387
+  else
2388
+    default_small_icon = NULL;
2389
+}
2390
+
2391
+void Fl_X::set_default_icons(HICON big_icon, HICON small_icon) {
2392
+  if (default_big_icon != NULL)
2393
+    DestroyIcon(default_big_icon);
2394
+  if (default_small_icon != NULL)
2395
+    DestroyIcon(default_small_icon);
2396
+
2397
+  if (big_icon != NULL)
2398
+    default_big_icon = CopyIcon(big_icon);
2399
+  if (small_icon != NULL)
2400
+    default_small_icon = CopyIcon(small_icon);
2401
+}
2402
+
2403
+void Fl_X::set_icons() {
2404
+  HICON big_icon, small_icon;
2405
+
2406
+  big_icon = NULL;
2407
+  small_icon = NULL;
2408
+
2409
+  if (w->icon_->count) {
2410
+    const Fl_RGB_Image *best_big, *best_small;
2411
+
2412
+    best_big = find_best_icon(GetSystemMetrics(SM_CXICON),
2413
+                              (const Fl_RGB_Image **)w->icon_->icons,
2414
+                              w->icon_->count);
2415
+    best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON),
2416
+                                (const Fl_RGB_Image **)w->icon_->icons,
2417
+                                w->icon_->count);
2418
+
2419
+    if (best_big != NULL)
2420
+      big_icon = image_to_icon(best_big);
2421
+    if (best_small != NULL)
2422
+      small_icon = image_to_icon(best_small);
2423
+  } else {
2424
+    big_icon = default_big_icon;
2425
+    small_icon = default_small_icon;
2426
+  }
2427
+
2428
+  if (big_icon != NULL)
2429
+    SendMessage(xid, WM_SETICON, ICON_BIG, (LPARAM)big_icon);
2430
+  if (small_icon != NULL)
2431
+    SendMessage(xid, WM_SETICON, ICON_SMALL, (LPARAM)small_icon);
2432
+
2433
+  if (w->icon_->count) {
2434
+    if (big_icon != NULL)
2435
+      DestroyIcon(big_icon);
2436
+    if (small_icon != NULL)
2437
+      DestroyIcon(small_icon);
2438
+  }
2439
+}
2440
+
2441
+void Fl_Window::default_icons(HICON big_icon, HICON small_icon) {
2442
+  Fl_X::set_default_icons(big_icon, small_icon);
2443
+}
2444
+
2445
+void Fl_Window::icons(HICON big_icon, HICON small_icon) {
2446
+  free_icons();
2447
+
2448
+  if (big_icon != NULL)
2449
+    icon_->big_icon = CopyIcon(big_icon);
2450
+  if (small_icon != NULL)
2451
+    icon_->small_icon = CopyIcon(small_icon);
2452
+
2453
+  if (i)
2454
+    i->set_icons();
2455
+}
2456
+
2457
+////////////////////////////////////////////////////////////////
2458
+
2459
+#ifndef IDC_HAND
2460
+#  define IDC_HAND  MAKEINTRESOURCE(32649)
2461
+#endif // !IDC_HAND
2462
+
2463
+int Fl_X::set_cursor(Fl_Cursor c) {
2464
+  LPSTR n;
2465
+  HCURSOR new_cursor;
2466
+
2467
+  if (c == FL_CURSOR_NONE)
2468
+    new_cursor = NULL;
2469
+  else {
2470
+    switch (c) {
2471
+    case FL_CURSOR_ARROW:   n = IDC_ARROW; break;
2472
+    case FL_CURSOR_CROSS:   n = IDC_CROSS; break;
2473
+    case FL_CURSOR_WAIT:    n = IDC_WAIT; break;
2474
+    case FL_CURSOR_INSERT:  n = IDC_IBEAM; break;
2475
+    case FL_CURSOR_HAND:    n = IDC_HAND; break;
2476
+    case FL_CURSOR_HELP:    n = IDC_HELP; break;
2477
+    case FL_CURSOR_MOVE:    n = IDC_SIZEALL; break;
2478
+    case FL_CURSOR_N:
2479
+    case FL_CURSOR_S:
2480
+      // FIXME: Should probably have fallbacks for these instead
2481
+    case FL_CURSOR_NS:      n = IDC_SIZENS; break;
2482
+    case FL_CURSOR_NE:
2483
+    case FL_CURSOR_SW:
2484
+      // FIXME: Dito.
2485
+    case FL_CURSOR_NESW:    n = IDC_SIZENESW; break;
2486
+    case FL_CURSOR_E:
2487
+    case FL_CURSOR_W:
2488
+      // FIXME: Dito.
2489
+    case FL_CURSOR_WE:      n = IDC_SIZEWE; break;
2490
+    case FL_CURSOR_SE:
2491
+    case FL_CURSOR_NW:
2492
+      // FIXME: Dito.
2493
+    case FL_CURSOR_NWSE:    n = IDC_SIZENWSE; break;
2494
+    default:
2495
+      return 0;
2496
+    }
2497
+
2498
+    new_cursor = LoadCursor(NULL, n);
2499
+    if (new_cursor == NULL)
2500
+      return 0;
2501
+  }
2502
+
2503
+  if ((cursor != NULL) && custom_cursor)
2504
+    DestroyIcon(cursor);
2505
+
2506
+  cursor = new_cursor;
2507
+  custom_cursor = 0;
2508
+
2509
+  SetCursor(cursor);
2510
+
2511
+  return 1;
2512
+}
2513
+
2514
+int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
2515
+  HCURSOR new_cursor;
2516
+
2517
+  new_cursor = image_to_icon(image, false, hotx, hoty);
2518
+  if (new_cursor == NULL)
2519
+    return 0;
2520
+
2521
+  if ((cursor != NULL) && custom_cursor)
2522
+    DestroyIcon(cursor);
2523
+
2524
+  cursor = new_cursor;
2525
+  custom_cursor = 1;
2526
+
2527
+  SetCursor(cursor);
2528
+
2529
+  return 1;
2530
+}
2531
+
2532
+////////////////////////////////////////////////////////////////
2533
 // Implement the virtual functions for the base Fl_Window class:
2534
 
2535
 // If the box is a filled rectangle, we can make the redisplay *look*
2536
diff -Nur src/Fl_Window.cxx src/Fl_Window.cxx
2537
--- src/Fl_Window.cxx	2012-11-06 21:46:14.000000000 +0100
2538
+++ src/Fl_Window.cxx	2013-07-17 19:38:01.699342056 +0200
2539
@@ -23,6 +23,7 @@
2540
 #include <config.h>
2541
 #include <FL/Fl.H>
2542
 #include <FL/x.H>
2543
+#include <FL/Fl_RGB_Image.H>
2544
 #include <FL/Fl_Window.H>
2545
 #include <stdlib.h>
2546
 #include "flstring.h"
2547
@@ -45,7 +46,8 @@
2548
   }
2549
   i = 0;
2550
   xclass_ = 0;
2551
-  icon_ = 0;
2552
+  icon_ = new icon_data;
2553
+  memset(icon_, 0, sizeof(*icon_));
2554
   iconlabel_ = 0;
2555
   resizable(0);
2556
   size_range_set = 0;
2557
@@ -62,8 +64,6 @@
2558
 Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l)
2559
 : Fl_Group(X, Y, W, H, l) {
2560
   cursor_default = FL_CURSOR_DEFAULT;
2561
-  cursor_fg      = FL_BLACK;
2562
-  cursor_bg      = FL_WHITE;
2563
 
2564
   _Fl_Window();
2565
   set_flag(FORCE_POSITION);
2566
@@ -73,8 +73,6 @@
2567
 // fix common user error of a missing end() with current(0):
2568
   : Fl_Group((Fl_Group::current(0),0), 0, W, H, l) {
2569
   cursor_default = FL_CURSOR_DEFAULT;
2570
-  cursor_fg      = FL_BLACK;
2571
-  cursor_bg      = FL_WHITE;
2572
 
2573
   _Fl_Window();
2574
   clear_visible();
2575
@@ -268,16 +266,68 @@
2576
   }
2577
 }
2578
 
2579
+void Fl_Window::default_icon(const Fl_RGB_Image *icon) {
2580
+  default_icons(&icon, 1);
2581
+}
2582
+
2583
+void Fl_Window::default_icons(const Fl_RGB_Image **icons, int count) {
2584
+  Fl_X::set_default_icons(icons, count);
2585
+}
2586
+
2587
+void Fl_Window::icon(const Fl_RGB_Image *icon) {
2588
+  icons(&icon, 1);
2589
+}
2590
+
2591
+void Fl_Window::icons(const Fl_RGB_Image **icons, int count) {
2592
+  free_icons();
2593
+
2594
+  if (count > 0) {
2595
+    icon_->icons = new Fl_RGB_Image*[count];
2596
+    icon_->count = count;
2597
+    // FIXME: Fl_RGB_Image lacks const modifiers on methods
2598
+    for (int i = 0;i < count;i++)
2599
+      icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy();
2600
+  }
2601
+
2602
+  if (i)
2603
+    i->set_icons();
2604
+}
2605
+
2606
 /** Gets the current icon window target dependent data. */
2607
 const void *Fl_Window::icon() const {
2608
-  return icon_;
2609
+  return icon_->legacy_icon;
2610
 }
2611
 
2612
 /** Sets the current icon window target dependent data. */
2613
 void Fl_Window::icon(const void * ic) {
2614
-  icon_ = ic;
2615
+  free_icons();
2616
+  icon_->legacy_icon = ic;
2617
 }
2618
 
2619
+void Fl_Window::free_icons() {
2620
+  int i;
2621
+
2622
+  icon_->legacy_icon = 0L;
2623
+
2624
+  if (icon_->icons) {
2625
+    for (i = 0;i < icon_->count;i++)
2626
+      delete icon_->icons[i];
2627
+    delete [] icon_->icons;
2628
+    icon_->icons = 0L;
2629
+  }
2630
+
2631
+  icon_->count = 0;
2632
+
2633
+#ifdef WIN32
2634
+  if (icon_->big_icon)
2635
+    DestroyIcon(icon_->big_icon);
2636
+  if (icon_->small_icon)
2637
+    DestroyIcon(icon_->small_icon);
2638
+
2639
+  icon_->big_icon = NULL;
2640
+  icon_->small_icon = NULL;
2641
+#endif
2642
+}
2643
 
2644
 //
2645
 // End of "$Id: Fl_Window.cxx 9706 2012-11-06 20:46:14Z matt $".
2646
diff -Nur src/Fl_Window_fullscreen.cxx src/Fl_Window_fullscreen.cxx
2647
--- src/Fl_Window_fullscreen.cxx	2012-11-06 21:46:14.000000000 +0100
2648
+++ src/Fl_Window_fullscreen.cxx	2013-07-17 19:38:17.323341239 +0200
2649
@@ -36,6 +36,10 @@
2650
 int Fl_Window::no_fullscreen_y = 0;
2651
 int Fl_Window::no_fullscreen_w = 0;
2652
 int Fl_Window::no_fullscreen_h = 0;
2653
+int Fl_Window::fullscreen_screen_top = -1;
2654
+int Fl_Window::fullscreen_screen_bottom = -1;
2655
+int Fl_Window::fullscreen_screen_left = -1;
2656
+int Fl_Window::fullscreen_screen_right = -1;
2657
 #endif
2658
 
2659
 void Fl_Window::border(int b) {
2660
@@ -95,6 +99,23 @@
2661
   fullscreen_off(no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h);
2662
 }
2663
 
2664
+void Fl_Window::fullscreen_screens(int top, int bottom, int left, int right) {
2665
+  if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
2666
+    fullscreen_screen_top = -1;
2667
+    fullscreen_screen_bottom = -1;
2668
+    fullscreen_screen_left = -1;
2669
+    fullscreen_screen_right = -1;
2670
+  } else {
2671
+    fullscreen_screen_top = top;
2672
+    fullscreen_screen_bottom = bottom;
2673
+    fullscreen_screen_left = left;
2674
+    fullscreen_screen_right = right;
2675
+  }
2676
+
2677
+  if (shown() && (flags() & Fl_Widget::FULLSCREEN))
2678
+    fullscreen_x();
2679
+}
2680
+
2681
 
2682
 //
2683
 // End of "$Id: Fl_Window_fullscreen.cxx 9706 2012-11-06 20:46:14Z matt $".
2684
diff -Nur src/Fl_x.cxx src/Fl_x.cxx
2685
--- src/Fl_x.cxx	2012-10-16 17:35:34.000000000 +0200
2686
+++ src/Fl_x.cxx	2013-07-17 19:38:17.326341239 +0200
2687
@@ -53,6 +53,17 @@
2688
 static int randrEventBase;                  // base of RandR-defined events
2689
 #endif
2690
 
2691
+#  if HAVE_XFIXES
2692
+#  include <X11/extensions/Xfixes.h>
2693
+static int xfixes_event_base = 0;
2694
+static bool have_xfixes = false;
2695
+#  endif
2696
+
2697
+#  include <X11/cursorfont.h>
2698
+
2699
+#  if HAVE_XCURSOR
2700
+#    include <X11/Xcursor/Xcursor.h>
2701
+#  endif
2702
 static Fl_Xlib_Graphics_Driver fl_xlib_driver;
2703
 static Fl_Display_Device fl_xlib_display(&fl_xlib_driver);
2704
 Fl_Display_Device *Fl_Display_Device::_display = &fl_xlib_display;// the platform display
2705
@@ -298,6 +309,7 @@
2706
 Colormap fl_colormap;
2707
 XIM fl_xim_im = 0;
2708
 XIC fl_xim_ic = 0;
2709
+Window fl_xim_win = 0;
2710
 char fl_is_over_the_spot = 0;
2711
 static XRectangle status_area;
2712
 
2713
@@ -306,6 +318,9 @@
2714
 static Atom fl_MOTIF_WM_HINTS;
2715
 static Atom TARGETS;
2716
 static Atom CLIPBOARD;
2717
+static Atom TIMESTAMP;
2718
+static Atom PRIMARY_TIMESTAMP;
2719
+static Atom CLIPBOARD_TIMESTAMP;
2720
 Atom fl_XdndAware;
2721
 Atom fl_XdndSelection;
2722
 Atom fl_XdndEnter;
2723
@@ -329,7 +344,9 @@
2724
 Atom fl_NET_SUPPORTING_WM_CHECK;
2725
 Atom fl_NET_WM_STATE;
2726
 Atom fl_NET_WM_STATE_FULLSCREEN;
2727
+Atom fl_NET_WM_FULLSCREEN_MONITORS;
2728
 Atom fl_NET_WORKAREA;
2729
+Atom fl_NET_WM_ICON;
2730
 
2731
 /*
2732
   X defines 32-bit-entities to have a format value of max. 32,
2733
@@ -583,6 +600,65 @@
2734
   if(xim_styles) XFree(xim_styles);
2735
 }
2736
 
2737
+void fl_xim_deactivate(void);
2738
+
2739
+void fl_xim_activate(Window xid)
2740
+{
2741
+  if (!fl_xim_im)
2742
+    return;
2743
+
2744
+  // If the focused window has changed, then use the brute force method
2745
+  // of completely recreating the input context.
2746
+  if (fl_xim_win != xid) {
2747
+    fl_xim_deactivate();
2748
+
2749
+    fl_new_ic();
2750
+    fl_xim_win = xid;
2751
+
2752
+    XSetICValues(fl_xim_ic,
2753
+                 XNFocusWindow, fl_xim_win,
2754
+                 XNClientWindow, fl_xim_win,
2755
+                 NULL);
2756
+  }
2757
+
2758
+  fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2759
+}
2760
+
2761
+void fl_xim_deactivate(void)
2762
+{
2763
+  if (!fl_xim_ic)
2764
+    return;
2765
+
2766
+  XDestroyIC(fl_xim_ic);
2767
+  fl_xim_ic = NULL;
2768
+
2769
+  fl_xim_win = 0;
2770
+}
2771
+
2772
+extern Fl_Window *fl_xfocus;
2773
+
2774
+void fl_update_focus(void)
2775
+{
2776
+  Fl_Widget *focus;
2777
+
2778
+  focus = Fl::grab();
2779
+  if (!focus)
2780
+    focus = Fl::focus();
2781
+  if (!focus)
2782
+    return;
2783
+
2784
+  if (focus->simple_keyboard()) {
2785
+    fl_xim_deactivate();
2786
+  } else {
2787
+    // fl_xfocus should always be set if something has focus, but let's
2788
+    // play it safe
2789
+    if (!fl_xfocus || !fl_xid(fl_xfocus))
2790
+      return;
2791
+
2792
+    fl_xim_activate(fl_xid(fl_xfocus));
2793
+  }
2794
+}
2795
+
2796
 void fl_open_display() {
2797
   if (fl_display) return;
2798
 
2799
@@ -607,6 +683,9 @@
2800
   fl_MOTIF_WM_HINTS     = XInternAtom(d, "_MOTIF_WM_HINTS",     0);
2801
   TARGETS               = XInternAtom(d, "TARGETS",             0);
2802
   CLIPBOARD             = XInternAtom(d, "CLIPBOARD",           0);
2803
+  TIMESTAMP             = XInternAtom(d, "TIMESTAMP",           0);
2804
+  PRIMARY_TIMESTAMP     = XInternAtom(d, "PRIMARY_TIMESTAMP",   0);
2805
+  CLIPBOARD_TIMESTAMP   = XInternAtom(d, "CLIPBOARD_TIMESTAMP", 0);
2806
   fl_XdndAware          = XInternAtom(d, "XdndAware",           0);
2807
   fl_XdndSelection      = XInternAtom(d, "XdndSelection",       0);
2808
   fl_XdndEnter          = XInternAtom(d, "XdndEnter",           0);
2809
@@ -631,7 +710,9 @@
2810
   fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
2811
   fl_NET_WM_STATE       = XInternAtom(d, "_NET_WM_STATE",       0);
2812
   fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
2813
+  fl_NET_WM_FULLSCREEN_MONITORS = XInternAtom(d, "_NET_WM_FULLSCREEN_MONITORS", 0);
2814
   fl_NET_WORKAREA       = XInternAtom(d, "_NET_WORKAREA",       0);
2815
+  fl_NET_WM_ICON        = XInternAtom(d, "_NET_WM_ICON",        0);
2816
 
2817
   if (sizeof(Atom) < 4)
2818
     atom_bits = sizeof(Atom) * 8;
2819
@@ -653,6 +734,15 @@
2820
 #if !USE_COLORMAP
2821
   Fl::visual(FL_RGB);
2822
 #endif
2823
+
2824
+#if HAVE_XFIXES
2825
+  int error_base;
2826
+  if (XFixesQueryExtension(fl_display, &xfixes_event_base, &error_base))
2827
+    have_xfixes = true;
2828
+  else
2829
+    have_xfixes = false;
2830
+#endif
2831
+
2832
 #if USE_XRANDR
2833
   void *libxrandr_addr = dlopen("libXrandr.so.2", RTLD_LAZY);
2834
   if (!libxrandr_addr)  libxrandr_addr = dlopen("libXrandr.so", RTLD_LAZY);
2835
@@ -841,6 +931,102 @@
2836
 }
2837
 
2838
 ////////////////////////////////////////////////////////////////
2839
+// Code for tracking clipboard changes:
2840
+
2841
+static Time primary_timestamp = -1;
2842
+static Time clipboard_timestamp = -1;
2843
+
2844
+extern bool fl_clipboard_notify_empty(void);
2845
+extern void fl_trigger_clipboard_notify(int source);
2846
+
2847
+static void poll_clipboard_owner(void) {
2848
+  Window xid;
2849
+
2850
+#if HAVE_XFIXES
2851
+  // No polling needed with Xfixes
2852
+  if (have_xfixes)
2853
+    return;
2854
+#endif
2855
+
2856
+  // No one is interested, so no point polling
2857
+  if (fl_clipboard_notify_empty())
2858
+    return;
2859
+
2860
+  // We need a window for this to work
2861
+  if (!Fl::first_window())
2862
+    return;
2863
+  xid = fl_xid(Fl::first_window());
2864
+  if (!xid)
2865
+    return;
2866
+
2867
+  // Request an update of the selection time for both the primary and
2868
+  // clipboard selections. Magic continues when we get a SelectionNotify.
2869
+  if (!fl_i_own_selection[0])
2870
+    XConvertSelection(fl_display, XA_PRIMARY, TIMESTAMP, PRIMARY_TIMESTAMP,
2871
+                      xid, fl_event_time);
2872
+  if (!fl_i_own_selection[1])
2873
+    XConvertSelection(fl_display, CLIPBOARD, TIMESTAMP, CLIPBOARD_TIMESTAMP,
2874
+                      xid, fl_event_time);
2875
+}
2876
+
2877
+static void clipboard_timeout(void *data)
2878
+{
2879
+  // No one is interested, so stop polling
2880
+  if (fl_clipboard_notify_empty())
2881
+    return;
2882
+
2883
+  poll_clipboard_owner();
2884
+
2885
+  Fl::repeat_timeout(0.5, clipboard_timeout);
2886
+}
2887
+
2888
+static void handle_clipboard_timestamp(int clipboard, Time time)
2889
+{
2890
+  Time *timestamp;
2891
+
2892
+  timestamp = clipboard ? &clipboard_timestamp : &primary_timestamp;
2893
+
2894
+#if HAVE_XFIXES
2895
+  if (!have_xfixes)
2896
+#endif
2897
+  {
2898
+    // Initial scan, just store the value
2899
+    if (*timestamp == (Time)-1) {
2900
+      *timestamp = time;
2901
+      return;
2902
+    }
2903
+  }
2904
+
2905
+  // Same selection
2906
+  if (time == *timestamp)
2907
+    return;
2908
+
2909
+  *timestamp = time;
2910
+
2911
+  // Something happened! Let's tell someone!
2912
+  fl_trigger_clipboard_notify(clipboard);
2913
+}
2914
+
2915
+void fl_clipboard_notify_change() {
2916
+  // Reset the timestamps if we've going idle so that you don't
2917
+  // get a bogus immediate trigger next time they're activated.
2918
+  if (fl_clipboard_notify_empty()) {
2919
+    primary_timestamp = -1;
2920
+    clipboard_timestamp = -1;
2921
+  } else {
2922
+#if HAVE_XFIXES
2923
+    if (!have_xfixes)
2924
+#endif
2925
+    {
2926
+      poll_clipboard_owner();
2927
+
2928
+      if (!Fl::has_timeout(clipboard_timeout))
2929
+        Fl::add_timeout(0.5, clipboard_timeout);
2930
+    }
2931
+  }
2932
+}
2933
+
2934
+////////////////////////////////////////////////////////////////
2935
 
2936
 const XEvent* fl_xevent; // the current x event
2937
 ulong fl_event_time; // the last timestamp from an x event
2938
@@ -918,10 +1104,9 @@
2939
   XEvent xevent = thisevent;
2940
   fl_xevent = &thisevent;
2941
   Window xid = xevent.xany.window;
2942
-  static Window xim_win = 0;
2943
 
2944
   if (fl_xim_ic && xevent.type == DestroyNotify &&
2945
-        xid != xim_win && !fl_find(xid))
2946
+        xid != fl_xim_win && !fl_find(xid))
2947
   {
2948
     XIM xim_im;
2949
     xim_im = XOpenIM(fl_display, NULL, NULL, NULL);
2950
@@ -936,48 +1121,10 @@
2951
     return 0;
2952
   }
2953
 
2954
-  if (fl_xim_ic && (xevent.type == FocusIn))
2955
-  {
2956
-#define POOR_XIM
2957
-#ifdef POOR_XIM
2958
-        if (xim_win != xid)
2959
-        {
2960
-                xim_win  = xid;
2961
-                XDestroyIC(fl_xim_ic);
2962
-                fl_xim_ic = NULL;
2963
-                fl_new_ic();
2964
-                XSetICValues(fl_xim_ic,
2965
-                                XNFocusWindow, xevent.xclient.window,
2966
-                                XNClientWindow, xid,
2967
-                                NULL);
2968
-        }
2969
-        fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2970
-#else
2971
-    if (Fl::first_window() && Fl::first_window()->modal()) {
2972
-      Window x  = fl_xid(Fl::first_window());
2973
-      if (x != xim_win) {
2974
-        xim_win  = x;
2975
-        XSetICValues(fl_xim_ic,
2976
-                        XNFocusWindow, xim_win,
2977
-                        XNClientWindow, xim_win,
2978
-                        NULL);
2979
-        fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2980
-      }
2981
-    } else if (xim_win != xid && xid) {
2982
-      xim_win = xid;
2983
-      XSetICValues(fl_xim_ic,
2984
-                        XNFocusWindow, xevent.xclient.window,
2985
-                        XNClientWindow, xid,
2986
-                        //XNFocusWindow, xim_win,
2987
-                        //XNClientWindow, xim_win,
2988
-                        NULL);
2989
-      fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
2990
-    }
2991
-#endif
2992
+  if (fl_xim_ic) {
2993
+    if (XFilterEvent((XEvent *)&xevent, 0))
2994
+      return 1;
2995
   }
2996
-
2997
-  if ( XFilterEvent((XEvent *)&xevent, 0) )
2998
-      return(1);
2999
   
3000
 #if USE_XRANDR  
3001
   if( XRRUpdateConfiguration_f && xevent.type == randrEventBase + RRScreenChangeNotify) {
3002
@@ -1003,7 +1150,6 @@
3003
     return 0;
3004
 
3005
   case SelectionNotify: {
3006
-    if (!fl_selection_requestor) return 0;
3007
     static unsigned char* buffer = 0;
3008
     if (buffer) {XFree(buffer); buffer = 0;}
3009
     long bytesread = 0;
3010
@@ -1019,6 +1165,19 @@
3011
                              bytesread/4, 65536, 1, 0,
3012
                              &actual, &format, &count, &remaining,
3013
                              &portion)) break; // quit on error
3014
+
3015
+      if ((fl_xevent->xselection.property == PRIMARY_TIMESTAMP) ||
3016
+          (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)) {
3017
+        if (portion && format == 32 && count == 1) {
3018
+          Time t = *(unsigned int*)portion;
3019
+          if (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)
3020
+            handle_clipboard_timestamp(1, t);
3021
+          else
3022
+            handle_clipboard_timestamp(0, t);
3023
+        }
3024
+        return true;
3025
+      }
3026
+
3027
       if (actual == TARGETS || actual == XA_ATOM) {
3028
 	Atom type = XA_STRING;
3029
 	for (unsigned i = 0; i<count; i++) {
3030
@@ -1055,6 +1214,9 @@
3031
       buffer[bytesread] = 0;
3032
       convert_crlf(buffer, bytesread);
3033
     }
3034
+
3035
+    if (!fl_selection_requestor) return 0;
3036
+
3037
     Fl::e_text = buffer ? (char*)buffer : (char *)"";
3038
     Fl::e_length = bytesread;
3039
     int old_event = Fl::e_number;
3040
@@ -1075,6 +1237,7 @@
3041
   case SelectionClear: {
3042
     int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD;
3043
     fl_i_own_selection[clipboard] = 0;
3044
+    poll_clipboard_owner();
3045
     return 1;}
3046
 
3047
   case SelectionRequest: {
3048
@@ -1287,6 +1450,9 @@
3049
   case FocusIn:
3050
     if (fl_xim_ic) XSetICFocus(fl_xim_ic);
3051
     event = FL_FOCUS;
3052
+    // If the user has toggled from another application to this one,
3053
+    // then it's a good time to check for clipboard changes.
3054
+    poll_clipboard_owner();
3055
     break;
3056
 
3057
   case FocusOut:
3058
@@ -1327,15 +1493,15 @@
3059
         //static XComposeStatus compose;
3060
         len = XLookupString((XKeyEvent*)&(xevent.xkey),
3061
                              buffer, buffer_len, &keysym, 0/*&compose*/);
3062
-        if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets
3063
-          // force it to type a character (not sure if this ever is needed):
3064
-          // if (!len) {buffer[0] = char(keysym); len = 1;}
3065
-          len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
3066
-          if (len < 1) len = 1;
3067
-          // ignore all effects of shift on the keysyms, which makes it a lot
3068
-          // easier to program shortcuts and is Windoze-compatible:
3069
-          keysym = XKeycodeToKeysym(fl_display, keycode, 0);
3070
-        }
3071
+        // XLookupString() is only defined to return Latin-1 (although it
3072
+        // often gives you more). To be safe, use our own lookups based on
3073
+        // keysym.
3074
+        len = fl_utf8encode(XKeysymToUcs(keysym), buffer);
3075
+        if (len < 1)
3076
+          len = 1;
3077
+        // ignore all effects of shift on the keysyms, which makes it a lot
3078
+        // easier to program shortcuts and is Windoze-compatable:
3079
+        keysym = XKeycodeToKeysym(fl_display, keycode, 0);
3080
       }
3081
       // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not
3082
       //      set until set_event_xy() is called later...
3083
@@ -1655,6 +1821,25 @@
3084
     }
3085
   }
3086
 
3087
+#if HAVE_XFIXES
3088
+  switch (xevent.type - xfixes_event_base) {
3089
+  case XFixesSelectionNotify: {
3090
+    // Someone feeding us bogus events?
3091
+    if (!have_xfixes)
3092
+      return true;
3093
+
3094
+    XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)&xevent;
3095
+
3096
+    if ((selection_notify->selection == XA_PRIMARY) && !fl_i_own_selection[0])
3097
+      handle_clipboard_timestamp(0, selection_notify->selection_timestamp);
3098
+    else if ((selection_notify->selection == CLIPBOARD) && !fl_i_own_selection[1])
3099
+      handle_clipboard_timestamp(1, selection_notify->selection_timestamp);
3100
+
3101
+    return true;
3102
+    }
3103
+  }
3104
+#endif
3105
+
3106
   return Fl::handle(event, window);
3107
 }
3108
 
3109
@@ -1697,22 +1882,30 @@
3110
 #define _NET_WM_STATE_ADD           1  /* add/set property */
3111
 #define _NET_WM_STATE_TOGGLE        2  /* toggle property  */
3112
 
3113
-static void send_wm_state_event(Window wnd, int add, Atom prop) {
3114
+static void send_wm_event(Window wnd, Atom message,
3115
+                          unsigned long d0, unsigned long d1=0,
3116
+                          unsigned long d2=0, unsigned long d3=0,
3117
+                          unsigned long d4=0) {
3118
   XEvent e;
3119
   e.xany.type = ClientMessage;
3120
   e.xany.window = wnd;
3121
-  e.xclient.message_type = fl_NET_WM_STATE;
3122
+  e.xclient.message_type = message;
3123
   e.xclient.format = 32;
3124
-  e.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
3125
-  e.xclient.data.l[1] = prop;
3126
-  e.xclient.data.l[2] = 0;
3127
-  e.xclient.data.l[3] = 0;
3128
-  e.xclient.data.l[4] = 0;
3129
+  e.xclient.data.l[0] = d0;
3130
+  e.xclient.data.l[1] = d1;
3131
+  e.xclient.data.l[2] = d2;
3132
+  e.xclient.data.l[3] = d3;
3133
+  e.xclient.data.l[4] = d4;
3134
   XSendEvent(fl_display, RootWindow(fl_display, fl_screen),
3135
              0, SubstructureNotifyMask | SubstructureRedirectMask,
3136
              &e);
3137
 }
3138
 
3139
+static void send_wm_state_event(Window wnd, int add, Atom prop) {
3140
+  send_wm_event(wnd, fl_NET_WM_STATE,
3141
+                add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, prop);
3142
+}
3143
+
3144
 int Fl_X::ewmh_supported() {
3145
   static int result = -1;
3146
 
3147
@@ -1736,6 +1929,22 @@
3148
 /* Change an existing window to fullscreen */
3149
 void Fl_Window::fullscreen_x() {
3150
   if (Fl_X::ewmh_supported()) {
3151
+    int top, bottom, left, right;
3152
+
3153
+    top = fullscreen_screen_top;
3154
+    bottom = fullscreen_screen_bottom;
3155
+    left = fullscreen_screen_left;
3156
+    right = fullscreen_screen_right;
3157
+
3158
+    if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
3159
+      top = Fl::screen_num(x(), y(), w(), h());
3160
+      bottom = top;
3161
+      left = top;
3162
+      right = top;
3163
+    }
3164
+
3165
+    send_wm_event(fl_xid(this), fl_NET_WM_FULLSCREEN_MONITORS,
3166
+                  top, bottom, left, right);
3167
     send_wm_state_event(fl_xid(this), 1, fl_NET_WM_STATE_FULLSCREEN);
3168
   } else {
3169
     _set_fullscreen();
3170
@@ -1822,7 +2031,7 @@
3171
     // force the window to be on-screen.  Usually the X window manager
3172
     // does this, but a few don't, so we do it here for consistency:
3173
     int scr_x, scr_y, scr_w, scr_h;
3174
-    Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y);
3175
+    Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H);
3176
 
3177
     if (win->border()) {
3178
       // ensure border is on screen:
3179
@@ -1851,6 +2060,23 @@
3180
     return;
3181
   }
3182
 
3183
+  // Compute which screen(s) we should be on if we want to go fullscreen
3184
+  int fullscreen_top, fullscreen_bottom, fullscreen_left, fullscreen_right;
3185
+
3186
+  fullscreen_top = win->fullscreen_screen_top;
3187
+  fullscreen_bottom = win->fullscreen_screen_bottom;
3188
+  fullscreen_left = win->fullscreen_screen_left;
3189
+  fullscreen_right = win->fullscreen_screen_right;
3190
+
3191
+  if ((fullscreen_top < 0) || (fullscreen_bottom < 0) ||
3192
+      (fullscreen_left < 0) || (fullscreen_right < 0)) {
3193
+    fullscreen_top = Fl::screen_num(X, Y, W, H);
3194
+    fullscreen_bottom = fullscreen_top;
3195
+    fullscreen_left = fullscreen_top;
3196
+    fullscreen_right = fullscreen_top;
3197
+  }
3198
+
3199
+
3200
   ulong root = win->parent() ?
3201
     fl_xid(win->window()) : RootWindow(fl_display, fl_screen);
3202
 
3203
@@ -1874,9 +2100,17 @@
3204
   // border, and cannot grab without an existing window. Besides, 
3205
   // there is no clear_override(). 
3206
   if (win->flags() & Fl_Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
3207
+    int sx, sy, sw, sh;
3208
     attr.override_redirect = 1;
3209
     mask |= CWOverrideRedirect;
3210
-    Fl::screen_xywh(X, Y, W, H, X, Y, W, H);
3211
+    Fl::screen_xywh(sx, sy, sw, sh, fullscreen_left);
3212
+    X = sx;
3213
+    Fl::screen_xywh(sx, sy, sw, sh, fullscreen_right);
3214
+    W = sx + sw - X;
3215
+    Fl::screen_xywh(sx, sy, sw, sh, fullscreen_top);
3216
+    Y = sy;
3217
+    Fl::screen_xywh(sx, sy, sw, sh, fullscreen_bottom);
3218
+    H = sy + sh - Y;
3219
   }
3220
 
3221
   if (fl_background_pixel >= 0) {
3222
@@ -1929,6 +2163,12 @@
3223
       while (wp->parent()) wp = wp->window();
3224
       XSetTransientForHint(fl_display, xp->xid, fl_xid(wp));
3225
       if (!wp->visible()) showit = 0; // guess that wm will not show it
3226
+      if (win->modal()) {
3227
+        Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0);
3228
+        Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_MODAL", 0);
3229
+        XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32,
3230
+            PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1);
3231
+      }
3232
     }
3233
 
3234
     // Make sure that borderless windows do not show in the task bar
3235
@@ -1941,6 +2181,13 @@
3236
 
3237
     // If asked for, create fullscreen
3238
     if (win->flags() & Fl_Widget::FULLSCREEN && Fl_X::ewmh_supported()) {
3239
+      unsigned long data[4];
3240
+      data[0] = fullscreen_top;
3241
+      data[1] = fullscreen_bottom;
3242
+      data[2] = fullscreen_left;
3243
+      data[3] = fullscreen_right;
3244
+      XChangeProperty (fl_display, xp->xid, fl_NET_WM_FULLSCREEN_MONITORS, XA_ATOM, 32,
3245
+                       PropModeReplace, (unsigned char*) data, 4);
3246
       XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32,
3247
                        PropModeAppend, (unsigned char*) &fl_NET_WM_STATE_FULLSCREEN, 1);
3248
     }
3249
@@ -1959,12 +2206,14 @@
3250
       fl_show_iconic = 0;
3251
       showit = 0;
3252
     }
3253
-    if (win->icon()) {
3254
-      hints->icon_pixmap = (Pixmap)win->icon();
3255
+    if (win->icon_->legacy_icon) {
3256
+      hints->icon_pixmap = (Pixmap)win->icon_->legacy_icon;
3257
       hints->flags       |= IconPixmapHint;
3258
     }
3259
     XSetWMHints(fl_display, xp->xid, hints);
3260
     XFree(hints);
3261
+
3262
+    xp->set_icons();
3263
   }
3264
 
3265
   // set the window type for menu and tooltip windows to avoid animations (compiz)
3266
@@ -1974,6 +2223,16 @@
3267
     XChangeProperty(fl_display, xp->xid, net_wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&net_wm_type_kind, 1);
3268
   }
3269
 
3270
+#if HAVE_XFIXES
3271
+  // register for clipboard change notifications
3272
+  if (have_xfixes && !win->parent()) {
3273
+    XFixesSelectSelectionInput(fl_display, xp->xid, XA_PRIMARY,
3274
+                               XFixesSetSelectionOwnerNotifyMask);
3275
+    XFixesSelectSelectionInput(fl_display, xp->xid, CLIPBOARD,
3276
+                               XFixesSetSelectionOwnerNotifyMask);
3277
+  }
3278
+#endif
3279
+
3280
   XMapWindow(fl_display, xp->xid);
3281
   if (showit) {
3282
     win->set_visible();
3283
@@ -2073,6 +2332,181 @@
3284
 }
3285
 
3286
 ////////////////////////////////////////////////////////////////
3287
+
3288
+static unsigned long *default_net_wm_icons = 0L;
3289
+static size_t default_net_wm_icons_size = 0;
3290
+
3291
+void icons_to_property(const Fl_RGB_Image *icons[], int count,
3292
+                       unsigned long **property, size_t *len) {
3293
+  size_t sz;
3294
+  unsigned long *data;
3295
+
3296
+  sz = 0;
3297
+  for (int i = 0;i < count;i++)
3298
+    sz += 2 + icons[i]->w() * icons[i]->h();
3299
+
3300
+  // FIXME: Might want to sort the icons
3301
+
3302
+  *property = data = new unsigned long[sz];
3303
+  *len = sz;
3304
+
3305
+  for (int i = 0;i < count;i++) {
3306
+    const Fl_RGB_Image *image;
3307
+
3308
+    image = icons[i];
3309
+
3310
+    data[0] = image->w();
3311
+    data[1] = image->h();
3312
+    data += 2;
3313
+
3314
+    const uchar *in = (const uchar*)*image->data();
3315
+    for (int y = 0;y < image->h();y++) {
3316
+      for (int x = 0;x < image->w();x++) {
3317
+        switch (image->d()) {
3318
+        case 1:
3319
+          *data = ( 0xff<<24) | (in[0]<<16) | (in[0]<<8) | in[0];
3320
+          break;
3321
+        case 2:
3322
+          *data = (in[1]<<24) | (in[0]<<16) | (in[0]<<8) | in[0];
3323
+          break;
3324
+        case 3:
3325
+          *data = ( 0xff<<24) | (in[0]<<16) | (in[1]<<8) | in[2];
3326
+          break;
3327
+        case 4:
3328
+          *data = (in[3]<<24) | (in[0]<<16) | (in[1]<<8) | in[2];
3329
+          break;
3330
+        }
3331
+        in += image->d();
3332
+        data++;
3333
+      }
3334
+      in += image->ld();
3335
+    }
3336
+  }
3337
+}
3338
+
3339
+void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) {
3340
+  if (default_net_wm_icons) {
3341
+    delete [] default_net_wm_icons;
3342
+    default_net_wm_icons = 0L;
3343
+    default_net_wm_icons_size = 0;
3344
+  }
3345
+
3346
+  if (count > 0)
3347
+    icons_to_property(icons, count,
3348
+                      &default_net_wm_icons, &default_net_wm_icons_size);
3349
+}
3350
+
3351
+void Fl_X::set_icons() {
3352
+  unsigned long *net_wm_icons;
3353
+  size_t net_wm_icons_size;
3354
+
3355
+  if (w->icon_->count) {
3356
+    icons_to_property((const Fl_RGB_Image **)w->icon_->icons, w->icon_->count,
3357
+                      &net_wm_icons, &net_wm_icons_size);
3358
+  } else {
3359
+    net_wm_icons = default_net_wm_icons;
3360
+    net_wm_icons_size = default_net_wm_icons_size;
3361
+  }
3362
+
3363
+  XChangeProperty (fl_display, xid, fl_NET_WM_ICON, XA_CARDINAL, 32,
3364
+      PropModeReplace, (unsigned char*) net_wm_icons, net_wm_icons_size);
3365
+
3366
+  if (w->icon_->count) {
3367
+    delete [] net_wm_icons;
3368
+    net_wm_icons = 0L;
3369
+    net_wm_icons_size = 0;
3370
+  }
3371
+}
3372
+
3373
+////////////////////////////////////////////////////////////////
3374
+
3375
+int Fl_X::set_cursor(Fl_Cursor c) {
3376
+  unsigned int shape;
3377
+  Cursor xc;
3378
+
3379
+  switch (c) {
3380
+  case FL_CURSOR_ARROW:   shape = XC_left_ptr; break;
3381
+  case FL_CURSOR_CROSS:   shape = XC_tcross; break;
3382
+  case FL_CURSOR_WAIT:    shape = XC_watch; break;
3383
+  case FL_CURSOR_INSERT:  shape = XC_xterm; break;
3384
+  case FL_CURSOR_HAND:    shape = XC_hand2; break;
3385
+  case FL_CURSOR_HELP:    shape = XC_question_arrow; break;
3386
+  case FL_CURSOR_MOVE:    shape = XC_fleur; break;
3387
+  case FL_CURSOR_NS:      shape = XC_sb_v_double_arrow; break;
3388
+  case FL_CURSOR_WE:      shape = XC_sb_h_double_arrow; break;
3389
+  case FL_CURSOR_NE:      shape = XC_top_right_corner; break;
3390
+  case FL_CURSOR_N:       shape = XC_top_side; break;
3391
+  case FL_CURSOR_NW:      shape = XC_top_left_corner; break;
3392
+  case FL_CURSOR_E:       shape = XC_right_side; break;
3393
+  case FL_CURSOR_W:       shape = XC_left_side; break;
3394
+  case FL_CURSOR_SE:      shape = XC_bottom_right_corner; break;
3395
+  case FL_CURSOR_S:       shape = XC_bottom_side; break;
3396
+  case FL_CURSOR_SW:      shape = XC_bottom_left_corner; break;
3397
+  default:
3398
+    return 0;
3399
+  }
3400
+
3401
+  xc = XCreateFontCursor(fl_display, shape);
3402
+  XDefineCursor(fl_display, xid, xc);
3403
+  XFreeCursor(fl_display, xc);
3404
+
3405
+  return 1;
3406
+}
3407
+
3408
+int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
3409
+#if ! HAVE_XCURSOR
3410
+  return 0;
3411
+#else
3412
+  XcursorImage *cursor;
3413
+  Cursor xc;
3414
+
3415
+  if ((hotx < 0) || (hotx >= image->w()))
3416
+    return 0;
3417
+  if ((hoty < 0) || (hoty >= image->h()))
3418
+    return 0;
3419
+
3420
+  cursor = XcursorImageCreate(image->w(), image->h());
3421
+  if (!cursor)
3422
+    return 0;
3423
+
3424
+  const uchar *i = (const uchar*)*image->data();
3425
+  XcursorPixel *o = cursor->pixels;
3426
+  for (int y = 0;y < image->h();y++) {
3427
+    for (int x = 0;x < image->w();x++) {
3428
+      switch (image->d()) {
3429
+      case 1:
3430
+        *o = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
3431
+        break;
3432
+      case 2:
3433
+        *o = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0];
3434
+        break;
3435
+      case 3:
3436
+        *o = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
3437
+        break;
3438
+      case 4:
3439
+        *o = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2];
3440
+        break;
3441
+      }
3442
+      i += image->d();
3443
+      o++;
3444
+    }
3445
+    i += image->ld();
3446
+  }
3447
+
3448
+  cursor->xhot = hotx;
3449
+  cursor->yhot = hoty;
3450
+
3451
+  xc = XcursorImageLoadCursor(fl_display, cursor);
3452
+  XDefineCursor(fl_display, xid, xc);
3453
+  XFreeCursor(fl_display, xc);
3454
+
3455
+  XcursorImageDestroy(cursor);
3456
+
3457
+  return 1;
3458
+#endif
3459
+}
3460
+
3461
+////////////////////////////////////////////////////////////////
3462
 
3463
 // returns pointer to the filename, or null if name ends with '/'
3464
 const char *fl_filename_name(const char *name) {
3465
diff -Nur src/ps_image.cxx src/ps_image.cxx
3466
--- src/ps_image.cxx	2011-07-19 06:49:30.000000000 +0200
3467
+++ src/ps_image.cxx	2013-07-17 19:37:37.912343302 +0200
3468
@@ -185,72 +185,38 @@
3469
 
3470
 extern uchar **fl_mask_bitmap;
3471
 
3472
+struct callback_data {
3473
+  const uchar *data;
3474
+  int D, LD;
3475
+};
3476
 
3477
-void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
3478
-  double x = ix, y = iy, w = iw, h = ih;
3479
 
3480
-  if (D<3){ //mono
3481
-    draw_image_mono(data, ix, iy, iw, ih, D, LD);
3482
-    return;
3483
-  }
3484
+static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
3485
+  struct callback_data *cb_data;
3486
+  const uchar *curdata;
3487
 
3488
+  cb_data = (struct callback_data*)data;
3489
+  curdata = cb_data->data + x*cb_data->D + y*cb_data->LD;
3490
 
3491
-  int i,j, k;
3492
+  memcpy(buf, curdata, w*cb_data->D);
3493
+}
3494
 
3495
-  fprintf(output,"save\n");
3496
 
3497
-  const char * interpol;
3498
-  if (lang_level_>1){
3499
-    if (interpolate_)
3500
-      interpol="true";
3501
-    else
3502
-      interpol="false";
3503
-    if (mask && lang_level_>2)
3504
-      fprintf(output, "%g %g %g %g %i %i %i %i %s CIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol);
3505
-    else
3506
-      fprintf(output, "%g %g %g %g %i %i %s CII\n", x , y+h , w , -h , iw , ih, interpol);
3507
-  } else
3508
-    fprintf(output , "%g %g %g %g %i %i CI", x , y+h , w , -h , iw , ih);
3509
+void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
3510
+  if (D<3){ //mono
3511
+    draw_image_mono(data, ix, iy, iw, ih, D, LD);
3512
+    return;
3513
+  }
3514
 
3515
+  struct callback_data cb_data;
3516
 
3517
   if (!LD) LD = iw*D;
3518
-  uchar *curmask=mask;
3519
-
3520
-  for (j=0; j<ih;j++){
3521
-    if (mask){
3522
-
3523
-      for (k=0;k<my/ih;k++){
3524
-        for (i=0; i<((mx+7)/8);i++){
3525
-          if (!(i%80)) fprintf(output, "\n");
3526
-          fprintf(output, "%.2x",swap_byte(*curmask));
3527
-          curmask++;
3528
-        }
3529
-        fprintf(output,"\n");
3530
-      }
3531
-    }
3532
-    const uchar *curdata=data+j*LD;
3533
-    for (i=0 ; i<iw ; i++) {
3534
-      uchar r = curdata[0];
3535
-      uchar g =  curdata[1];
3536
-      uchar b =  curdata[2];
3537
-      if (lang_level_<3 && D>3) { //can do  mixing using bg_* colors)
3538
-        unsigned int a2 = curdata[3]; //must be int
3539
-        unsigned int a = 255-a2;
3540
-        r = (a2 * r + bg_r * a)/255;
3541
-        g = (a2 * g + bg_g * a)/255;
3542
-        b = (a2 * b + bg_b * a)/255;
3543
-      }
3544
-      if (!(i%40)) fprintf(output, "\n");
3545
-      fprintf(output, "%.2x%.2x%.2x", r, g, b);
3546
-      curdata +=D;
3547
-    }
3548
-    fprintf(output,"\n");
3549
-
3550
-  }
3551
-
3552
-  fprintf(output," >\nrestore\n" );
3553
 
3554
+  cb_data.data = data;
3555
+  cb_data.D = D;
3556
+  cb_data.LD = LD;
3557
 
3558
+  draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, D);
3559
 }
3560
 
3561
 void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) {
3562
@@ -325,6 +291,14 @@
3563
 	uchar g =  curdata[1];
3564
 	uchar b =  curdata[2];
3565
 
3566
+        if (lang_level_<3 && D>3) { //can do  mixing using bg_* colors)
3567
+          unsigned int a2 = curdata[3]; //must be int
3568
+          unsigned int a = 255-a2;
3569
+          r = (a2 * r + bg_r * a)/255;
3570
+          g = (a2 * g + bg_g * a)/255;
3571
+          b = (a2 * b + bg_b * a)/255;
3572
+        }
3573
+
3574
 	if (!(i%40)) 	fputs("\n", output);
3575
 	fprintf(output, "%.2x%.2x%.2x", r, g, b);
3576
 
3577
diff -Nur src/screen_xywh.cxx src/screen_xywh.cxx
3578
--- src/screen_xywh.cxx	2012-03-23 17:47:53.000000000 +0100
3579
+++ src/screen_xywh.cxx	2013-07-17 19:38:09.575341648 +0200
3580
@@ -215,21 +215,6 @@
3581
   return num_screens ? num_screens : 1;
3582
 }
3583
 
3584
-static int find_screen_with_point(int mx, int my) {
3585
-  int screen = 0;
3586
-  if (num_screens < 0) screen_init();
3587
-  
3588
-  for (int i = 0; i < num_screens; i ++) {
3589
-    int sx, sy, sw, sh;
3590
-    Fl::screen_xywh(sx, sy, sw, sh, i);
3591
-    if ((mx >= sx) && (mx < (sx+sw)) && (my >= sy) && (my < (sy+sh))) {
3592
-      screen = i;
3593
-      break;
3594
-    }
3595
-  }
3596
-  return screen;
3597
-}
3598
-
3599
 /**
3600
   Gets the bounding box of a screen
3601
   that contains the specified screen position \p mx, \p my
3602
@@ -237,7 +222,7 @@
3603
   \param[in] mx, my the absolute screen position
3604
 */
3605
 void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) {
3606
-  screen_xywh(X, Y, W, H, find_screen_with_point(mx, my));
3607
+  screen_xywh(X, Y, W, H, screen_num(mx, my));
3608
 }
3609
 
3610
 
3611
@@ -248,7 +233,7 @@
3612
  \param[in] mx, my the absolute screen position
3613
  */
3614
 void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) {
3615
-  screen_work_area(X, Y, W, H, find_screen_with_point(mx, my));
3616
+  screen_work_area(X, Y, W, H, screen_num(mx, my));
3617
 }
3618
 
3619
 /**
3620
@@ -321,6 +306,38 @@
3621
 #endif // WIN32
3622
 }
3623
 
3624
+/**
3625
+  Gets the screen bounding rect for the screen
3626
+  which intersects the most with the rectangle
3627
+  defined by \p mx, \p my, \p mw, \p mh.
3628
+  \param[out]  X,Y,W,H the corresponding screen bounding box
3629
+  \param[in] mx, my, mw, mh the rectangle to search for intersection with
3630
+  \see void screen_xywh(int &X, int &Y, int &W, int &H, int n)
3631
+  */
3632
+void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) {
3633
+  screen_xywh(X, Y, W, H, screen_num(mx, my, mw, mh));
3634
+}
3635
+
3636
+/**
3637
+  Gets the screen number of a screen
3638
+  that contains the specified screen position \p x, \p y
3639
+  \param[in] x, y the absolute screen position
3640
+*/
3641
+int Fl::screen_num(int x, int y) {
3642
+  int screen = 0;
3643
+  if (num_screens < 0) screen_init();
3644
+  
3645
+  for (int i = 0; i < num_screens; i ++) {
3646
+    int sx, sy, sw, sh;
3647
+    Fl::screen_xywh(sx, sy, sw, sh, i);
3648
+    if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) {
3649
+      screen = i;
3650
+      break;
3651
+    }
3652
+  }
3653
+  return screen;
3654
+}
3655
+
3656
 static inline float fl_intersection(int x1, int y1, int w1, int h1,
3657
                         int x2, int y2, int w2, int h2) {
3658
   if(x1+w1 < x2 || x2+w2 < x1 || y1+h1 < y2 || y2+h2 < y1)
3659
@@ -333,30 +350,27 @@
3660
 }
3661
 
3662
 /**
3663
-  Gets the screen bounding rect for the screen
3664
+  Gets the screen number for the screen
3665
   which intersects the most with the rectangle
3666
-  defined by \p mx, \p my, \p mw, \p mh.
3667
-  \param[out]  X,Y,W,H the corresponding screen bounding box
3668
-  \param[in] mx, my, mw, mh the rectangle to search for intersection with
3669
-  \see void screen_xywh(int &X, int &Y, int &W, int &H, int n)
3670
+  defined by \p x, \p y, \p w, \p h.
3671
+  \param[in] x, y, w, h the rectangle to search for intersection with
3672
   */
3673
-void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) {
3674
+int Fl::screen_num(int x, int y, int w, int h) {
3675
   int best_screen = 0;
3676
   float best_intersection = 0.;
3677
   for(int i = 0; i < Fl::screen_count(); i++) {
3678
     int sx, sy, sw, sh;
3679
     Fl::screen_xywh(sx, sy, sw, sh, i);
3680
-    float sintersection = fl_intersection(mx, my, mw, mh, sx, sy, sw, sh);
3681
+    float sintersection = fl_intersection(x, y, w, h, sx, sy, sw, sh);
3682
     if(sintersection > best_intersection) {
3683
       best_screen = i;
3684
       best_intersection = sintersection;
3685
     }
3686
   }
3687
-  screen_xywh(X, Y, W, H, best_screen);
3688
+  return best_screen;
3689
 }
3690
 
3691
 
3692
-
3693
 /**
3694
  Gets the screen resolution in dots-per-inch for the given screen.
3695
  \param[out]  h, v  horizontal and vertical resolution
3696
diff -Nur src/xutf8/imKStoUCS.c src/xutf8/imKStoUCS.c
3697
--- src/xutf8/imKStoUCS.c	2009-03-13 23:43:43.000000000 +0100
3698
+++ src/xutf8/imKStoUCS.c	2013-07-17 19:37:07.412344891 +0200
3699
@@ -266,6 +266,12 @@
3700
     0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac                          /* 0x20a8-0x20af */
3701
 };
3702
 
3703
+static unsigned short const keysym_to_unicode_fe50_fe60[] = {
3704
+    0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0306, 0x0307, 0x0308, /* 0xfe50-0xfe57 */
3705
+    0x030a, 0x030b, 0x030c, 0x0327, 0x0328, 0x1da5, 0x3099, 0x309a, /* 0xfe58-0xfe5f */
3706
+    0x0323                                                          /* 0xfe60-0xfe67 */
3707
+};
3708
+
3709
 unsigned int
3710
 KeySymToUcs4(KeySym keysym)
3711
 {
3712
@@ -315,6 +321,8 @@
3713
 	return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
3714
     else if (keysym > 0x209f && keysym < 0x20ad)
3715
 	return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
3716
+    else if (keysym > 0xfe4f && keysym < 0xfe61)
3717
+	return keysym_to_unicode_fe50_fe60[keysym - 0xfe50];
3718
     else 
3719
 	return 0;
3720
 }
3721
diff -Nur test/cursor.cxx test/cursor.cxx
3722
--- test/cursor.cxx	2011-07-19 06:49:30.000000000 +0200
3723
+++ test/cursor.cxx	2013-07-17 19:37:45.796342890 +0200
3724
@@ -23,8 +23,6 @@
3725
 #include <FL/fl_draw.H>
3726
 #include <FL/Fl_Box.H>
3727
 
3728
-Fl_Color fg = FL_BLACK;
3729
-Fl_Color bg = FL_WHITE;
3730
 Fl_Cursor cursor = FL_CURSOR_DEFAULT;
3731
 
3732
 Fl_Hor_Value_Slider *cursor_slider;
3733
@@ -32,7 +30,7 @@
3734
 void choice_cb(Fl_Widget *, void *v) {
3735
   cursor = (Fl_Cursor)(fl_intptr_t)v;
3736
   cursor_slider->value(cursor);
3737
-  fl_cursor(cursor,fg,bg);
3738
+  fl_cursor(cursor);
3739
 }
3740
 
3741
 Fl_Menu_Item choices[] = {
3742
@@ -48,8 +46,6 @@
3743
   {"FL_CURSOR_WE",0,choice_cb,(void*)FL_CURSOR_WE},
3744
   {"FL_CURSOR_NWSE",0,choice_cb,(void*)FL_CURSOR_NWSE},
3745
   {"FL_CURSOR_NESW",0,choice_cb,(void*)FL_CURSOR_NESW},
3746
-  {"FL_CURSOR_NONE",0,choice_cb,(void*)FL_CURSOR_NONE},
3747
-#if 0
3748
   {"FL_CURSOR_N",0,choice_cb,(void*)FL_CURSOR_N},
3749
   {"FL_CURSOR_NE",0,choice_cb,(void*)FL_CURSOR_NE},
3750
   {"FL_CURSOR_E",0,choice_cb,(void*)FL_CURSOR_E},
3751
@@ -58,26 +54,14 @@
3752
   {"FL_CURSOR_SW",0,choice_cb,(void*)FL_CURSOR_SW},
3753
   {"FL_CURSOR_W",0,choice_cb,(void*)FL_CURSOR_W},
3754
   {"FL_CURSOR_NW",0,choice_cb,(void*)FL_CURSOR_NW},
3755
-#endif
3756
+  {"FL_CURSOR_NONE",0,choice_cb,(void*)FL_CURSOR_NONE},
3757
   {0}
3758
 };
3759
 
3760
 void setcursor(Fl_Widget *o, void *) {
3761
   Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3762
   cursor = Fl_Cursor((int)slider->value());
3763
-  fl_cursor(cursor,fg,bg);
3764
-}
3765
-
3766
-void setfg(Fl_Widget *o, void *) {
3767
-  Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3768
-  fg = Fl_Color((int)slider->value());
3769
-  fl_cursor(cursor,fg,bg);
3770
-}
3771
-
3772
-void setbg(Fl_Widget *o, void *) {
3773
-  Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
3774
-  bg = Fl_Color((int)slider->value());
3775
-  fl_cursor(cursor,fg,bg);
3776
+  fl_cursor(cursor);
3777
 }
3778
 
3779
 // draw the label without any ^C or \nnn conversions:
3780
@@ -103,29 +87,11 @@
3781
   slider1.align(FL_ALIGN_LEFT);
3782
   slider1.step(1);
3783
   slider1.precision(0);
3784
-  slider1.bounds(0,100);
3785
+  slider1.bounds(0,255);
3786
   slider1.value(0);
3787
   slider1.callback(setcursor);
3788
   slider1.value(cursor);
3789
 
3790
-  Fl_Hor_Value_Slider slider2(80,220,310,30,"fgcolor:");
3791
-  slider2.align(FL_ALIGN_LEFT);
3792
-  slider2.step(1);
3793
-  slider2.precision(0);
3794
-  slider2.bounds(0,255);
3795
-  slider2.value(0);
3796
-  slider2.callback(setfg);
3797
-  slider2.value(fg);
3798
-
3799
-  Fl_Hor_Value_Slider slider3(80,260,310,30,"bgcolor:");
3800
-  slider3.align(FL_ALIGN_LEFT);
3801
-  slider3.step(1);
3802
-  slider3.precision(0);
3803
-  slider3.bounds(0,255);
3804
-  slider3.value(0);
3805
-  slider3.callback(setbg);
3806
-  slider3.value(bg);
3807
-
3808
 #if 0
3809
   // draw the manual's diagram of cursors...
3810
   window.size(400,800);
3811
diff -Nur test/fullscreen.cxx test/fullscreen.cxx
3812
--- test/fullscreen.cxx	2012-06-14 17:09:46.000000000 +0200
3813
+++ test/fullscreen.cxx	2013-07-17 19:38:17.327341239 +0200
3814
@@ -127,7 +127,7 @@
3815
   fullscreen_window(int W, int H, const char *t=0);
3816
   int handle (int e);
3817
   Fl_Toggle_Light_Button *b3;
3818
-
3819
+  Fl_Toggle_Light_Button *b4;
3820
 };
3821
 
3822
 fullscreen_window::fullscreen_window(int W, int H, const char *t) : Fl_Single_Window(W, H, t) { 
3823
@@ -170,23 +170,54 @@
3824
 #endif
3825
 }
3826
 
3827
-int px,py,pw,ph;
3828
 Fl_Button *border_button;
3829
 void fullscreen_cb(Fl_Widget *o, void *p) {
3830
   Fl_Window *w = (Fl_Window *)p;
3831
   int d = ((Fl_Button *)o)->value();
3832
   if (d) {
3833
-    px = w->x();
3834
-    py = w->y();
3835
-    pw = w->w();
3836
-    ph = w->h();
3837
+    if (((fullscreen_window*)w)->b4->value()) {
3838
+      int top, bottom, left, right;
3839
+      int top_y, bottom_y, left_x, right_x;
3840
+
3841
+      int sx, sy, sw, sh;
3842
+
3843
+      top = bottom = left = right = 0;
3844
+
3845
+      Fl::screen_xywh(sx, sy, sw, sh, 0);
3846
+      top_y = sy;
3847
+      bottom_y = sy + sh;
3848
+      left_x = sx;
3849
+      right_x = sx + sw;
3850
+
3851
+      for (int i = 1;i < Fl::screen_count();i++) {
3852
+        Fl::screen_xywh(sx, sy, sw, sh, i);
3853
+        if (sy < top_y) {
3854
+          top = i;
3855
+          top_y = sy;
3856
+        }
3857
+        if ((sy + sh) > bottom_y) {
3858
+          bottom = i;
3859
+          bottom_y = sy + sh;
3860
+        }
3861
+        if (sx < left_x) {
3862
+          left = i;
3863
+          left_x = sx;
3864
+        }
3865
+        if ((sx + sw) > right_x) {
3866
+          right = i;
3867
+          right_x = sx + sw;
3868
+        }
3869
+      }
3870
+
3871
+      w->fullscreen_screens(top, bottom, left, right);
3872
+    } else {
3873
+      w->fullscreen_screens(-1, -1, -1, -1);
3874
+    }
3875
     w->fullscreen();
3876
-    w->override();
3877
 #ifndef WIN32 // update our border state in case border was turned off
3878
     border_button->value(w->border());
3879
 #endif
3880
   } else {
3881
-    //w->fullscreen_off(px,py,pw,ph);
3882
     w->fullscreen_off();
3883
   }
3884
 }
3885
@@ -219,7 +250,7 @@
3886
   exit(0);
3887
 }
3888
 
3889
-#define NUMB 7
3890
+#define NUMB 8
3891
 
3892
 int twowindow = 0;
3893
 int initfull = 0;
3894
@@ -284,6 +315,9 @@
3895
   window.b3->callback(fullscreen_cb,w);
3896
   y+=30;
3897
 
3898
+  window.b4 = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"All Screens");
3899
+  y+=30;
3900
+
3901
   Fl_Button eb(50,y,window.w()-60,30,"Exit");
3902
   eb.callback(exit_cb);
3903
   y+=30;
(-)x11-toolkits/fltk/files/patch-src_Fl_x.cxx (-12 / +11 lines)
Lines 1-26 Link Here
1
Index: src/Fl_x.cxx
1
--- src/Fl_x.cx.orig	2013-09-10 18:36:35.000000000 +0900
2
===================================================================
2
+++ src/Fl_x.cxx	2013-09-10 18:39:55.000000000 +0900
3
--- src/Fl_x.cxx	(revision 9749)
3
@@ -2099,7 +2099,7 @@
4
+++ src/Fl_x.cxx	(working copy)
5
@@ -1873,7 +1873,7 @@
6
   // since we do not want save_under, do not want to turn off the
4
   // since we do not want save_under, do not want to turn off the
7
   // border, and cannot grab without an existing window. Besides, 
5
   // border, and cannot grab without an existing window. Besides, 
8
   // there is no clear_override(). 
6
   // there is no clear_override(). 
9
-  if (win->flags() & Fl_Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
7
-  if (win->flags() & Fl_Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
10
+  if (win->fullscreen_active() && !Fl_X::ewmh_supported()) {
8
+  if (win->fullscreen_active() && !Fl_X::ewmh_supported()) {
9
     int sx, sy, sw, sh;
11
     attr.override_redirect = 1;
10
     attr.override_redirect = 1;
12
     mask |= CWOverrideRedirect;
11
     mask |= CWOverrideRedirect;
13
     Fl::screen_xywh(X, Y, W, H, X, Y, W, H);
12
@@ -2180,7 +2180,7 @@
14
@@ -1940,7 +1940,7 @@
15
     }
13
     }
16
 
14
 
17
     // If asked for, create fullscreen
15
     // If asked for, create fullscreen
18
-    if (win->flags() & Fl_Widget::FULLSCREEN && Fl_X::ewmh_supported()) {
16
-    if (win->flags() & Fl_Widget::FULLSCREEN && Fl_X::ewmh_supported()) {
19
+    if (win->fullscreen_active() && Fl_X::ewmh_supported()) {
17
+    if (win->fullscreen_active() && !Fl_X::ewmh_supported()) {
20
       XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32,
18
       unsigned long data[4];
21
                        PropModeAppend, (unsigned char*) &fl_NET_WM_STATE_FULLSCREEN, 1);
19
       data[0] = fullscreen_top;
22
     }
20
       data[1] = fullscreen_bottom;
23
@@ -1984,7 +1984,7 @@
21
@@ -2243,7 +2243,7 @@
24
   }
22
   }
25
 
23
 
26
   // non-EWMH fullscreen case, need grab
24
   // non-EWMH fullscreen case, need grab
Lines 28-30 Link Here
28
+  if (win->fullscreen_active() && !Fl_X::ewmh_supported()) {
26
+  if (win->fullscreen_active() && !Fl_X::ewmh_supported()) {
29
     XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync, fl_event_time);
27
     XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync, fl_event_time);
30
   }
28
   }
29
 

Return to bug 182006