Rex Dieter f272280
diff -up fltk-1.3.2/CMakeLists.txt.clp-x11 fltk-1.3.2/CMakeLists.txt
Rex Dieter f272280
--- fltk-1.3.2/CMakeLists.txt.clp-x11	2012-09-13 16:19:01.000000000 +0200
Rex Dieter f272280
+++ fltk-1.3.2/CMakeLists.txt	2013-01-30 15:56:25.810663430 +0100
Rex Dieter f272280
@@ -515,6 +515,20 @@ else()
Rex Dieter f272280
 endif(OPTION_USE_XINERAMA)
Rex Dieter f272280
 
Rex Dieter f272280
 #######################################################################
Rex Dieter f272280
+if(X11_Xfixes_FOUND)
Rex Dieter f272280
+   option(OPTION_USE_XFIXES "use lib XFIXES" ON)
Rex Dieter f272280
+endif(X11_Xfixes_FOUND)
Rex Dieter f272280
+
Rex Dieter f272280
+if(OPTION_USE_XFIXES)
Rex Dieter f272280
+   set(HAVE_XFIXES ${X11_Xfixes_FOUND})
Rex Dieter f272280
+   include_directories(${X11_Xfixes_INCLUDE_PATH})
Rex Dieter f272280
+   list(APPEND FLTK_LDLIBS -lXfixes)
Rex Dieter f272280
+   set(FLTK_XFIXES_FOUND TRUE)
Rex Dieter f272280
+else()
Rex Dieter f272280
+   set(FLTK_XFIXES_FOUND FALSE)
Rex Dieter f272280
+endif(OPTION_USE_XFIXES)
Rex Dieter f272280
+
Rex Dieter f272280
+#######################################################################
Rex Dieter f272280
 if(X11_Xft_FOUND)
Rex Dieter f272280
    option(OPTION_USE_XFT "use lib Xft" ON)
Rex Dieter f272280
 endif(X11_Xft_FOUND)
Rex Dieter f272280
diff -up fltk-1.3.2/configh.cmake.in.clp-x11 fltk-1.3.2/configh.cmake.in
Rex Dieter f272280
--- fltk-1.3.2/configh.cmake.in.clp-x11	2011-07-19 06:49:30.000000000 +0200
Rex Dieter f272280
+++ fltk-1.3.2/configh.cmake.in	2013-01-30 15:56:25.810663430 +0100
Rex Dieter f272280
@@ -108,6 +108,14 @@
Rex Dieter f272280
 #define USE_XDBE HAVE_XDBE
Rex Dieter f272280
 
Rex Dieter f272280
 /*
Rex Dieter f272280
+ * HAVE_XFIXES:
Rex Dieter f272280
+ *
Rex Dieter f272280
+ * Do we have the X fixes extension?
Rex Dieter f272280
+ */
Rex Dieter f272280
+
Rex Dieter f272280
+#cmakedefine01 HAVE_XFIXES
Rex Dieter f272280
+
Rex Dieter f272280
+/*
Rex Dieter f272280
  * __APPLE_QUARTZ__:
Rex Dieter f272280
  *
Rex Dieter f272280
  * If __APPLE_QUARTZ__ is defined, FLTK will be
Rex Dieter f272280
diff -up fltk-1.3.2/configh.in.clp-x11 fltk-1.3.2/configh.in
Rex Dieter f272280
--- fltk-1.3.2/configh.in.clp-x11	2011-10-04 11:21:47.000000000 +0200
Rex Dieter f272280
+++ fltk-1.3.2/configh.in	2013-01-30 15:56:25.810663430 +0100
Rex Dieter f272280
@@ -108,6 +108,14 @@
Rex Dieter f272280
 #define USE_XDBE HAVE_XDBE
Rex Dieter f272280
 
Rex Dieter f272280
 /*
Rex Dieter f272280
+ * HAVE_XFIXES:
Rex Dieter f272280
+ *
Rex Dieter f272280
+ * Do we have the X fixes extension?
Rex Dieter f272280
+ */
Rex Dieter f272280
+
Rex Dieter f272280
+#define HAVE_XFIXES 0
Rex Dieter f272280
+
Rex Dieter f272280
+/*
Rex Dieter f272280
  * __APPLE_QUARTZ__:
Rex Dieter f272280
  *
Rex Dieter f272280
  * All Apple implementations are now based on Quartz and Cocoa,
Rex Dieter f272280
diff -up fltk-1.3.2/configure.in.clp-x11 fltk-1.3.2/configure.in
Rex Dieter f272280
--- fltk-1.3.2/configure.in.clp-x11	2013-01-30 15:56:25.802663573 +0100
Rex Dieter f272280
+++ fltk-1.3.2/configure.in	2013-01-30 15:56:25.810663430 +0100
Rex Dieter f272280
@@ -999,6 +999,16 @@ case $uname_GUI in
Rex Dieter f272280
 		LIBS="-lXext $LIBS")
Rex Dieter f272280
 	fi
Rex Dieter f272280
 
Rex Dieter f272280
+	dnl Check for the Xfixes extension unless disabled...
Rex Dieter f272280
+        AC_ARG_ENABLE(xfixes, [  --enable-xfixes       turn on Xfixes support [default=yes]])
Rex Dieter f272280
+
Rex Dieter f272280
+	if test x$enable_xfixes != xno; then
Rex Dieter f272280
+	    AC_CHECK_HEADER(X11/extensions/Xfixes.h, AC_DEFINE(HAVE_XFIXES),,
Rex Dieter f272280
+	        [#include <X11/Xlib.h>])
Rex Dieter f272280
+	    AC_CHECK_LIB(Xfixes, XFixesQueryExtension,
Rex Dieter f272280
+		LIBS="-lXfixes $LIBS")
Rex Dieter f272280
+	fi
Rex Dieter f272280
+
Rex Dieter f272280
 	dnl Check for overlay visuals...
Rex Dieter f272280
 	AC_PATH_PROG(XPROP, xprop)
Rex Dieter f272280
 	AC_CACHE_CHECK(for X overlay visuals, ac_cv_have_overlay,
Rex Dieter f272280
diff -up fltk-1.3.2/fluid/CMakeLists.txt.clp-x11 fltk-1.3.2/fluid/CMakeLists.txt
Rex Dieter f272280
diff -up fltk-1.3.2/src/CMakeLists.txt.clp-x11 fltk-1.3.2/src/CMakeLists.txt
Rex Dieter f272280
--- fltk-1.3.2/src/CMakeLists.txt.clp-x11	2013-01-30 16:06:00.785430590 +0100
Rex Dieter f272280
+++ fltk-1.3.2/src/CMakeLists.txt	2013-01-30 16:06:17.883126642 +0100
Rex Dieter f272280
@@ -243,6 +243,10 @@ if(HAVE_XINERAMA)
Rex Dieter f272280
    target_link_libraries(fltk ${X11_Xinerama_LIB})
Rex Dieter f272280
 endif(HAVE_XINERAMA)
Rex Dieter f272280
 
Rex Dieter f272280
+if(HAVE_XFIXES)
Rex Dieter f272280
+   target_link_libraries(fltk ${X11_Xfixes_LIB})
Rex Dieter f272280
+endif(HAVE_XFIXES)
Rex Dieter f272280
+
Rex Dieter f272280
 if(USE_XFT)
Rex Dieter f272280
    target_link_libraries(fltk ${X11_Xft_LIB})
Rex Dieter f272280
 endif(USE_XFT)
Rex Dieter f272280
diff -up fltk-1.3.2/src/Fl_x.cxx.clp-x11 fltk-1.3.2/src/Fl_x.cxx
Rex Dieter f272280
--- fltk-1.3.2/src/Fl_x.cxx.clp-x11	2013-01-30 15:56:25.793663733 +0100
Rex Dieter f272280
+++ fltk-1.3.2/src/Fl_x.cxx	2013-01-30 16:03:37.355981103 +0100
Rex Dieter f272280
@@ -53,6 +53,12 @@ static XRRUpdateConfiguration_type XRRUp
Rex Dieter f272280
 static int randrEventBase;                  // base of RandR-defined events
Rex Dieter f272280
 #endif
Rex Dieter f272280
 
Rex Dieter f272280
+#  if HAVE_XFIXES
Rex Dieter f272280
+#  include <X11/extensions/Xfixes.h>
Rex Dieter f272280
+static int xfixes_event_base = 0;
Rex Dieter f272280
+static bool have_xfixes = false;
Rex Dieter f272280
+#  endif
Rex Dieter f272280
+
Rex Dieter f272280
 static Fl_Xlib_Graphics_Driver fl_xlib_driver;
Rex Dieter f272280
 static Fl_Display_Device fl_xlib_display(&fl_xlib_driver);
Rex Dieter f272280
 Fl_Display_Device *Fl_Display_Device::_display = &fl_xlib_display;// the platform display
Rex Dieter f272280
@@ -307,6 +313,9 @@ static Atom WM_PROTOCOLS;
Rex Dieter f272280
 static Atom fl_MOTIF_WM_HINTS;
Rex Dieter f272280
 static Atom TARGETS;
Rex Dieter f272280
 static Atom CLIPBOARD;
Rex Dieter f272280
+static Atom TIMESTAMP;
Rex Dieter f272280
+static Atom PRIMARY_TIMESTAMP;
Rex Dieter f272280
+static Atom CLIPBOARD_TIMESTAMP;
Rex Dieter f272280
 Atom fl_XdndAware;
Rex Dieter f272280
 Atom fl_XdndSelection;
Rex Dieter f272280
 Atom fl_XdndEnter;
Rex Dieter f272280
@@ -667,6 +676,9 @@ void fl_open_display(Display* d) {
Rex Dieter f272280
   fl_MOTIF_WM_HINTS     = XInternAtom(d, "_MOTIF_WM_HINTS",     0);
Rex Dieter f272280
   TARGETS               = XInternAtom(d, "TARGETS",             0);
Rex Dieter f272280
   CLIPBOARD             = XInternAtom(d, "CLIPBOARD",           0);
Rex Dieter f272280
+  TIMESTAMP             = XInternAtom(d, "TIMESTAMP",           0);
Rex Dieter f272280
+  PRIMARY_TIMESTAMP     = XInternAtom(d, "PRIMARY_TIMESTAMP",   0);
Rex Dieter f272280
+  CLIPBOARD_TIMESTAMP   = XInternAtom(d, "CLIPBOARD_TIMESTAMP", 0);
Rex Dieter f272280
   fl_XdndAware          = XInternAtom(d, "XdndAware",           0);
Rex Dieter f272280
   fl_XdndSelection      = XInternAtom(d, "XdndSelection",       0);
Rex Dieter f272280
   fl_XdndEnter          = XInternAtom(d, "XdndEnter",           0);
Rex Dieter f272280
@@ -713,6 +725,15 @@ void fl_open_display(Display* d) {
Rex Dieter f272280
 #if !USE_COLORMAP
Rex Dieter f272280
   Fl::visual(FL_RGB);
Rex Dieter f272280
 #endif
Rex Dieter f272280
+
Rex Dieter f272280
+#if HAVE_XFIXES
Rex Dieter f272280
+  int error_base;
Rex Dieter f272280
+  if (XFixesQueryExtension(fl_display, &xfixes_event_base, &error_base))
Rex Dieter f272280
+    have_xfixes = true;
Rex Dieter f272280
+  else
Rex Dieter f272280
+    have_xfixes = false;
Rex Dieter f272280
+#endif
Rex Dieter f272280
+
Rex Dieter f272280
 #if USE_XRANDR
Rex Dieter f272280
   void *libxrandr_addr = dlopen("libXrandr.so.2", RTLD_LAZY);
Rex Dieter f272280
   if (!libxrandr_addr)  libxrandr_addr = dlopen("libXrandr.so", RTLD_LAZY);
Rex Dieter f272280
@@ -901,6 +922,107 @@ void Fl::copy(const char *stuff, int len
Rex Dieter f272280
 }
Rex Dieter f272280
 
Rex Dieter f272280
 ////////////////////////////////////////////////////////////////
Rex Dieter f272280
+// Code for tracking clipboard changes:
Rex Dieter f272280
+
Rex Dieter f272280
+static Time primary_timestamp = -1;
Rex Dieter f272280
+static Time clipboard_timestamp = -1;
Rex Dieter f272280
+
Rex Dieter f272280
+extern bool fl_clipboard_notify_empty(void);
Rex Dieter f272280
+extern void fl_trigger_clipboard_notify(int source);
Rex Dieter f272280
+
Rex Dieter f272280
+static void poll_clipboard_owner(void) {
Rex Dieter f272280
+  Window xid;
Rex Dieter f272280
+
Rex Dieter f272280
+#if HAVE_XFIXES
Rex Dieter f272280
+  // No polling needed with Xfixes
Rex Dieter f272280
+  if (have_xfixes)
Rex Dieter f272280
+    return;
Rex Dieter f272280
+#endif
Rex Dieter f272280
+
Rex Dieter f272280
+  // No one is interested, so no point polling
Rex Dieter f272280
+  if (fl_clipboard_notify_empty())
Rex Dieter f272280
+    return;
Rex Dieter f272280
+
Rex Dieter f272280
+  // We need a window for this to work
Rex Dieter f272280
+  if (!Fl::first_window())
Rex Dieter f272280
+    return;
Rex Dieter f272280
+  xid = fl_xid(Fl::first_window());
Rex Dieter f272280
+  if (!xid)
Rex Dieter f272280
+    return;
Rex Dieter f272280
+
Rex Dieter f272280
+  // Request an update of the selection time for both the primary and
Rex Dieter f272280
+  // clipboard selections. Magic continues when we get a SelectionNotify.
Rex Dieter f272280
+  if (!fl_i_own_selection[0])
Rex Dieter f272280
+    XConvertSelection(fl_display, XA_PRIMARY, TIMESTAMP, PRIMARY_TIMESTAMP,
Rex Dieter f272280
+                      xid, fl_event_time);
Rex Dieter f272280
+  if (!fl_i_own_selection[1])
Rex Dieter f272280
+    XConvertSelection(fl_display, CLIPBOARD, TIMESTAMP, CLIPBOARD_TIMESTAMP,
Rex Dieter f272280
+                      xid, fl_event_time);
Rex Dieter f272280
+}
Rex Dieter f272280
+
Rex Dieter f272280
+static void clipboard_timeout(void *data)
Rex Dieter f272280
+{
Rex Dieter f272280
+  // No one is interested, so stop polling
Rex Dieter f272280
+  if (fl_clipboard_notify_empty())
Rex Dieter f272280
+    return;
Rex Dieter f272280
+
Rex Dieter f272280
+  poll_clipboard_owner();
Rex Dieter f272280
+
Rex Dieter f272280
+  Fl::repeat_timeout(0.5, clipboard_timeout);
Rex Dieter f272280
+}
Rex Dieter f272280
+
Rex Dieter f272280
+static void handle_clipboard_timestamp(int clipboard, Time time)
Rex Dieter f272280
+{
Rex Dieter f272280
+  Time *timestamp;
Rex Dieter f272280
+
Rex Dieter f272280
+  timestamp = clipboard ? &clipboard_timestamp : &primary_timestamp;
Rex Dieter f272280
+
Rex Dieter f272280
+#if HAVE_XFIXES
Rex Dieter f272280
+  if (!have_xfixes)
Rex Dieter f272280
+#endif
Rex Dieter f272280
+  {
Rex Dieter f272280
+    // Initial scan, just store the value
Rex Dieter f272280
+    if (*timestamp == (Time)-1) {
Rex Dieter f272280
+      *timestamp = time;
Rex Dieter f272280
+      return;
Rex Dieter f272280
+    }
Rex Dieter f272280
+  }
Rex Dieter f272280
+
Rex Dieter f272280
+  // Same selection
Rex Dieter f272280
+  if (time == *timestamp)
Rex Dieter f272280
+    return;
Rex Dieter f272280
+
Rex Dieter f272280
+  *timestamp = time;
Rex Dieter f272280
+
Rex Dieter f272280
+  // The clipboard change is the event that caused us to request
Rex Dieter f272280
+  // the clipboard data, so use that time as the latest event.
Rex Dieter f272280
+  if (time > fl_event_time)
Rex Dieter f272280
+    fl_event_time = time;
Rex Dieter f272280
+
Rex Dieter f272280
+  // Something happened! Let's tell someone!
Rex Dieter f272280
+  fl_trigger_clipboard_notify(clipboard);
Rex Dieter f272280
+}
Rex Dieter f272280
+
Rex Dieter f272280
+void fl_clipboard_notify_change() {
Rex Dieter f272280
+  // Reset the timestamps if we've going idle so that you don't
Rex Dieter f272280
+  // get a bogus immediate trigger next time they're activated.
Rex Dieter f272280
+  if (fl_clipboard_notify_empty()) {
Rex Dieter f272280
+    primary_timestamp = -1;
Rex Dieter f272280
+    clipboard_timestamp = -1;
Rex Dieter f272280
+  } else {
Rex Dieter f272280
+#if HAVE_XFIXES
Rex Dieter f272280
+    if (!have_xfixes)
Rex Dieter f272280
+#endif
Rex Dieter f272280
+    {
Rex Dieter f272280
+      poll_clipboard_owner();
Rex Dieter f272280
+
Rex Dieter f272280
+      if (!Fl::has_timeout(clipboard_timeout))
Rex Dieter f272280
+        Fl::add_timeout(0.5, clipboard_timeout);
Rex Dieter f272280
+    }
Rex Dieter f272280
+  }
Rex Dieter f272280
+}
Rex Dieter f272280
+
Rex Dieter f272280
+////////////////////////////////////////////////////////////////
Rex Dieter f272280
 
Rex Dieter f272280
 const XEvent* fl_xevent; // the current x event
Rex Dieter f272280
 ulong fl_event_time; // the last timestamp from an x event
Rex Dieter f272280
@@ -1024,7 +1141,6 @@ int fl_handle(const XEvent& thisevent)
Rex Dieter f272280
     return 0;
Rex Dieter f272280
 
Rex Dieter f272280
   case SelectionNotify: {
Rex Dieter f272280
-    if (!fl_selection_requestor) return 0;
Rex Dieter f272280
     static unsigned char* buffer = 0;
Rex Dieter f272280
     if (buffer) {XFree(buffer); buffer = 0;}
Rex Dieter f272280
     long bytesread = 0;
Rex Dieter f272280
@@ -1040,6 +1156,19 @@ int fl_handle(const XEvent& thisevent)
Rex Dieter f272280
                              bytesread/4, 65536, 1, 0,
Rex Dieter f272280
                              &actual, &format, &count, &remaining,
Rex Dieter f272280
                              &portion)) break; // quit on error
Rex Dieter f272280
+
Rex Dieter f272280
+      if ((fl_xevent->xselection.property == PRIMARY_TIMESTAMP) ||
Rex Dieter f272280
+          (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)) {
Rex Dieter f272280
+        if (portion && format == 32 && count == 1) {
Rex Dieter f272280
+          Time t = *(unsigned int*)portion;
Rex Dieter f272280
+          if (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)
Rex Dieter f272280
+            handle_clipboard_timestamp(1, t);
Rex Dieter f272280
+          else
Rex Dieter f272280
+            handle_clipboard_timestamp(0, t);
Rex Dieter f272280
+        }
Rex Dieter f272280
+        return true;
Rex Dieter f272280
+      }
Rex Dieter f272280
+
Rex Dieter f272280
       if (actual == TARGETS || actual == XA_ATOM) {
Rex Dieter f272280
 	Atom type = XA_STRING;
Rex Dieter f272280
 	for (unsigned i = 0; i
Rex Dieter f272280
@@ -1076,6 +1205,9 @@ int fl_handle(const XEvent& thisevent)
Rex Dieter f272280
       buffer[bytesread] = 0;
Rex Dieter f272280
       convert_crlf(buffer, bytesread);
Rex Dieter f272280
     }
Rex Dieter f272280
+
Rex Dieter f272280
+    if (!fl_selection_requestor) return 0;
Rex Dieter f272280
+
Rex Dieter f272280
     Fl::e_text = buffer ? (char*)buffer : (char *)"";
Rex Dieter f272280
     Fl::e_length = bytesread;
Rex Dieter f272280
     int old_event = Fl::e_number;
Rex Dieter f272280
@@ -1096,6 +1228,7 @@ int fl_handle(const XEvent& thisevent)
Rex Dieter f272280
   case SelectionClear: {
Rex Dieter f272280
     int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD;
Rex Dieter f272280
     fl_i_own_selection[clipboard] = 0;
Rex Dieter f272280
+    poll_clipboard_owner();
Rex Dieter f272280
     return 1;}
Rex Dieter f272280
 
Rex Dieter f272280
   case SelectionRequest: {
Rex Dieter f272280
@@ -1308,6 +1441,9 @@ int fl_handle(const XEvent& thisevent)
Rex Dieter f272280
   case FocusIn:
Rex Dieter f272280
     if (fl_xim_ic) XSetICFocus(fl_xim_ic);
Rex Dieter f272280
     event = FL_FOCUS;
Rex Dieter f272280
+    // If the user has toggled from another application to this one,
Rex Dieter f272280
+    // then it's a good time to check for clipboard changes.
Rex Dieter f272280
+    poll_clipboard_owner();
Rex Dieter f272280
     break;
Rex Dieter f272280
 
Rex Dieter f272280
   case FocusOut:
Rex Dieter f272280
@@ -1676,6 +1812,25 @@ int fl_handle(const XEvent& thisevent)
Rex Dieter f272280
     }
Rex Dieter f272280
   }
Rex Dieter f272280
 
Rex Dieter f272280
+#if HAVE_XFIXES
Rex Dieter f272280
+  switch (xevent.type - xfixes_event_base) {
Rex Dieter f272280
+  case XFixesSelectionNotify: {
Rex Dieter f272280
+    // Someone feeding us bogus events?
Rex Dieter f272280
+    if (!have_xfixes)
Rex Dieter f272280
+      return true;
Rex Dieter f272280
+
Rex Dieter f272280
+    XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)&xevent;
Rex Dieter f272280
+
Rex Dieter f272280
+    if ((selection_notify->selection == XA_PRIMARY) && !fl_i_own_selection[0])
Rex Dieter f272280
+      handle_clipboard_timestamp(0, selection_notify->selection_timestamp);
Rex Dieter f272280
+    else if ((selection_notify->selection == CLIPBOARD) && !fl_i_own_selection[1])
Rex Dieter f272280
+      handle_clipboard_timestamp(1, selection_notify->selection_timestamp);
Rex Dieter f272280
+
Rex Dieter f272280
+    return true;
Rex Dieter f272280
+    }
Rex Dieter f272280
+  }
Rex Dieter f272280
+#endif
Rex Dieter f272280
+
Rex Dieter f272280
   return Fl::handle(event, window);
Rex Dieter f272280
 }
Rex Dieter f272280
 
Rex Dieter f272280
@@ -1995,6 +2150,16 @@ void Fl_X::make_xid(Fl_Window* win, XVis
Rex Dieter f272280
     XChangeProperty(fl_display, xp->xid, net_wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&net_wm_type_kind, 1);
Rex Dieter f272280
   }
Rex Dieter f272280
 
Rex Dieter f272280
+#if HAVE_XFIXES
Rex Dieter f272280
+  // register for clipboard change notifications
Rex Dieter f272280
+  if (have_xfixes && !win->parent()) {
Rex Dieter f272280
+    XFixesSelectSelectionInput(fl_display, xp->xid, XA_PRIMARY,
Rex Dieter f272280
+                               XFixesSetSelectionOwnerNotifyMask);
Rex Dieter f272280
+    XFixesSelectSelectionInput(fl_display, xp->xid, CLIPBOARD,
Rex Dieter f272280
+                               XFixesSetSelectionOwnerNotifyMask);
Rex Dieter f272280
+  }
Rex Dieter f272280
+#endif
Rex Dieter f272280
+
Rex Dieter f272280
   XMapWindow(fl_display, xp->xid);
Rex Dieter f272280
   if (showit) {
Rex Dieter f272280
     win->set_visible();
Rex Dieter f272280
diff -up fltk-1.3.2/test/CMakeLists.txt.clp-x11 fltk-1.3.2/test/CMakeLists.txt