Initial commit

This commit is contained in:
matt
2020-09-20 12:16:44 +00:00
parent 09a4460ddb
commit 408c005d3e
839 changed files with 190481 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
diff -up fltk-1.3.x-r8659/FL/Fl.H.orig fltk-1.3.x-r8659/FL/Fl.H
--- fltk-1.3.x-r8659/FL/Fl.H.orig 2011-05-17 16:25:56.671744548 +0200
+++ fltk-1.3.x-r8659/FL/Fl.H 2011-05-17 16:26:05.709101536 +0200
@@ -108,6 +108,9 @@ typedef int (*Fl_Args_Handler)(int argc,
\see Fl::event_dispatch(Fl_Event_Dispatch) */
typedef int (*Fl_Event_Dispatch)(int event, Fl_Window *w);
+/** Signature of add_clipboard_notify functions passed as parameters */
+typedef void (*Fl_Clipboard_Notify_Handler)(int source, void *data);
+
/** @} */ /* group callback_functions */
@@ -744,6 +747,19 @@ public:
*/
static void paste(Fl_Widget &receiver, int source /*=0*/); // platform dependent
/**
+ FLTK will call the registered callback whenever there is a change to the
+ selection buffer or the clipboard. The source argument indicates which
+ of the two has changed. Only changes by other applications are reported.
+ \note Some systems require polling to monitor the clipboard and may
+ therefore have some delay in detecting changes.
+ */
+ static void add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data);
+ /**
+ Stop calling the specified callback when there are changes to the selection
+ buffer or the clipboard.
+ */
+ static void remove_clipboard_notify(Fl_Clipboard_Notify_Handler h);
+ /**
Initiate a Drag And Drop operation. The selection buffer should be
filled with relevant data before calling this method. FLTK will
then initiate the system wide drag and drop handling. Dropped data
diff -up fltk-1.3.x-r8659/src/Fl.cxx.orig fltk-1.3.x-r8659/src/Fl.cxx
--- fltk-1.3.x-r8659/src/Fl.cxx.orig 2011-05-18 15:20:26.667291459 +0200
+++ fltk-1.3.x-r8659/src/Fl.cxx 2011-05-18 16:31:15.522026086 +0200
@@ -430,6 +430,69 @@ static char in_idle;
#endif
////////////////////////////////////////////////////////////////
+// Clipboard notifications
+
+struct Clipboard_Notify {
+ Fl_Clipboard_Notify_Handler handler;
+ void *data;
+ struct Clipboard_Notify *next;
+};
+
+static struct Clipboard_Notify *clip_notify_list = NULL;
+
+extern void fl_clipboard_notify_change(); // in Fl_<platform>.cxx
+
+void Fl::add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data) {
+ struct Clipboard_Notify *node;
+
+ remove_clipboard_notify(h);
+
+ node = new Clipboard_Notify;
+
+ node->handler = h;
+ node->data = data;
+ node->next = clip_notify_list;
+
+ clip_notify_list = node;
+
+ fl_clipboard_notify_change();
+}
+
+void Fl::remove_clipboard_notify(Fl_Clipboard_Notify_Handler h) {
+ struct Clipboard_Notify *node, **prev;
+
+ node = clip_notify_list;
+ prev = &clip_notify_list;
+ while (node != NULL) {
+ if (node->handler == h) {
+ *prev = node->next;
+ delete node;
+
+ fl_clipboard_notify_change();
+
+ return;
+ }
+
+ prev = &node->next;
+ node = node->next;
+ }
+}
+
+bool fl_clipboard_notify_empty(void) {
+ return clip_notify_list == NULL;
+}
+
+void fl_trigger_clipboard_notify(int source) {
+ struct Clipboard_Notify *node;
+
+ node = clip_notify_list;
+ while (node != NULL) {
+ node->handler(source, node->data);
+ node = node->next;
+ }
+}
+
+////////////////////////////////////////////////////////////////
// wait/run/check/ready:
void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions

View File

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

View File

@@ -0,0 +1,135 @@
diff -ur fltk-1.3.0r9110.org/src/Fl_win32.cxx fltk-1.3.0r9110/src/Fl_win32.cxx
--- fltk-1.3.0r9110.org/src/Fl_win32.cxx 2012-06-17 19:42:02.169422400 +0200
+++ fltk-1.3.0r9110/src/Fl_win32.cxx 2012-06-17 19:43:38.286031455 +0200
@@ -543,6 +543,37 @@
const char* GetValue() const { return(out); }
};
+void fl_update_clipboard(void) {
+ Fl_Window *w1 = Fl::first_window();
+ if (!w1)
+ return;
+
+ HWND hwnd = fl_xid(w1);
+
+ if (!OpenClipboard(hwnd))
+ return;
+
+ EmptyClipboard();
+
+ int utf16_len = fl_utf8toUtf16(fl_selection_buffer[1],
+ fl_selection_length[1], 0, 0);
+
+ HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc.
+ LPVOID memLock = GlobalLock(hMem);
+
+ fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1],
+ (unsigned short*) memLock, utf16_len + 1);
+
+ GlobalUnlock(hMem);
+ SetClipboardData(CF_UNICODETEXT, hMem);
+
+ CloseClipboard();
+
+ // In case Windows managed to lob of a WM_DESTROYCLIPBOARD during
+ // the above.
+ fl_i_own_selection[1] = 1;
+}
+
// call this when you create a selection:
void Fl::copy(const char *stuff, int len, int clipboard) {
if (!stuff || len<0) return;
@@ -560,25 +591,9 @@
memcpy(fl_selection_buffer[clipboard], stuff, len);
fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
fl_selection_length[clipboard] = len;
- if (clipboard) {
- // set up for "delayed rendering":
- if (OpenClipboard(NULL)) {
- // if the system clipboard works, use it
- int utf16_len = fl_utf8toUtf16(fl_selection_buffer[clipboard], fl_selection_length[clipboard], 0, 0);
- EmptyClipboard();
- HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc.
- LPVOID memLock = GlobalLock(hMem);
- fl_utf8toUtf16(fl_selection_buffer[clipboard], fl_selection_length[clipboard], (unsigned short*) memLock, utf16_len + 1);
- GlobalUnlock(hMem);
- SetClipboardData(CF_UNICODETEXT, hMem);
- CloseClipboard();
- GlobalFree(hMem);
- fl_i_own_selection[clipboard] = 0;
- } else {
- // only if it fails, instruct paste() to use the internal buffers
- fl_i_own_selection[clipboard] = 1;
- }
- }
+ fl_i_own_selection[clipboard] = 1;
+ if (clipboard)
+ fl_update_clipboard();
}
// Call this when a "paste" operation happens:
@@ -1307,33 +1322,6 @@
fl_i_own_selection[1] = 0;
return 1;
- case WM_RENDERALLFORMATS:
- fl_i_own_selection[1] = 0;
- // Windoze seems unhappy unless I do these two steps. Documentation
- // seems to vary on whether opening the clipboard is necessary or
- // is in fact wrong:
- CloseClipboard();
- OpenClipboard(NULL);
- // fall through...
- case WM_RENDERFORMAT: {
- HANDLE h;
-
-// int l = fl_utf_nb_char((unsigned char*)fl_selection_buffer[1], fl_selection_length[1]);
- int l = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], NULL, 0); // Pass NULL buffer to query length required
- h = GlobalAlloc(GHND, (l+1) * sizeof(unsigned short));
- if (h) {
- unsigned short *g = (unsigned short*) GlobalLock(h);
-// fl_utf2unicode((unsigned char *)fl_selection_buffer[1], fl_selection_length[1], (xchar*)g);
- l = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], g, (l+1));
- g[l] = 0;
- GlobalUnlock(h);
- SetClipboardData(CF_UNICODETEXT, h);
- }
-
- // Windoze also seems unhappy if I don't do this. Documentation very
- // unclear on what is correct:
- if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard();
- return 1;}
case WM_DISPLAYCHANGE: // occurs when screen configuration (number, position) changes
Fl::call_screen_init();
Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
diff -ur fltk-1.3.0r9110.org/src/Fl.cxx fltk-1.3.0r9110/src/Fl.cxx
--- fltk-1.3.0r9110.org/src/Fl.cxx 2012-06-17 19:42:02.173422595 +0200
+++ fltk-1.3.0r9110/src/Fl.cxx 2012-06-17 19:42:02.317429497 +0200
@@ -1420,7 +1420,9 @@
////////////////////////////////////////////////////////////////
// hide() destroys the X window, it does not do unmap!
-#if !defined(WIN32) && USE_XFT
+#if defined(WIN32)
+extern void fl_update_clipboard(void);
+#elif USE_XFT
extern void fl_destroy_xft_draw(Window);
#endif
@@ -1467,14 +1469,8 @@
#if defined(WIN32)
// this little trick keeps the current clipboard alive, even if we are about
// to destroy the window that owns the selection.
- if (GetClipboardOwner()==ip->xid) {
- Fl_Window *w1 = Fl::first_window();
- if (w1 && OpenClipboard(fl_xid(w1))) {
- EmptyClipboard();
- SetClipboardData(CF_TEXT, NULL);
- CloseClipboard();
- }
- }
+ if (GetClipboardOwner()==ip->xid)
+ fl_update_clipboard();
// Send a message to myself so that I'll get out of the event loop...
PostMessage(ip->xid, WM_APP, 0, 0);
if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc);

View File

@@ -0,0 +1,99 @@
diff -ur fltk-1.3.0r9110.org/src/Fl.cxx fltk-1.3.0r9110/src/Fl.cxx
--- fltk-1.3.0r9110.org/src/Fl.cxx 2012-06-17 19:47:09.988183253 +0200
+++ fltk-1.3.0r9110/src/Fl.cxx 2012-06-17 19:47:10.127189919 +0200
@@ -1421,6 +1421,7 @@
// hide() destroys the X window, it does not do unmap!
#if defined(WIN32)
+extern void fl_clipboard_notify_untarget(HWND wnd);
extern void fl_update_clipboard(void);
#elif USE_XFT
extern void fl_destroy_xft_draw(Window);
@@ -1471,6 +1472,8 @@
// to destroy the window that owns the selection.
if (GetClipboardOwner()==ip->xid)
fl_update_clipboard();
+ // Make sure we unlink this window from the clipboard chain
+ fl_clipboard_notify_untarget(ip->xid);
// Send a message to myself so that I'll get out of the event loop...
PostMessage(ip->xid, WM_APP, 0, 0);
if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc);
diff -ur fltk-1.3.0r9110.org/src/Fl_win32.cxx fltk-1.3.0r9110/src/Fl_win32.cxx
--- fltk-1.3.0r9110.org/src/Fl_win32.cxx 2012-06-17 19:47:09.987183205 +0200
+++ fltk-1.3.0r9110/src/Fl_win32.cxx 2012-06-17 19:47:19.069618739 +0200
@@ -646,6 +646,38 @@
}
}
+static HWND clipboard_wnd = 0;
+static HWND next_clipboard_wnd = 0;
+
+static bool initial_clipboard = true;
+
+void fl_clipboard_notify_change() {
+ // No need to do anything here...
+}
+
+void fl_clipboard_notify_target(HWND wnd) {
+ if (clipboard_wnd)
+ return;
+
+ // We get one fake WM_DRAWCLIPBOARD immediately, which we therefore
+ // need to ignore.
+ initial_clipboard = true;
+
+ clipboard_wnd = wnd;
+ next_clipboard_wnd = SetClipboardViewer(wnd);
+}
+
+void fl_clipboard_notify_untarget(HWND wnd) {
+ if (wnd != clipboard_wnd)
+ return;
+
+ ChangeClipboardChain(wnd, next_clipboard_wnd);
+ clipboard_wnd = next_clipboard_wnd = 0;
+
+ if (Fl::first_window())
+ fl_clipboard_notify_target(fl_xid(Fl::first_window()));
+}
+
////////////////////////////////////////////////////////////////
char fl_is_ime = 0;
void fl_get_codepage()
@@ -1327,6 +1359,27 @@
Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
return 0;
+ case WM_CHANGECBCHAIN:
+ if ((hWnd == clipboard_wnd) &&
+ (next_clipboard_wnd == (HWND)wParam)) {
+ next_clipboard_wnd = (HWND)lParam;
+ return 0;
+ }
+ break;
+
+ case WM_DRAWCLIPBOARD:
+ // When the clipboard moves between two FLTK windows,
+ // fl_i_own_selection will temporarily be false as we are
+ // processing this message. Hence the need to use fl_find().
+ if (!initial_clipboard && !fl_find(GetClipboardOwner()))
+ fl_trigger_clipboard_notify(1);
+ initial_clipboard = false;
+
+ if (next_clipboard_wnd)
+ SendMessage(next_clipboard_wnd, WM_DRAWCLIPBOARD, wParam, lParam);
+
+ return 0;
+
default:
if (Fl::handle(0,0)) return 0;
break;
@@ -1685,6 +1738,8 @@
x->next = Fl_X::first;
Fl_X::first = x;
+ fl_clipboard_notify_target(x->xid);
+
x->wait_for_expose = 1;
if (fl_show_iconic) {showit = 0; fl_show_iconic = 0;}
if (showit) {

View File

@@ -0,0 +1,44 @@
diff -bur fltk-1.3.0r9619.org/src/Fl_cocoa.mm fltk-1.3.0r9619/src/Fl_cocoa.mm
--- fltk-1.3.0r9619.org/src/Fl_cocoa.mm 2012-06-18 19:24:30.971688769 +0200
+++ fltk-1.3.0r9619/src/Fl_cocoa.mm 2012-06-18 19:25:25.700310375 +0200
@@ -1319,9 +1319,13 @@
}
@end
+static void clipboard_check(void);
+
@implementation FLApplication
+ (void)sendEvent:(NSEvent *)theEvent
{
+ // update clipboard status
+ clipboard_check();
NSEventType type = [theEvent type];
if (type == NSLeftMouseDown) {
fl_lock_function();
@@ -2790,6 +2794,26 @@
PasteboardCreate(kPasteboardClipboard, &myPasteboard);
}
+extern void fl_trigger_clipboard_notify(int source);
+
+void fl_clipboard_notify_change() {
+ // No need to do anything here...
+}
+
+static void clipboard_check(void)
+{
+ PasteboardSyncFlags flags;
+
+ allocatePasteboard();
+ flags = PasteboardSynchronize(myPasteboard);
+
+ if (!(flags & kPasteboardModified))
+ return;
+ if (flags & kPasteboardClientIsOwner)
+ return;
+
+ fl_trigger_clipboard_notify(1);
+}
/*
* create a selection

View File

@@ -0,0 +1,554 @@
diff -ur fltk-1.3.2.org/FL/Fl_Image.H fltk-1.3.2/FL/Fl_Image.H
--- fltk-1.3.2.org/FL/Fl_Image.H 2012-11-09 17:02:08.000000000 +0100
+++ fltk-1.3.2/FL/Fl_Image.H 2013-01-16 14:40:51.543230638 +0100
@@ -26,6 +26,7 @@
#include <stdlib.h>
class Fl_Widget;
+class Fl_Pixmap;
struct Fl_Menu_Item;
struct Fl_Label;
@@ -203,6 +204,7 @@
*/
Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0) :
Fl_Image(W,H,D), array(bits), alloc_array(0), id_(0), mask_(0) {data((const char **)&array, 1); ld(LD);}
+ Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg=FL_GRAY);
virtual ~Fl_RGB_Image();
virtual Fl_Image *copy(int W, int H);
Fl_Image *copy() { return copy(w(), h()); }
diff -ur fltk-1.3.2.org/src/fl_draw_pixmap.cxx fltk-1.3.2/src/fl_draw_pixmap.cxx
--- fltk-1.3.2.org/src/fl_draw_pixmap.cxx 2012-04-22 05:09:31.000000000 +0200
+++ fltk-1.3.2/src/fl_draw_pixmap.cxx 2013-01-16 14:40:51.542230588 +0100
@@ -58,99 +58,6 @@
return 1;
}
-#ifdef U64
-
-// The callback from fl_draw_image to get a row of data passes this:
-struct pixmap_data {
- int w, h;
- const uchar*const* data;
- union {
- U64 colors[256];
- U64* byte1[256];
- };
-};
-
-// callback for 1 byte per pixel:
-static void cb1(void*v, int x, int y, int w, uchar* buf) {
- pixmap_data& d = *(pixmap_data*)v;
- const uchar* p = d.data[y]+x;
- U64* q = (U64*)buf;
- for (int X=w; X>0; X-=2, p += 2) {
- if (X>1) {
-# if WORDS_BIGENDIAN
- *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]];
-# else
- *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]];
-# endif
- } else {
-# if WORDS_BIGENDIAN
- *q++ = d.colors[p[0]]<<32;
-# else
- *q++ = d.colors[p[0]];
-# endif
- }
- }
-}
-
-// callback for 2 bytes per pixel:
-static void cb2(void*v, int x, int y, int w, uchar* buf) {
- pixmap_data& d = *(pixmap_data*)v;
- const uchar* p = d.data[y]+2*x;
- U64* q = (U64*)buf;
- for (int X=w; X>0; X-=2) {
- U64* colors = d.byte1[*p++];
- int index = *p++;
- if (X>1) {
- U64* colors1 = d.byte1[*p++];
- int index1 = *p++;
-# if WORDS_BIGENDIAN
- *q++ = (colors[index]<<32) | colors1[index1];
-# else
- *q++ = (colors1[index1]<<32) | colors[index];
-# endif
- } else {
-# if WORDS_BIGENDIAN
- *q++ = colors[index]<<32;
-# else
- *q++ = colors[index];
-# endif
- }
- }
-}
-
-#else // U32
-
-// The callback from fl_draw_image to get a row of data passes this:
-struct pixmap_data {
- int w, h;
- const uchar*const* data;
- union {
- U32 colors[256];
- U32* byte1[256];
- };
-};
-
-// callback for 1 byte per pixel:
-static void cb1(void*v, int x, int y, int w, uchar* buf) {
- pixmap_data& d = *(pixmap_data*)v;
- const uchar* p = d.data[y]+x;
- U32* q = (U32*)buf;
- for (int X=w; X--;) *q++ = d.colors[*p++];
-}
-
-// callback for 2 bytes per pixel:
-static void cb2(void*v, int x, int y, int w, uchar* buf) {
- pixmap_data& d = *(pixmap_data*)v;
- const uchar* p = d.data[y]+2*x;
- U32* q = (U32*)buf;
- for (int X=w; X--;) {
- U32* colors = d.byte1[*p++];
- *q++ = colors[*p++];
- }
-}
-
-#endif // U64 else U32
-
uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here
/**
@@ -200,34 +107,33 @@
}
#endif
-/**
- Draw XPM image data, with the top-left corner at the given position.
- \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
- */
-int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
- pixmap_data d;
- if (!fl_measure_pixmap(cdata, d.w, d.h)) return 0;
+int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg) {
+ int w, h;
const uchar*const* data = (const uchar*const*)(cdata+1);
int transparent_index = -1;
+
+ if (!fl_measure_pixmap(cdata, w, h))
+ return 0;
+
+ if ((chars_per_pixel < 1) || (chars_per_pixel > 2))
+ return 0;
+
+ uchar colors[1<<(chars_per_pixel*8)][4];
+
#ifdef WIN32
uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color
color_count = 0;
used_colors = (uchar *)malloc(abs(ncolors)*3*sizeof(uchar));
#endif
- if (ncolors < 0) { // FLTK (non standard) compressed colormap
+ if (ncolors < 0) {
+ // FLTK (non standard) compressed colormap
ncolors = -ncolors;
const uchar *p = *data++;
// if first color is ' ' it is transparent (put it later to make
// it not be transparent):
if (*p == ' ') {
- uchar* c = (uchar*)&d.colors[(int)' '];
-#ifdef U64
- *(U64*)c = 0;
-# if WORDS_BIGENDIAN
- c += 4;
-# endif
-#endif
+ uchar* c = colors[(int)' '];
transparent_index = ' ';
Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
#ifdef WIN32
@@ -238,13 +144,7 @@
}
// read all the rest of the colors:
for (int i=0; i < ncolors; i++) {
- uchar* c = (uchar*)&d.colors[*p++];
-#ifdef U64
- *(U64*)c = 0;
-# if WORDS_BIGENDIAN
- c += 4;
-# endif
-#endif
+ uchar* c = colors[*p++];
#ifdef WIN32
used_colors[3*color_count] = *p;
used_colors[3*color_count+1] = *(p+1);
@@ -254,69 +154,44 @@
*c++ = *p++;
*c++ = *p++;
*c++ = *p++;
-#ifdef __APPLE_QUARTZ__
*c = 255;
-#else
- *c = 0;
-#endif
}
- } else { // normal XPM colormap with names
- if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1));
+ } else {
+ // normal XPM colormap with names
for (int i=0; i<ncolors; i++) {
const uchar *p = *data++;
// the first 1 or 2 characters are the color index:
int ind = *p++;
uchar* c;
- if (chars_per_pixel>1) {
-#ifdef U64
- U64* colors = d.byte1[ind];
- if (!colors) colors = d.byte1[ind] = new U64[256];
-#else
- U32* colors = d.byte1[ind];
- if (!colors) colors = d.byte1[ind] = new U32[256];
-#endif
- c = (uchar*)&colors[*p];
- ind = (ind<<8)|*p++;
- } else {
- c = (uchar *)&d.colors[ind];
- }
+ if (chars_per_pixel>1)
+ ind = (ind<<8)|*p++;
+ c = colors[ind];
// look for "c word", or last word if none:
const uchar *previous_word = p;
for (;;) {
- while (*p && isspace(*p)) p++;
- uchar what = *p++;
- while (*p && !isspace(*p)) p++;
- while (*p && isspace(*p)) p++;
- if (!*p) {p = previous_word; break;}
- if (what == 'c') break;
- previous_word = p;
- while (*p && !isspace(*p)) p++;
+ while (*p && isspace(*p)) p++;
+ uchar what = *p++;
+ while (*p && !isspace(*p)) p++;
+ while (*p && isspace(*p)) p++;
+ if (!*p) {p = previous_word; break;}
+ if (what == 'c') break;
+ previous_word = p;
+ while (*p && !isspace(*p)) p++;
}
-#ifdef U64
- *(U64*)c = 0;
-# if WORDS_BIGENDIAN
- c += 4;
-# endif
-#endif
-#ifdef __APPLE_QUARTZ__
- c[3] = 255;
-#endif
int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]);
+ c[3] = 255;
if (parse) {
#ifdef WIN32
- used_colors[3*color_count] = c[0];
- used_colors[3*color_count+1] = c[1];
- used_colors[3*color_count+2] = c[2];
- color_count++;
+ used_colors[3*color_count] = c[0];
+ used_colors[3*color_count+1] = c[1];
+ used_colors[3*color_count+2] = c[2];
+ color_count++;
#endif
- }
- else {
+ } else {
// assume "None" or "#transparent" for any errors
- // "bg" should be transparent...
- Fl::get_color(bg, c[0], c[1], c[2]);
-#ifdef __APPLE_QUARTZ__
+ // "bg" should be transparent...
+ Fl::get_color(bg, c[0], c[1], c[2]);
c[3] = 0;
-#endif
transparent_index = ind;
#ifdef WIN32
transparent_c = c;
@@ -324,7 +199,6 @@
}
}
}
- d.data = data;
#ifdef WIN32
if (transparent_c) {
make_unused_color(transparent_c[0], transparent_c[1], transparent_c[2]);
@@ -334,77 +208,76 @@
make_unused_color(r, g, b);
}
#endif
+
+ U32 *q = (U32*)out;
+ for (int Y = 0; Y < h; Y++) {
+ const uchar* p = data[Y];
+ if (chars_per_pixel <= 1) {
+ for (int X = 0; X < w; X++)
+ memcpy(q++, colors[*p++], 4);
+ } else {
+ for (int X = 0; X < w; X++) {
+ int ind = (*p++)<<8;
+ ind |= *p++;
+ memcpy(q++, colors[ind], 4);
+ }
+ }
+ }
+ return 1;
+}
+
+/**
+ Draw XPM image data, with the top-left corner at the given position.
+ \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
+ */
+int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
+ int w, h;
+
+ if (!fl_measure_pixmap(cdata, w, h))
+ return 0;
+
+ uchar buffer[w*h*4];
+
+ if (!fl_convert_pixmap(cdata, buffer, bg))
+ return 0;
+
+ // FIXME: Hack until fl_draw_image() supports alpha properly
#ifdef __APPLE_QUARTZ__
if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) {
- U32 *array = new U32[d.w * d.h], *q = array;
- for (int Y = 0; Y < d.h; Y++) {
- const uchar* p = data[Y];
- if (chars_per_pixel <= 1) {
- for (int X = 0; X < d.w; X++) {
- *q++ = d.colors[*p++];
- }
- } else {
- for (int X = 0; X < d.w; X++) {
- U32* colors = (U32*)d.byte1[*p++];
- *q++ = colors[*p++];
- }
- }
- }
- Fl_RGB_Image* rgb = new Fl_RGB_Image((uchar*)array, d.w, d.h, 4);
+ Fl_RGB_Image* rgb = new Fl_RGB_Image(buffer, w, h, 4);
rgb->draw(x, y);
delete rgb;
- delete[] array;
- }
- else {
+ } else {
#endif // __APPLE_QUARTZ__
-
// build the mask bitmap used by Fl_Pixmap:
- if (fl_mask_bitmap && transparent_index >= 0) {
- int W = (d.w+7)/8;
- uchar* bitmap = new uchar[W * d.h];
+ if (fl_mask_bitmap) {
+ int W = (w+7)/8;
+ uchar* bitmap = new uchar[W * h];
*fl_mask_bitmap = bitmap;
- for (int Y = 0; Y < d.h; Y++) {
- const uchar* p = data[Y];
- if (chars_per_pixel <= 1) {
- int dw = d.w;
- for (int X = 0; X < W; X++) {
- uchar b = (dw-->0 && *p++ != transparent_index);
- if (dw-->0 && *p++ != transparent_index) b |= 2;
- if (dw-->0 && *p++ != transparent_index) b |= 4;
- if (dw-->0 && *p++ != transparent_index) b |= 8;
- if (dw-->0 && *p++ != transparent_index) b |= 16;
- if (dw-->0 && *p++ != transparent_index) b |= 32;
- if (dw-->0 && *p++ != transparent_index) b |= 64;
- if (dw-->0 && *p++ != transparent_index) b |= 128;
+ const uchar *p = &buffer[3];
+ uchar b = 0;
+ for (int Y = 0; Y < h; Y++) {
+ b = 0;
+ for (int X = 0, bit = 1; X < w; X++, p += 4) {
+ if (*p > 127) b |= bit;
+ bit <<= 1;
+ if (bit > 0x80 || X == w-1) {
*bitmap++ = b;
- }
- } else {
- uchar b = 0, bit = 1;
- for (int X = 0; X < d.w; X++) {
- int ind = *p++;
- ind = (ind<<8) | (*p++);
- if (ind != transparent_index) b |= bit;
-
- if (bit < 128) bit <<= 1;
- else {
- *bitmap++ = b;
- b = 0;
- bit = 1;
+ bit = 1;
+ b = 0;
}
}
-
- if (bit > 1) *bitmap++ = b;
}
- }
+
}
- fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4);
+ fl_draw_image(buffer, x, y, w, h, 4);
+
#ifdef __APPLE_QUARTZ__
}
#endif
- if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i];
return 1;
}
diff -ur fltk-1.3.2.org/src/Fl_Image.cxx fltk-1.3.2/src/Fl_Image.cxx
--- fltk-1.3.2.org/src/Fl_Image.cxx 2012-11-09 17:02:08.000000000 +0100
+++ fltk-1.3.2/src/Fl_Image.cxx 2013-01-16 14:41:38.404162795 +0100
@@ -165,7 +165,22 @@
//
size_t Fl_RGB_Image::max_size_ = ~((size_t)0);
-/** The destructor free all memory and server resources that are used by the image. */
+int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
+
+/** The constructor creates a new RGBA image from the specified Fl_Pixmap.
+
+ The RGBA image is built fully opaque except for the transparent area
+ of the pixmap that is assigned the \par bg color with full transparency */
+Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg):
+ Fl_Image(pxm->w(), pxm->h(), 4), id_(0), mask_(0)
+{
+ array = new uchar[w() * h() * d()];
+ alloc_array = 1;
+ fl_convert_pixmap(pxm->data(), (uchar*)array, bg);
+ data((const char **)&array, 1);
+}
+
+/** The destructor frees all memory and server resources that are used by the image. */
Fl_RGB_Image::~Fl_RGB_Image() {
uncache();
if (alloc_array) delete[] (uchar *)array;
diff -ur fltk-1.3.2.org/src/ps_image.cxx fltk-1.3.2/src/ps_image.cxx
--- fltk-1.3.2.org/src/ps_image.cxx 2011-07-19 06:49:30.000000000 +0200
+++ fltk-1.3.2/src/ps_image.cxx 2013-01-16 14:40:51.541228080 +0100
@@ -185,72 +185,38 @@
extern uchar **fl_mask_bitmap;
+struct callback_data {
+ const uchar *data;
+ int D, LD;
+};
-void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
- double x = ix, y = iy, w = iw, h = ih;
- if (D<3){ //mono
- draw_image_mono(data, ix, iy, iw, ih, D, LD);
- return;
- }
+static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
+ struct callback_data *cb_data;
+ const uchar *curdata;
+ cb_data = (struct callback_data*)data;
+ curdata = cb_data->data + x*cb_data->D + y*cb_data->LD;
- int i,j, k;
+ memcpy(buf, curdata, w*cb_data->D);
+}
- fprintf(output,"save\n");
- const char * interpol;
- if (lang_level_>1){
- if (interpolate_)
- interpol="true";
- else
- interpol="false";
- if (mask && lang_level_>2)
- fprintf(output, "%g %g %g %g %i %i %i %i %s CIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol);
- else
- fprintf(output, "%g %g %g %g %i %i %s CII\n", x , y+h , w , -h , iw , ih, interpol);
- } else
- fprintf(output , "%g %g %g %g %i %i CI", x , y+h , w , -h , iw , ih);
+void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
+ if (D<3){ //mono
+ draw_image_mono(data, ix, iy, iw, ih, D, LD);
+ return;
+ }
+ struct callback_data cb_data;
if (!LD) LD = iw*D;
- uchar *curmask=mask;
-
- for (j=0; j<ih;j++){
- if (mask){
-
- for (k=0;k<my/ih;k++){
- for (i=0; i<((mx+7)/8);i++){
- if (!(i%80)) fprintf(output, "\n");
- fprintf(output, "%.2x",swap_byte(*curmask));
- curmask++;
- }
- fprintf(output,"\n");
- }
- }
- const uchar *curdata=data+j*LD;
- for (i=0 ; i<iw ; i++) {
- uchar r = curdata[0];
- uchar g = curdata[1];
- uchar b = curdata[2];
- if (lang_level_<3 && D>3) { //can do mixing using bg_* colors)
- unsigned int a2 = curdata[3]; //must be int
- unsigned int a = 255-a2;
- r = (a2 * r + bg_r * a)/255;
- g = (a2 * g + bg_g * a)/255;
- b = (a2 * b + bg_b * a)/255;
- }
- if (!(i%40)) fprintf(output, "\n");
- fprintf(output, "%.2x%.2x%.2x", r, g, b);
- curdata +=D;
- }
- fprintf(output,"\n");
-
- }
-
- fprintf(output," >\nrestore\n" );
+ cb_data.data = data;
+ cb_data.D = D;
+ cb_data.LD = LD;
+ draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, D);
}
void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) {
@@ -325,6 +291,14 @@
uchar g = curdata[1];
uchar b = curdata[2];
+ if (lang_level_<3 && D>3) { //can do mixing using bg_* colors)
+ unsigned int a2 = curdata[3]; //must be int
+ unsigned int a = 255-a2;
+ r = (a2 * r + bg_r * a)/255;
+ g = (a2 * g + bg_g * a)/255;
+ b = (a2 * b + bg_b * a)/255;
+ }
+
if (!(i%40)) fputs("\n", output);
fprintf(output, "%.2x%.2x%.2x", r, g, b);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
diff -bur fltk-1.3.0r9619.org/src/Fl_cocoa.mm fltk-1.3.0r9619/src/Fl_cocoa.mm
--- fltk-1.3.0r9619.org/src/Fl_cocoa.mm 2012-06-19 12:54:43.694231638 +0200
+++ fltk-1.3.0r9619/src/Fl_cocoa.mm 2012-06-19 12:57:05.899048602 +0200
@@ -697,12 +697,9 @@
return NO; // prevent the caption to be redrawn as active on click
// when another modal window is currently the key win
- return !(w->tooltip_window() || w->menu_window());
+ return !w->tooltip_window();
}
-// TODO see if we really need a canBecomeMainWindow ...
-#if 0
-
- (BOOL)canBecomeMainWindow
{
if (Fl::modal_ && (Fl::modal_ != w))
@@ -711,7 +708,6 @@
return !(w->tooltip_window() || w->menu_window());
}
-#endif
@end
diff -bur fltk-1.3.0r9619.org/src/Fl_win32.cxx fltk-1.3.0r9619/src/Fl_win32.cxx
--- fltk-1.3.0r9619.org/src/Fl_win32.cxx 2012-06-19 12:54:43.696231735 +0200
+++ fltk-1.3.0r9619/src/Fl_win32.cxx 2012-06-19 12:54:43.803236862 +0200
@@ -1065,6 +1065,10 @@
break;
case WM_SETFOCUS:
+ if ((Fl::modal_) && (Fl::modal_ != window)) {
+ SetFocus(fl_xid(Fl::modal_));
+ return 0;
+ }
Fl::handle(FL_FOCUS, window);
break;
@@ -1826,6 +1830,11 @@
Fl::e_number = old_event;
w->redraw(); // force draw to happen
}
+
+ // Needs to be done before ShowWindow() to get the correct behaviour
+ // when we get WM_SETFOCUS.
+ if (w->modal()) {Fl::modal_ = w; fl_fix_focus();}
+
// If we've captured the mouse, we dont want to activate any
// other windows from the code, or we lose the capture.
ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
@@ -1843,7 +1852,6 @@
}
}
- if (w->modal()) {Fl::modal_ = w; fl_fix_focus();}
return x;
}
diff -bur fltk-1.3.0r9619.org/src/Fl_x.cxx fltk-1.3.0r9619/src/Fl_x.cxx
--- fltk-1.3.0r9619.org/src/Fl_x.cxx 2012-06-19 12:54:43.697231783 +0200
+++ fltk-1.3.0r9619/src/Fl_x.cxx 2012-06-19 12:54:43.804236911 +0200
@@ -2101,6 +2101,12 @@
while (wp->parent()) wp = wp->window();
XSetTransientForHint(fl_display, xp->xid, fl_xid(wp));
if (!wp->visible()) showit = 0; // guess that wm will not show it
+ if (win->modal()) {
+ Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0);
+ Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_MODAL", 0);
+ XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32,
+ PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1);
+ }
}
// Make sure that borderless windows do not show in the task bar

View File

@@ -0,0 +1,645 @@
diff -ur fltk-1.3.2.org/FL/Fl_Window.H fltk-1.3.2/FL/Fl_Window.H
--- fltk-1.3.2.org/FL/Fl_Window.H 2013-01-16 10:49:40.904228200 +0100
+++ fltk-1.3.2/FL/Fl_Window.H 2013-01-16 10:49:55.554353925 +0100
@@ -22,6 +22,10 @@
#ifndef Fl_Window_H
#define Fl_Window_H
+#ifdef WIN32
+#include <windows.h>
+#endif
+
#include "Fl_Group.H"
#define FL_WINDOW 0xF0 ///< window type id all subclasses have type() >= this
@@ -73,9 +77,19 @@
friend class Fl_X;
Fl_X *i; // points at the system-specific stuff
+ struct icon_data {
+ const void *legacy_icon;
+ Fl_RGB_Image **icons;
+ int count;
+#ifdef WIN32
+ HICON big_icon;
+ HICON small_icon;
+#endif
+ };
+
const char* iconlabel_;
char* xclass_;
- const void* icon_;
+ struct icon_data *icon_;
// size_range stuff:
int minw, minh, maxw, maxh;
int dw, dh, aspect;
@@ -121,6 +135,8 @@
*/
int force_position() const { return ((flags() & FORCE_POSITION)?1:0); }
+ void free_icons();
+
public:
/**
@@ -350,6 +366,18 @@
static const char *default_xclass();
const char* xclass() const;
void xclass(const char* c);
+
+ static void default_icon(const Fl_RGB_Image*);
+ static void default_icons(const Fl_RGB_Image*[], int);
+ void icon(const Fl_RGB_Image*);
+ void icons(const Fl_RGB_Image*[], int);
+
+#ifdef WIN32
+ static void default_icons(HICON big_icon, HICON small_icon);
+ void icons(HICON big_icon, HICON small_icon);
+#endif
+
+ /* for legacy compatibility */
const void* icon() const;
void icon(const void * ic);
diff -ur fltk-1.3.2.org/FL/mac.H fltk-1.3.2/FL/mac.H
--- fltk-1.3.2.org/FL/mac.H 2013-01-16 10:49:40.904228200 +0100
+++ fltk-1.3.2/FL/mac.H 2013-01-16 10:49:55.554353925 +0100
@@ -120,6 +120,9 @@
void collapse(void);
WindowRef window_ref(void);
void set_key_window(void);
+ // OS X doesn't have per window icons
+ static void set_default_icons(const Fl_RGB_Image*[], int) {};
+ void set_icons() {};
int set_cursor(Fl_Cursor);
int set_cursor(const Fl_RGB_Image*, int, int);
static CGImageRef CGImage_from_window_rect(Fl_Window *win, int x, int y, int w, int h);
diff -ur fltk-1.3.2.org/FL/win32.H fltk-1.3.2/FL/win32.H
--- fltk-1.3.2.org/FL/win32.H 2013-01-16 10:49:40.904228200 +0100
+++ fltk-1.3.2/FL/win32.H 2013-01-16 10:49:55.555355617 +0100
@@ -84,6 +84,9 @@
void flush() {w->flush();}
void set_minmax(LPMINMAXINFO minmax);
void mapraise();
+ static void set_default_icons(const Fl_RGB_Image*[], int);
+ static void set_default_icons(HICON, HICON);
+ void set_icons();
int set_cursor(Fl_Cursor);
int set_cursor(const Fl_RGB_Image*, int, int);
static Fl_X* make(Fl_Window*);
diff -ur fltk-1.3.2.org/FL/x.H fltk-1.3.2/FL/x.H
--- fltk-1.3.2.org/FL/x.H 2013-01-16 10:49:40.904228200 +0100
+++ fltk-1.3.2/FL/x.H 2013-01-16 10:49:55.555355617 +0100
@@ -154,6 +154,8 @@
static Fl_X* i(const Fl_Window* wi) {return wi->i;}
void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
void sendxjunk();
+ static void set_default_icons(const Fl_RGB_Image*[], int);
+ void set_icons();
int set_cursor(Fl_Cursor);
int set_cursor(const Fl_RGB_Image*, int, int);
static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, Colormap=fl_colormap);
diff -ur fltk-1.3.2.org/src/Fl.cxx fltk-1.3.2/src/Fl.cxx
--- fltk-1.3.2.org/src/Fl.cxx 2013-01-16 10:49:40.895228113 +0100
+++ fltk-1.3.2/src/Fl.cxx 2013-01-16 10:49:55.556137979 +0100
@@ -1530,6 +1530,8 @@
if (xclass_) {
free(xclass_);
}
+ free_icons();
+ delete icon_;
}
// FL_SHOW and FL_HIDE are called whenever the visibility of this widget
diff -ur fltk-1.3.2.org/src/Fl_win32.cxx fltk-1.3.2/src/Fl_win32.cxx
--- fltk-1.3.2.org/src/Fl_win32.cxx 2013-01-16 10:49:40.911227539 +0100
+++ fltk-1.3.2/src/Fl_win32.cxx 2013-01-16 10:49:55.556137979 +0100
@@ -1804,6 +1804,8 @@
);
if (lab) free(lab);
+ x->set_icons();
+
if (w->fullscreen_active()) {
/* We need to make sure that the fullscreen is created on the
default monitor, ie the desktop where the shortcut is located
@@ -2034,71 +2036,19 @@
////////////////////////////////////////////////////////////////
-#ifndef IDC_HAND
-# define IDC_HAND MAKEINTRESOURCE(32649)
-#endif // !IDC_HAND
-
-int Fl_X::set_cursor(Fl_Cursor c) {
- LPSTR n;
- HCURSOR new_cursor;
-
- if (c == FL_CURSOR_NONE)
- new_cursor = NULL;
- else {
- switch (c) {
- case FL_CURSOR_ARROW: n = IDC_ARROW; break;
- case FL_CURSOR_CROSS: n = IDC_CROSS; break;
- case FL_CURSOR_WAIT: n = IDC_WAIT; break;
- case FL_CURSOR_INSERT: n = IDC_IBEAM; break;
- case FL_CURSOR_HAND: n = IDC_HAND; break;
- case FL_CURSOR_HELP: n = IDC_HELP; break;
- case FL_CURSOR_MOVE: n = IDC_SIZEALL; break;
- case FL_CURSOR_N:
- case FL_CURSOR_S:
- // FIXME: Should probably have fallbacks for these instead
- case FL_CURSOR_NS: n = IDC_SIZENS; break;
- case FL_CURSOR_NE:
- case FL_CURSOR_SW:
- // FIXME: Dito.
- case FL_CURSOR_NESW: n = IDC_SIZENESW; break;
- case FL_CURSOR_E:
- case FL_CURSOR_W:
- // FIXME: Dito.
- case FL_CURSOR_WE: n = IDC_SIZEWE; break;
- case FL_CURSOR_SE:
- case FL_CURSOR_NW:
- // FIXME: Dito.
- case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break;
- default:
- return 0;
- }
-
- new_cursor = LoadCursor(NULL, n);
- if (new_cursor == NULL)
- return 0;
- }
-
- if ((cursor != NULL) && custom_cursor)
- DestroyIcon(cursor);
-
- cursor = new_cursor;
- custom_cursor = 0;
-
- SetCursor(cursor);
-
- return 1;
-}
-
-int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
+static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon=true,
+ int hotx = 0, int hoty = 0) {
BITMAPV5HEADER bi;
HBITMAP bitmap, mask;
DWORD *bits;
- HCURSOR new_cursor;
+ HICON icon;
+ if (!is_icon) {
if ((hotx < 0) || (hotx >= image->w()))
- return 0;
+ return NULL;
if ((hoty < 0) || (hoty >= image->h()))
- return 0;
+ return NULL;
+ }
memset(&bi, 0, sizeof(BITMAPV5HEADER));
@@ -2120,7 +2070,7 @@
ReleaseDC(NULL, hdc);
if (bits == NULL)
- return 0;
+ return NULL;
const uchar *i = (const uchar*)*image->data();
for (int y = 0;y < image->h();y++) {
@@ -2149,22 +2099,206 @@
mask = CreateBitmap(image->w(),image->h(),1,1,NULL);
if (mask == NULL) {
DeleteObject(bitmap);
- return 0;
+ return NULL;
}
ICONINFO ii;
- ii.fIcon = FALSE;
+ ii.fIcon = is_icon;
ii.xHotspot = hotx;
ii.yHotspot = hoty;
ii.hbmMask = mask;
ii.hbmColor = bitmap;
- new_cursor = CreateIconIndirect(&ii);
+ icon = CreateIconIndirect(&ii);
DeleteObject(bitmap);
DeleteObject(mask);
+ if (icon == NULL)
+ return NULL;
+
+ return icon;
+}
+
+////////////////////////////////////////////////////////////////
+
+static HICON default_big_icon = NULL;
+static HICON default_small_icon = NULL;
+
+const Fl_RGB_Image *find_best_icon(int ideal_width,
+ const Fl_RGB_Image *icons[], int count) {
+ const Fl_RGB_Image *best;
+
+ best = NULL;
+
+ for (int i = 0;i < count;i++) {
+ if (best == NULL)
+ best = icons[i];
+ else {
+ if (best->w() < ideal_width) {
+ if (icons[i]->w() > best->w())
+ best = icons[i];
+ } else {
+ if ((icons[i]->w() >= ideal_width) &&
+ (icons[i]->w() < best->w()))
+ best = icons[i];
+ }
+ }
+ }
+
+ return best;
+}
+
+void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) {
+ const Fl_RGB_Image *best_big, *best_small;
+
+ if (default_big_icon != NULL)
+ DestroyIcon(default_big_icon);
+ if (default_small_icon != NULL)
+ DestroyIcon(default_small_icon);
+
+ best_big = find_best_icon(GetSystemMetrics(SM_CXICON), icons, count);
+ best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), icons, count);
+
+ if (best_big != NULL)
+ default_big_icon = image_to_icon(best_big);
+ else
+ default_big_icon = NULL;
+
+ if (best_small != NULL)
+ default_small_icon = image_to_icon(best_small);
+ else
+ default_small_icon = NULL;
+}
+
+void Fl_X::set_default_icons(HICON big_icon, HICON small_icon) {
+ if (default_big_icon != NULL)
+ DestroyIcon(default_big_icon);
+ if (default_small_icon != NULL)
+ DestroyIcon(default_small_icon);
+
+ if (big_icon != NULL)
+ default_big_icon = CopyIcon(big_icon);
+ if (small_icon != NULL)
+ default_small_icon = CopyIcon(small_icon);
+}
+
+void Fl_X::set_icons() {
+ HICON big_icon, small_icon;
+
+ big_icon = NULL;
+ small_icon = NULL;
+
+ if (w->icon_->count) {
+ const Fl_RGB_Image *best_big, *best_small;
+
+ best_big = find_best_icon(GetSystemMetrics(SM_CXICON),
+ (const Fl_RGB_Image **)w->icon_->icons,
+ w->icon_->count);
+ best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON),
+ (const Fl_RGB_Image **)w->icon_->icons,
+ w->icon_->count);
+
+ if (best_big != NULL)
+ big_icon = image_to_icon(best_big);
+ if (best_small != NULL)
+ small_icon = image_to_icon(best_small);
+ } else {
+ big_icon = default_big_icon;
+ small_icon = default_small_icon;
+ }
+
+ if (big_icon != NULL)
+ SendMessage(xid, WM_SETICON, ICON_BIG, (LPARAM)big_icon);
+ if (small_icon != NULL)
+ SendMessage(xid, WM_SETICON, ICON_SMALL, (LPARAM)small_icon);
+
+ if (w->icon_->count) {
+ if (big_icon != NULL)
+ DestroyIcon(big_icon);
+ if (small_icon != NULL)
+ DestroyIcon(small_icon);
+ }
+}
+
+void Fl_Window::default_icons(HICON big_icon, HICON small_icon) {
+ Fl_X::set_default_icons(big_icon, small_icon);
+}
+
+void Fl_Window::icons(HICON big_icon, HICON small_icon) {
+ free_icons();
+
+ if (big_icon != NULL)
+ icon_->big_icon = CopyIcon(big_icon);
+ if (small_icon != NULL)
+ icon_->small_icon = CopyIcon(small_icon);
+
+ if (i)
+ i->set_icons();
+}
+
+////////////////////////////////////////////////////////////////
+
+#ifndef IDC_HAND
+# define IDC_HAND MAKEINTRESOURCE(32649)
+#endif // !IDC_HAND
+
+int Fl_X::set_cursor(Fl_Cursor c) {
+ LPSTR n;
+ HCURSOR new_cursor;
+
+ if (c == FL_CURSOR_NONE)
+ new_cursor = NULL;
+ else {
+ switch (c) {
+ case FL_CURSOR_ARROW: n = IDC_ARROW; break;
+ case FL_CURSOR_CROSS: n = IDC_CROSS; break;
+ case FL_CURSOR_WAIT: n = IDC_WAIT; break;
+ case FL_CURSOR_INSERT: n = IDC_IBEAM; break;
+ case FL_CURSOR_HAND: n = IDC_HAND; break;
+ case FL_CURSOR_HELP: n = IDC_HELP; break;
+ case FL_CURSOR_MOVE: n = IDC_SIZEALL; break;
+ case FL_CURSOR_N:
+ case FL_CURSOR_S:
+ // FIXME: Should probably have fallbacks for these instead
+ case FL_CURSOR_NS: n = IDC_SIZENS; break;
+ case FL_CURSOR_NE:
+ case FL_CURSOR_SW:
+ // FIXME: Dito.
+ case FL_CURSOR_NESW: n = IDC_SIZENESW; break;
+ case FL_CURSOR_E:
+ case FL_CURSOR_W:
+ // FIXME: Dito.
+ case FL_CURSOR_WE: n = IDC_SIZEWE; break;
+ case FL_CURSOR_SE:
+ case FL_CURSOR_NW:
+ // FIXME: Dito.
+ case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break;
+ default:
+ return 0;
+ }
+
+ new_cursor = LoadCursor(NULL, n);
+ if (new_cursor == NULL)
+ return 0;
+ }
+
+ if ((cursor != NULL) && custom_cursor)
+ DestroyIcon(cursor);
+
+ cursor = new_cursor;
+ custom_cursor = 0;
+
+ SetCursor(cursor);
+
+ return 1;
+}
+
+int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
+ HCURSOR new_cursor;
+
+ new_cursor = image_to_icon(image, false, hotx, hoty);
if (new_cursor == NULL)
return 0;
diff -ur fltk-1.3.2.org/src/Fl_Window.cxx fltk-1.3.2/src/Fl_Window.cxx
--- fltk-1.3.2.org/src/Fl_Window.cxx 2013-01-16 10:49:40.908130903 +0100
+++ fltk-1.3.2/src/Fl_Window.cxx 2013-01-16 10:49:55.557353865 +0100
@@ -23,6 +23,7 @@
#include <config.h>
#include <FL/Fl.H>
#include <FL/x.H>
+#include <FL/Fl_RGB_Image.H>
#include <FL/Fl_Window.H>
#include <stdlib.h>
#include "flstring.h"
@@ -45,7 +46,8 @@
}
i = 0;
xclass_ = 0;
- icon_ = 0;
+ icon_ = new icon_data;
+ memset(icon_, 0, sizeof(*icon_));
iconlabel_ = 0;
resizable(0);
size_range_set = 0;
@@ -264,16 +266,68 @@
}
}
+void Fl_Window::default_icon(const Fl_RGB_Image *icon) {
+ default_icons(&icon, 1);
+}
+
+void Fl_Window::default_icons(const Fl_RGB_Image **icons, int count) {
+ Fl_X::set_default_icons(icons, count);
+}
+
+void Fl_Window::icon(const Fl_RGB_Image *icon) {
+ icons(&icon, 1);
+}
+
+void Fl_Window::icons(const Fl_RGB_Image **icons, int count) {
+ free_icons();
+
+ if (count > 0) {
+ icon_->icons = new Fl_RGB_Image*[count];
+ icon_->count = count;
+ // FIXME: Fl_RGB_Image lacks const modifiers on methods
+ for (int i = 0;i < count;i++)
+ icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy();
+ }
+
+ if (i)
+ i->set_icons();
+}
+
/** Gets the current icon window target dependent data. */
const void *Fl_Window::icon() const {
- return icon_;
+ return icon_->legacy_icon;
}
/** Sets the current icon window target dependent data. */
void Fl_Window::icon(const void * ic) {
- icon_ = ic;
+ free_icons();
+ icon_->legacy_icon = ic;
}
+void Fl_Window::free_icons() {
+ int i;
+
+ icon_->legacy_icon = 0L;
+
+ if (icon_->icons) {
+ for (i = 0;i < icon_->count;i++)
+ delete icon_->icons[i];
+ delete [] icon_->icons;
+ icon_->icons = 0L;
+ }
+
+ icon_->count = 0;
+
+#ifdef WIN32
+ if (icon_->big_icon)
+ DestroyIcon(icon_->big_icon);
+ if (icon_->small_icon)
+ DestroyIcon(icon_->small_icon);
+
+ icon_->big_icon = NULL;
+ icon_->small_icon = NULL;
+#endif
+}
//
// End of "$Id: Fl_Window.cxx 9706 2012-11-06 20:46:14Z matt $".
diff -ur fltk-1.3.2.org/src/Fl_x.cxx fltk-1.3.2/src/Fl_x.cxx
--- fltk-1.3.2.org/src/Fl_x.cxx 2013-01-16 10:49:40.912227213 +0100
+++ fltk-1.3.2/src/Fl_x.cxx 2013-01-16 10:49:55.558137113 +0100
@@ -345,6 +345,7 @@
Atom fl_NET_WM_STATE;
Atom fl_NET_WM_STATE_FULLSCREEN;
Atom fl_NET_WORKAREA;
+Atom fl_NET_WM_ICON;
/*
X defines 32-bit-entities to have a format value of max. 32,
@@ -709,6 +710,7 @@
fl_NET_WM_STATE = XInternAtom(d, "_NET_WM_STATE", 0);
fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
fl_NET_WORKAREA = XInternAtom(d, "_NET_WORKAREA", 0);
+ fl_NET_WM_ICON = XInternAtom(d, "_NET_WM_ICON", 0);
if (sizeof(Atom) < 4)
atom_bits = sizeof(Atom) * 8;
@@ -2138,12 +2140,14 @@
fl_show_iconic = 0;
showit = 0;
}
- if (win->icon()) {
- hints->icon_pixmap = (Pixmap)win->icon();
+ if (win->icon_->legacy_icon) {
+ hints->icon_pixmap = (Pixmap)win->icon_->legacy_icon;
hints->flags |= IconPixmapHint;
}
XSetWMHints(fl_display, xp->xid, hints);
XFree(hints);
+
+ xp->set_icons();
}
// set the window type for menu and tooltip windows to avoid animations (compiz)
@@ -2263,6 +2267,93 @@
////////////////////////////////////////////////////////////////
+static unsigned long *default_net_wm_icons = 0L;
+static size_t default_net_wm_icons_size = 0;
+
+void icons_to_property(const Fl_RGB_Image *icons[], int count,
+ unsigned long **property, size_t *len) {
+ size_t sz;
+ unsigned long *data;
+
+ sz = 0;
+ for (int i = 0;i < count;i++)
+ sz += 2 + icons[i]->w() * icons[i]->h();
+
+ // FIXME: Might want to sort the icons
+
+ *property = data = new unsigned long[sz];
+ *len = sz;
+
+ for (int i = 0;i < count;i++) {
+ const Fl_RGB_Image *image;
+
+ image = icons[i];
+
+ data[0] = image->w();
+ data[1] = image->h();
+ data += 2;
+
+ const uchar *in = (const uchar*)*image->data();
+ for (int y = 0;y < image->h();y++) {
+ for (int x = 0;x < image->w();x++) {
+ switch (image->d()) {
+ case 1:
+ *data = ( 0xff<<24) | (in[0]<<16) | (in[0]<<8) | in[0];
+ break;
+ case 2:
+ *data = (in[1]<<24) | (in[0]<<16) | (in[0]<<8) | in[0];
+ break;
+ case 3:
+ *data = ( 0xff<<24) | (in[0]<<16) | (in[1]<<8) | in[2];
+ break;
+ case 4:
+ *data = (in[3]<<24) | (in[0]<<16) | (in[1]<<8) | in[2];
+ break;
+ }
+ in += image->d();
+ data++;
+ }
+ in += image->ld();
+ }
+ }
+}
+
+void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) {
+ if (default_net_wm_icons) {
+ delete [] default_net_wm_icons;
+ default_net_wm_icons = 0L;
+ default_net_wm_icons_size = 0;
+ }
+
+ if (count > 0)
+ icons_to_property(icons, count,
+ &default_net_wm_icons, &default_net_wm_icons_size);
+}
+
+void Fl_X::set_icons() {
+ unsigned long *net_wm_icons;
+ size_t net_wm_icons_size;
+
+ if (w->icon_->count) {
+ icons_to_property((const Fl_RGB_Image **)w->icon_->icons, w->icon_->count,
+ &net_wm_icons, &net_wm_icons_size);
+ } else {
+ net_wm_icons = default_net_wm_icons;
+ net_wm_icons_size = default_net_wm_icons_size;
+ }
+
+ XChangeProperty (fl_display, xid, fl_NET_WM_ICON, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*) net_wm_icons, net_wm_icons_size);
+
+ if (w->icon_->count) {
+ delete [] net_wm_icons;
+ net_wm_icons = 0L;
+ net_wm_icons_size = 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
int Fl_X::set_cursor(Fl_Cursor c) {
unsigned int shape;
Cursor xc;

View File

@@ -0,0 +1,131 @@
diff -up fltk-1.3.0r9619/FL/Fl.H.screen_num fltk-1.3.0r9619/FL/Fl.H
--- fltk-1.3.0r9619/FL/Fl.H.screen_num 2012-07-03 13:49:28.663085580 +0200
+++ fltk-1.3.0r9619/FL/Fl.H 2012-07-03 13:49:28.731084402 +0200
@@ -806,6 +806,8 @@ public:
static void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my);
static void screen_xywh(int &X, int &Y, int &W, int &H, int n);
static void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh);
+ static int screen_num(int x, int y);
+ static int screen_num(int x, int y, int w, int h);
static void screen_dpi(float &h, float &v, int n=0);
static void screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my);
static void screen_work_area(int &X, int &Y, int &W, int &H, int n);
diff -up fltk-1.3.0r9619/src/screen_xywh.cxx.screen_num fltk-1.3.0r9619/src/screen_xywh.cxx
--- fltk-1.3.0r9619/src/screen_xywh.cxx.screen_num 2012-03-23 17:47:53.000000000 +0100
+++ fltk-1.3.0r9619/src/screen_xywh.cxx 2012-07-03 13:58:01.947195396 +0200
@@ -215,21 +215,6 @@ int Fl::screen_count() {
return num_screens ? num_screens : 1;
}
-static int find_screen_with_point(int mx, int my) {
- int screen = 0;
- if (num_screens < 0) screen_init();
-
- for (int i = 0; i < num_screens; i ++) {
- int sx, sy, sw, sh;
- Fl::screen_xywh(sx, sy, sw, sh, i);
- if ((mx >= sx) && (mx < (sx+sw)) && (my >= sy) && (my < (sy+sh))) {
- screen = i;
- break;
- }
- }
- return screen;
-}
-
/**
Gets the bounding box of a screen
that contains the specified screen position \p mx, \p my
@@ -237,7 +222,7 @@ static int find_screen_with_point(int mx
\param[in] mx, my the absolute screen position
*/
void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) {
- screen_xywh(X, Y, W, H, find_screen_with_point(mx, my));
+ screen_xywh(X, Y, W, H, screen_num(mx, my));
}
@@ -248,7 +233,7 @@ void Fl::screen_xywh(int &X, int &Y, int
\param[in] mx, my the absolute screen position
*/
void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) {
- screen_work_area(X, Y, W, H, find_screen_with_point(mx, my));
+ screen_work_area(X, Y, W, H, screen_num(mx, my));
}
/**
@@ -321,6 +306,38 @@ void Fl::screen_xywh(int &X, int &Y, int
#endif // WIN32
}
+/**
+ Gets the screen bounding rect for the screen
+ which intersects the most with the rectangle
+ defined by \p mx, \p my, \p mw, \p mh.
+ \param[out] X,Y,W,H the corresponding screen bounding box
+ \param[in] mx, my, mw, mh the rectangle to search for intersection with
+ \see void screen_xywh(int &X, int &Y, int &W, int &H, int n)
+ */
+void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) {
+ screen_xywh(X, Y, W, H, screen_num(mx, my, mw, mh));
+}
+
+/**
+ Gets the screen number of a screen
+ that contains the specified screen position \p x, \p y
+ \param[in] x, y the absolute screen position
+*/
+int Fl::screen_num(int x, int y) {
+ int screen = 0;
+ if (num_screens < 0) screen_init();
+
+ for (int i = 0; i < num_screens; i ++) {
+ int sx, sy, sw, sh;
+ Fl::screen_xywh(sx, sy, sw, sh, i);
+ if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) {
+ screen = i;
+ break;
+ }
+ }
+ return screen;
+}
+
static inline float fl_intersection(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2) {
if(x1+w1 < x2 || x2+w2 < x1 || y1+h1 < y2 || y2+h2 < y1)
@@ -333,30 +350,27 @@ static inline float fl_intersection(int
}
/**
- Gets the screen bounding rect for the screen
+ Gets the screen number for the screen
which intersects the most with the rectangle
- defined by \p mx, \p my, \p mw, \p mh.
- \param[out] X,Y,W,H the corresponding screen bounding box
- \param[in] mx, my, mw, mh the rectangle to search for intersection with
- \see void screen_xywh(int &X, int &Y, int &W, int &H, int n)
+ defined by \p x, \p y, \p w, \p h.
+ \param[in] x, y, w, h the rectangle to search for intersection with
*/
-void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) {
+int Fl::screen_num(int x, int y, int w, int h) {
int best_screen = 0;
float best_intersection = 0.;
for(int i = 0; i < Fl::screen_count(); i++) {
int sx, sy, sw, sh;
Fl::screen_xywh(sx, sy, sw, sh, i);
- float sintersection = fl_intersection(mx, my, mw, mh, sx, sy, sw, sh);
+ float sintersection = fl_intersection(x, y, w, h, sx, sy, sw, sh);
if(sintersection > best_intersection) {
best_screen = i;
best_intersection = sintersection;
}
}
- screen_xywh(X, Y, W, H, best_screen);
+ return best_screen;
}
-
/**
Gets the screen resolution in dots-per-inch for the given screen.
\param[out] h, v horizontal and vertical resolution

View File

@@ -0,0 +1,468 @@
diff -urp fltk-1.3.2.org/FL/Fl_Window.H fltk-1.3.2/FL/Fl_Window.H
--- fltk-1.3.2.org/FL/Fl_Window.H 2013-01-16 10:52:33.017228122 +0100
+++ fltk-1.3.2/FL/Fl_Window.H 2013-01-16 10:52:47.876478968 +0100
@@ -54,7 +54,7 @@ class Fl_RGB_Image;
class FL_EXPORT Fl_Window : public Fl_Group {
static char *default_xclass_;
- // Note: we must use separate statements for each of the following 4 variables,
+ // Note: we must use separate statements for each of the following 8 variables,
// with the static attribute, otherwise MS VC++ 2008/2010 complains :-(
// AlbrechtS 04/2012
#if FLTK_ABI_VERSION < 10301
@@ -73,6 +73,22 @@ class FL_EXPORT Fl_Window : public Fl_Gr
static // when these members are static, ABI compatibility with 1.3.0 is respected
#endif
int no_fullscreen_h;
+#if FLTK_ABI_VERSION < 10302
+ static // when these members are static, ABI compatibility with 1.3.0 is respected
+#endif
+ int fullscreen_screen_top;
+#if FLTK_ABI_VERSION < 10302
+ static // when these members are static, ABI compatibility with 1.3.0 is respected
+#endif
+ int fullscreen_screen_bottom;
+#if FLTK_ABI_VERSION < 10302
+ static // when these members are static, ABI compatibility with 1.3.0 is respected
+#endif
+ int fullscreen_screen_left;
+#if FLTK_ABI_VERSION < 10302
+ static // when these members are static, ABI compatibility with 1.3.0 is respected
+#endif
+ int fullscreen_screen_right;
friend class Fl_X;
Fl_X *i; // points at the system-specific stuff
@@ -430,13 +446,15 @@ public:
*/
void show(int argc, char **argv);
/**
- Makes the window completely fill the screen, without any window
- manager border visible. You must use fullscreen_off() to undo
- this.
+ Makes the window completely fill one or more screens, without any
+ window manager border visible. You must use fullscreen_off() to
+ undo this.
\note On some platforms, this can result in the keyboard being
grabbed. The window may also be recreated, meaning hide() and
show() will be called.
+
+ \see void Fl_Window::fullscreen_screens()
*/
void fullscreen();
/**
@@ -453,6 +471,17 @@ public:
*/
unsigned int fullscreen_active() const { return flags() & FULLSCREEN; }
/**
+ Sets which screens should be used when this window is in fullscreen
+ mode. The window will be resized to the top of the screen with index
+ \p top, the bottom of the screen with index \p bottom, etc.
+
+ If this method is never called, or if any argument is < 0, then the
+ window will be resized to fill the screen it is currently on.
+
+ \see void Fl_Window::fullscreen()
+ */
+ void fullscreen_screens(int top, int bottom, int left, int right);
+ /**
Iconifies the window. If you call this when shown() is false
it will show() it as an icon. If the window is already
iconified this does nothing.
diff -urp fltk-1.3.2.org/FL/win32.H fltk-1.3.2/FL/win32.H
--- fltk-1.3.2.org/FL/win32.H 2013-01-16 10:52:33.017228122 +0100
+++ fltk-1.3.2/FL/win32.H 2013-01-16 10:52:47.876478968 +0100
@@ -80,6 +80,7 @@ public:
static Fl_X* i(const Fl_Window* w) {return w->i;}
static int fake_X_wm(const Fl_Window* w,int &X, int &Y,
int &bt,int &bx,int &by);
+ void make_fullscreen(int X, int Y, int W, int H);
void setwindow(Fl_Window* wi) {w=wi; wi->i=this;}
void flush() {w->flush();}
void set_minmax(LPMINMAXINFO minmax);
diff -urp fltk-1.3.2.org/src/Fl_cocoa.mm fltk-1.3.2/src/Fl_cocoa.mm
--- fltk-1.3.2.org/src/Fl_cocoa.mm 2013-01-16 10:52:33.014229574 +0100
+++ fltk-1.3.2/src/Fl_cocoa.mm 2013-01-16 10:52:47.877480606 +0100
@@ -2438,9 +2438,32 @@ void Fl_X::make(Fl_Window* w)
NSRect crect;
if (w->fullscreen_active()) {
- int sx, sy, sw, sh;
- Fl::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h());
- w->resize(sx, sy, sw, sh);
+ int top, bottom, left, right;
+ int sx, sy, sw, sh, X, Y, W, H;
+
+ top = w->fullscreen_screen_top;
+ bottom = w->fullscreen_screen_bottom;
+ left = w->fullscreen_screen_left;
+ right = w->fullscreen_screen_right;
+
+ if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
+ top = Fl::screen_num(w->x(), w->y(), w->w(), w->h());
+ bottom = top;
+ left = top;
+ right = top;
+ }
+
+ Fl::screen_xywh(sx, sy, sw, sh, top);
+ Y = sy;
+ Fl::screen_xywh(sx, sy, sw, sh, bottom);
+ H = sy + sh - Y;
+ Fl::screen_xywh(sx, sy, sw, sh, left);
+ X = sx;
+ Fl::screen_xywh(sx, sy, sw, sh, right);
+ W = sx + sw - X;
+
+ w->resize(X, Y, W, H);
+
winstyle = NSBorderlessWindowMask;
winlevel = NSStatusWindowLevel;
}
diff -urp fltk-1.3.2.org/src/Fl_win32.cxx fltk-1.3.2/src/Fl_win32.cxx
--- fltk-1.3.2.org/src/Fl_win32.cxx 2013-01-16 10:52:33.019230734 +0100
+++ fltk-1.3.2/src/Fl_win32.cxx 2013-01-16 10:52:47.878480504 +0100
@@ -1493,7 +1493,6 @@ int Fl_X::fake_X_wm(const Fl_Window* w,i
Y+=yoff;
if (w->fullscreen_active()) {
- X = Y = 0;
bx = by = bt = 0;
}
@@ -1547,19 +1546,42 @@ void Fl_Window::resize(int X,int Y,int W
}
}
-static void make_fullscreen(Fl_Window *w, Window xid, int X, int Y, int W, int H) {
+void Fl_X::make_fullscreen(int X, int Y, int W, int H) {
+ int top, bottom, left, right;
int sx, sy, sw, sh;
- Fl::screen_xywh(sx, sy, sw, sh, X, Y, W, H);
+
+ top = w->fullscreen_screen_top;
+ bottom = w->fullscreen_screen_bottom;
+ left = w->fullscreen_screen_left;
+ right = w->fullscreen_screen_right;
+
+ if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
+ top = Fl::screen_num(X, Y, W, H);
+ bottom = top;
+ left = top;
+ right = top;
+ }
+
+ Fl::screen_xywh(sx, sy, sw, sh, top);
+ Y = sy;
+ Fl::screen_xywh(sx, sy, sw, sh, bottom);
+ H = sy + sh - Y;
+ Fl::screen_xywh(sx, sy, sw, sh, left);
+ X = sx;
+ Fl::screen_xywh(sx, sy, sw, sh, right);
+ W = sx + sw - X;
+
DWORD flags = GetWindowLong(xid, GWL_STYLE);
flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
SetWindowLong(xid, GWL_STYLE, flags);
+
// SWP_NOSENDCHANGING is so that we can override size limits
- SetWindowPos(xid, HWND_TOP, sx, sy, sw, sh, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
+ SetWindowPos(xid, HWND_TOP, X, Y, W, H, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
}
void Fl_Window::fullscreen_x() {
_set_fullscreen();
- make_fullscreen(this, fl_xid(this), x(), y(), w(), h());
+ i->make_fullscreen(x(), y(), w(), h());
Fl::handle(FL_FULLSCREEN, this);
}
@@ -1814,8 +1836,8 @@ Fl_X* Fl_X::make(Fl_Window* w) {
monitor the window was placed on. */
RECT rect;
GetWindowRect(x->xid, &rect);
- make_fullscreen(w, x->xid, rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top);
+ x->make_fullscreen(rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top);
}
x->next = Fl_X::first;
diff -urp fltk-1.3.2.org/src/Fl_Window_fullscreen.cxx fltk-1.3.2/src/Fl_Window_fullscreen.cxx
--- fltk-1.3.2.org/src/Fl_Window_fullscreen.cxx 2012-11-06 21:46:14.000000000 +0100
+++ fltk-1.3.2/src/Fl_Window_fullscreen.cxx 2013-01-16 10:52:47.879480608 +0100
@@ -36,6 +36,10 @@ int Fl_Window::no_fullscreen_x = 0;
int Fl_Window::no_fullscreen_y = 0;
int Fl_Window::no_fullscreen_w = 0;
int Fl_Window::no_fullscreen_h = 0;
+int Fl_Window::fullscreen_screen_top = -1;
+int Fl_Window::fullscreen_screen_bottom = -1;
+int Fl_Window::fullscreen_screen_left = -1;
+int Fl_Window::fullscreen_screen_right = -1;
#endif
void Fl_Window::border(int b) {
@@ -95,6 +99,23 @@ void Fl_Window::fullscreen_off() {
fullscreen_off(no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h);
}
+void Fl_Window::fullscreen_screens(int top, int bottom, int left, int right) {
+ if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
+ fullscreen_screen_top = -1;
+ fullscreen_screen_bottom = -1;
+ fullscreen_screen_left = -1;
+ fullscreen_screen_right = -1;
+ } else {
+ fullscreen_screen_top = top;
+ fullscreen_screen_bottom = bottom;
+ fullscreen_screen_left = left;
+ fullscreen_screen_right = right;
+ }
+
+ if (shown() && (flags() & Fl_Widget::FULLSCREEN))
+ fullscreen_x();
+}
+
//
// End of "$Id: Fl_Window_fullscreen.cxx 9706 2012-11-06 20:46:14Z matt $".
diff -urp fltk-1.3.2.org/src/Fl_x.cxx fltk-1.3.2/src/Fl_x.cxx
--- fltk-1.3.2.org/src/Fl_x.cxx 2013-01-16 10:52:33.020228202 +0100
+++ fltk-1.3.2/src/Fl_x.cxx 2013-01-16 10:52:47.880480556 +0100
@@ -344,6 +344,7 @@ Atom fl_NET_WM_ICON_NAME; // utf8 aware
Atom fl_NET_SUPPORTING_WM_CHECK;
Atom fl_NET_WM_STATE;
Atom fl_NET_WM_STATE_FULLSCREEN;
+Atom fl_NET_WM_FULLSCREEN_MONITORS;
Atom fl_NET_WORKAREA;
Atom fl_NET_WM_ICON;
@@ -709,6 +710,7 @@ void fl_open_display(Display* d) {
fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
fl_NET_WM_STATE = XInternAtom(d, "_NET_WM_STATE", 0);
fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0);
+ fl_NET_WM_FULLSCREEN_MONITORS = XInternAtom(d, "_NET_WM_FULLSCREEN_MONITORS", 0);
fl_NET_WORKAREA = XInternAtom(d, "_NET_WORKAREA", 0);
fl_NET_WM_ICON = XInternAtom(d, "_NET_WM_ICON", 0);
@@ -1872,22 +1874,30 @@ void Fl_Window::resize(int X,int Y,int W
#define _NET_WM_STATE_ADD 1 /* add/set property */
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
-static void send_wm_state_event(Window wnd, int add, Atom prop) {
+static void send_wm_event(Window wnd, Atom message,
+ unsigned long d0, unsigned long d1=0,
+ unsigned long d2=0, unsigned long d3=0,
+ unsigned long d4=0) {
XEvent e;
e.xany.type = ClientMessage;
e.xany.window = wnd;
- e.xclient.message_type = fl_NET_WM_STATE;
+ e.xclient.message_type = message;
e.xclient.format = 32;
- e.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
- e.xclient.data.l[1] = prop;
- e.xclient.data.l[2] = 0;
- e.xclient.data.l[3] = 0;
- e.xclient.data.l[4] = 0;
+ e.xclient.data.l[0] = d0;
+ e.xclient.data.l[1] = d1;
+ e.xclient.data.l[2] = d2;
+ e.xclient.data.l[3] = d3;
+ e.xclient.data.l[4] = d4;
XSendEvent(fl_display, RootWindow(fl_display, fl_screen),
0, SubstructureNotifyMask | SubstructureRedirectMask,
&e);
}
+static void send_wm_state_event(Window wnd, int add, Atom prop) {
+ send_wm_event(wnd, fl_NET_WM_STATE,
+ add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, prop);
+}
+
int Fl_X::ewmh_supported() {
static int result = -1;
@@ -1911,6 +1921,22 @@ int Fl_X::ewmh_supported() {
/* Change an existing window to fullscreen */
void Fl_Window::fullscreen_x() {
if (Fl_X::ewmh_supported()) {
+ int top, bottom, left, right;
+
+ top = fullscreen_screen_top;
+ bottom = fullscreen_screen_bottom;
+ left = fullscreen_screen_left;
+ right = fullscreen_screen_right;
+
+ if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
+ top = Fl::screen_num(x(), y(), w(), h());
+ bottom = top;
+ left = top;
+ right = top;
+ }
+
+ send_wm_event(fl_xid(this), fl_NET_WM_FULLSCREEN_MONITORS,
+ top, bottom, left, right);
send_wm_state_event(fl_xid(this), 1, fl_NET_WM_STATE_FULLSCREEN);
} else {
_set_fullscreen();
@@ -1997,7 +2023,7 @@ void Fl_X::make_xid(Fl_Window* win, XVis
// force the window to be on-screen. Usually the X window manager
// does this, but a few don't, so we do it here for consistency:
int scr_x, scr_y, scr_w, scr_h;
- Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y);
+ Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H);
if (win->border()) {
// ensure border is on screen:
@@ -2026,6 +2052,23 @@ void Fl_X::make_xid(Fl_Window* win, XVis
return;
}
+ // Compute which screen(s) we should be on if we want to go fullscreen
+ int fullscreen_top, fullscreen_bottom, fullscreen_left, fullscreen_right;
+
+ fullscreen_top = win->fullscreen_screen_top;
+ fullscreen_bottom = win->fullscreen_screen_bottom;
+ fullscreen_left = win->fullscreen_screen_left;
+ fullscreen_right = win->fullscreen_screen_right;
+
+ if ((fullscreen_top < 0) || (fullscreen_bottom < 0) ||
+ (fullscreen_left < 0) || (fullscreen_right < 0)) {
+ fullscreen_top = Fl::screen_num(X, Y, W, H);
+ fullscreen_bottom = fullscreen_top;
+ fullscreen_left = fullscreen_top;
+ fullscreen_right = fullscreen_top;
+ }
+
+
ulong root = win->parent() ?
fl_xid(win->window()) : RootWindow(fl_display, fl_screen);
@@ -2049,9 +2092,17 @@ void Fl_X::make_xid(Fl_Window* win, XVis
// border, and cannot grab without an existing window. Besides,
// there is no clear_override().
if (win->flags() & Fl_Widget::FULLSCREEN && !Fl_X::ewmh_supported()) {
+ int sx, sy, sw, sh;
attr.override_redirect = 1;
mask |= CWOverrideRedirect;
- Fl::screen_xywh(X, Y, W, H, X, Y, W, H);
+ Fl::screen_xywh(sx, sy, sw, sh, fullscreen_left);
+ X = sx;
+ Fl::screen_xywh(sx, sy, sw, sh, fullscreen_right);
+ W = sx + sw - X;
+ Fl::screen_xywh(sx, sy, sw, sh, fullscreen_top);
+ Y = sy;
+ Fl::screen_xywh(sx, sy, sw, sh, fullscreen_bottom);
+ H = sy + sh - Y;
}
if (fl_background_pixel >= 0) {
@@ -2122,6 +2173,13 @@ void Fl_X::make_xid(Fl_Window* win, XVis
// If asked for, create fullscreen
if (win->flags() & Fl_Widget::FULLSCREEN && Fl_X::ewmh_supported()) {
+ unsigned long data[4];
+ data[0] = fullscreen_top;
+ data[1] = fullscreen_bottom;
+ data[2] = fullscreen_left;
+ data[3] = fullscreen_right;
+ XChangeProperty (fl_display, xp->xid, fl_NET_WM_FULLSCREEN_MONITORS, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) data, 4);
XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32,
PropModeAppend, (unsigned char*) &fl_NET_WM_STATE_FULLSCREEN, 1);
}
diff -urp fltk-1.3.2.org/test/fullscreen.cxx fltk-1.3.2/test/fullscreen.cxx
--- fltk-1.3.2.org/test/fullscreen.cxx 2012-06-14 17:09:46.000000000 +0200
+++ fltk-1.3.2/test/fullscreen.cxx 2013-01-16 10:52:47.881104801 +0100
@@ -127,7 +127,7 @@ class fullscreen_window : public Fl_Sing
fullscreen_window(int W, int H, const char *t=0);
int handle (int e);
Fl_Toggle_Light_Button *b3;
-
+ Fl_Toggle_Light_Button *b4;
};
fullscreen_window::fullscreen_window(int W, int H, const char *t) : Fl_Single_Window(W, H, t) {
@@ -170,23 +170,54 @@ void border_cb(Fl_Widget *o, void *p) {
#endif
}
-int px,py,pw,ph;
Fl_Button *border_button;
void fullscreen_cb(Fl_Widget *o, void *p) {
Fl_Window *w = (Fl_Window *)p;
int d = ((Fl_Button *)o)->value();
if (d) {
- px = w->x();
- py = w->y();
- pw = w->w();
- ph = w->h();
+ if (((fullscreen_window*)w)->b4->value()) {
+ int top, bottom, left, right;
+ int top_y, bottom_y, left_x, right_x;
+
+ int sx, sy, sw, sh;
+
+ top = bottom = left = right = 0;
+
+ Fl::screen_xywh(sx, sy, sw, sh, 0);
+ top_y = sy;
+ bottom_y = sy + sh;
+ left_x = sx;
+ right_x = sx + sw;
+
+ for (int i = 1;i < Fl::screen_count();i++) {
+ Fl::screen_xywh(sx, sy, sw, sh, i);
+ if (sy < top_y) {
+ top = i;
+ top_y = sy;
+ }
+ if ((sy + sh) > bottom_y) {
+ bottom = i;
+ bottom_y = sy + sh;
+ }
+ if (sx < left_x) {
+ left = i;
+ left_x = sx;
+ }
+ if ((sx + sw) > right_x) {
+ right = i;
+ right_x = sx + sw;
+ }
+ }
+
+ w->fullscreen_screens(top, bottom, left, right);
+ } else {
+ w->fullscreen_screens(-1, -1, -1, -1);
+ }
w->fullscreen();
- w->override();
#ifndef WIN32 // update our border state in case border was turned off
border_button->value(w->border());
#endif
} else {
- //w->fullscreen_off(px,py,pw,ph);
w->fullscreen_off();
}
}
@@ -219,7 +250,7 @@ void exit_cb(Fl_Widget *, void *) {
exit(0);
}
-#define NUMB 7
+#define NUMB 8
int twowindow = 0;
int initfull = 0;
@@ -284,6 +315,9 @@ int main(int argc, char **argv) {
window.b3->callback(fullscreen_cb,w);
y+=30;
+ window.b4 = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"All Screens");
+ y+=30;
+
Fl_Button eb(50,y,window.w()-60,30,"Exit");
eb.callback(exit_cb);
y+=30;

View File

@@ -0,0 +1,203 @@
diff -up fltk-1.3.2/FL/Fl.H.xhandlers fltk-1.3.2/FL/Fl.H
--- fltk-1.3.2/FL/Fl.H.xhandlers 2014-07-22 15:23:18.087334467 +0200
+++ fltk-1.3.2/FL/Fl.H 2014-07-22 15:23:18.094334589 +0200
@@ -96,6 +96,9 @@ typedef void (*Fl_FD_Handler)(FL_SOCKET
/** Signature of add_handler functions passed as parameters */
typedef int (*Fl_Event_Handler)(int event);
+/** Signature of add_system_handler functions passed as parameters */
+typedef int (*Fl_System_Handler)(void *event, void *data);
+
/** Signature of set_abort functions passed as parameters */
typedef void (*Fl_Abort_Handler)(const char *format,...);
@@ -712,6 +715,8 @@ public:
static void focus(Fl_Widget*);
static void add_handler(Fl_Event_Handler h);
static void remove_handler(Fl_Event_Handler h);
+ static void add_system_handler(Fl_System_Handler h, void *data);
+ static void remove_system_handler(Fl_System_Handler h);
static void event_dispatch(Fl_Event_Dispatch d);
static Fl_Event_Dispatch event_dispatch();
/** @} */
diff -up fltk-1.3.2/src/Fl_cocoa.mm.xhandlers fltk-1.3.2/src/Fl_cocoa.mm
--- fltk-1.3.2/src/Fl_cocoa.mm.xhandlers 2014-07-22 15:23:18.089334502 +0200
+++ fltk-1.3.2/src/Fl_cocoa.mm 2014-07-22 15:23:18.095334607 +0200
@@ -1269,6 +1269,8 @@ void fl_open_callback(void (*cb)(const c
}
@end
+extern int fl_send_system_handlers(void *e);
+
static void clipboard_check(void);
@implementation FLApplication
@@ -1276,6 +1278,10 @@ static void clipboard_check(void);
{
// update clipboard status
clipboard_check();
+
+ if (fl_send_system_handlers(theEvent))
+ return;
+
NSEventType type = [theEvent type];
if (type == NSLeftMouseDown) {
fl_lock_function();
diff -up fltk-1.3.2/src/Fl.cxx.xhandlers fltk-1.3.2/src/Fl.cxx
--- fltk-1.3.2/src/Fl.cxx.xhandlers 2014-07-22 15:23:18.085334432 +0200
+++ fltk-1.3.2/src/Fl.cxx 2014-07-22 15:23:18.095334607 +0200
@@ -891,6 +891,83 @@ static int send_handlers(int e) {
return 0;
}
+
+////////////////////////////////////////////////////////////////
+// System event handlers:
+
+
+struct system_handler_link {
+ Fl_System_Handler handle;
+ void *data;
+ system_handler_link *next;
+};
+
+
+static system_handler_link *sys_handlers = 0;
+
+
+/**
+ \brief Install a function to intercept system events.
+
+ FLTK calls each of these functions as soon as a new system event is
+ received. The processing will stop at the first function to return
+ non-zero. If all functions return zero then the event is passed on
+ for normal handling by FLTK.
+
+ Each function will be called with a pointer to the system event as
+ the first argument and \p data as the second argument. The system
+ event pointer will always be void *, but will point to different
+ objects depending on the platform:
+ - X11: XEvent
+ - Windows: MSG
+ - OS X: NSEvent
+
+ \param ha The event handler function to register
+ \param data User data to include on each call
+
+ \see Fl::remove_system_handler(Fl_System_Handler)
+*/
+void Fl::add_system_handler(Fl_System_Handler ha, void *data) {
+ system_handler_link *l = new system_handler_link;
+ l->handle = ha;
+ l->data = data;
+ l->next = sys_handlers;
+ sys_handlers = l;
+}
+
+
+/**
+ Removes a previously added system event handler.
+
+ \param ha The event handler function to remove
+
+ \see Fl::add_system_handler(Fl_System_Handler)
+*/
+void Fl::remove_system_handler(Fl_System_Handler ha) {
+ system_handler_link *l, *p;
+
+ // Search for the handler in the list...
+ for (l = sys_handlers, p = 0; l && l->handle != ha; p = l, l = l->next);
+
+ if (l) {
+ // Found it, so remove it from the list...
+ if (p) p->next = l->next;
+ else sys_handlers = l->next;
+
+ // And free the record...
+ delete l;
+ }
+}
+
+int fl_send_system_handlers(void *e) {
+ for (const system_handler_link *hl = sys_handlers; hl; hl = hl->next) {
+ if (hl->handle(e, hl->data))
+ return 1;
+ }
+ return 0;
+}
+
+
////////////////////////////////////////////////////////////////
Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
diff -up fltk-1.3.2/src/Fl_win32.cxx.xhandlers fltk-1.3.2/src/Fl_win32.cxx
--- fltk-1.3.2/src/Fl_win32.cxx.xhandlers 2014-07-22 15:23:18.092334554 +0200
+++ fltk-1.3.2/src/Fl_win32.cxx 2014-07-22 15:24:44.682843610 +0200
@@ -336,6 +336,8 @@ void* Fl::thread_message() {
return r;
}
+extern int fl_send_system_handlers(void *e);
+
IActiveIMMApp *fl_aimm = NULL;
MSG fl_msg;
@@ -401,23 +403,21 @@ int fl_wait(double time_to_wait) {
// Execute the message we got, and all other pending messages:
// have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
- have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
- if (have_message > 0) {
- while (have_message != 0 && have_message != -1) {
- if (fl_msg.message == fl_wake_msg) {
- // Used for awaking wait() from another thread
- thread_message_ = (void*)fl_msg.wParam;
- Fl_Awake_Handler func;
- void *data;
- while (Fl::get_awake_handler_(func, data)==0) {
- func(data);
- }
- }
-
- TranslateMessage(&fl_msg);
- DispatchMessageW(&fl_msg);
- have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ while ((have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE)) > 0) {
+ if (fl_send_system_handlers(&fl_msg))
+ continue;
+
+ if (fl_msg.message == fl_wake_msg) {
+ // Used for awaking wait() from another thread
+ thread_message_ = (void*)fl_msg.wParam;
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0)
+ func(data);
}
+
+ TranslateMessage(&fl_msg);
+ DispatchMessageW(&fl_msg);
}
Fl::flush();
diff -up fltk-1.3.2/src/Fl_x.cxx.xhandlers fltk-1.3.2/src/Fl_x.cxx
--- fltk-1.3.2/src/Fl_x.cxx.xhandlers 2014-07-22 15:23:18.093334572 +0200
+++ fltk-1.3.2/src/Fl_x.cxx 2014-07-22 15:23:18.096334624 +0200
@@ -188,6 +188,8 @@ void Fl::remove_fd(int n) {
remove_fd(n, -1);
}
+extern int fl_send_system_handlers(void *e);
+
#if CONSOLIDATE_MOTION
static Fl_Window* send_motion;
extern Fl_Window* fl_xmousewin;
@@ -198,6 +200,8 @@ static void do_queued_events() {
while (XEventsQueued(fl_display,QueuedAfterReading)) {
XEvent xevent;
XNextEvent(fl_display, &xevent);
+ if (fl_send_system_handlers(&xevent))
+ continue;
fl_handle(xevent);
}
// we send FL_LEAVE only if the mouse did not enter some other window:

View File

@@ -0,0 +1,582 @@
diff -up fltk-1.3.2/FL/Fl.H.im fltk-1.3.2/FL/Fl.H
--- fltk-1.3.2/FL/Fl.H.im 2014-09-10 14:40:05.193265424 +0200
+++ fltk-1.3.2/FL/Fl.H 2014-09-10 14:40:05.196265471 +0200
@@ -699,6 +699,17 @@ public:
static int event_inside(const Fl_Widget*);
static int test_shortcut(Fl_Shortcut);
+ /**
+ Enables the system input methods facilities. This is the default.
+ \see disable_im()
+ */
+ static void enable_im();
+ /**
+ Disables the system input methods facilities.
+ \see enable_im()
+ */
+ static void disable_im();
+
// event destinations:
static int handle(int, Fl_Window*);
static int handle_(int, Fl_Window*);
diff -up fltk-1.3.2/FL/win32.H.im fltk-1.3.2/FL/win32.H
--- fltk-1.3.2/FL/win32.H.im 2014-09-10 14:40:05.186265315 +0200
+++ fltk-1.3.2/FL/win32.H 2014-09-10 14:40:05.196265471 +0200
@@ -102,6 +102,8 @@ extern FL_EXPORT void fl_save_dc( HWND w
inline Window fl_xid(const Fl_Window* w) { Fl_X *temp = Fl_X::i(w); return temp ? temp->xid : 0; }
+extern FL_EXPORT void fl_open_display();
+
#else
FL_EXPORT Window fl_xid_(const Fl_Window* w);
#define fl_xid(w) fl_xid_(w)
diff -up fltk-1.3.2/src/Fl_cocoa.mm.im fltk-1.3.2/src/Fl_cocoa.mm
--- fltk-1.3.2/src/Fl_cocoa.mm.im 2014-09-10 14:40:05.193265424 +0200
+++ fltk-1.3.2/src/Fl_cocoa.mm 2014-09-10 14:43:41.103642243 +0200
@@ -88,6 +88,7 @@ static void createAppleMenu(void);
static Fl_Region MacRegionMinusRect(Fl_Region r, int x,int y,int w,int h);
static void cocoaMouseHandler(NSEvent *theEvent);
static int calc_mac_os_version();
+static void im_update(void);
static Fl_Quartz_Graphics_Driver fl_quartz_driver;
static Fl_Display_Device fl_quartz_display(&fl_quartz_driver);
@@ -108,6 +109,30 @@ int fl_mac_os_version = calc_mac_os_vers
static int got_events = 0;
static Fl_Window* resize_from_system;
static int main_screen_height; // height of menubar-containing screen used to convert between Cocoa and FLTK global screen coordinates
+static int im_enabled = -1;
+
+// Carbon functions and definitions
+
+typedef void *TSMDocumentID;
+
+extern "C" enum {
+ kTSMDocumentEnabledInputSourcesPropertyTag = 'enis' // from Carbon/TextServices.h
+};
+
+// Undocumented voodoo. Taken from Mozilla.
+static const int smEnableRomanKybdsOnly = -23;
+
+typedef TSMDocumentID (*TSMGetActiveDocument_type)(void);
+static TSMGetActiveDocument_type TSMGetActiveDocument;
+typedef OSStatus (*TSMSetDocumentProperty_type)(TSMDocumentID, OSType, UInt32, void*);
+static TSMSetDocumentProperty_type TSMSetDocumentProperty;
+typedef OSStatus (*TSMRemoveDocumentProperty_type)(TSMDocumentID, OSType);
+static TSMRemoveDocumentProperty_type TSMRemoveDocumentProperty;
+typedef CFArrayRef (*TISCreateASCIICapableInputSourceList_type)(void);
+static TISCreateASCIICapableInputSourceList_type TISCreateASCIICapableInputSourceList;
+
+typedef void (*KeyScript_type)(short);
+static KeyScript_type KeyScript;
#if CONSOLIDATE_MOTION
static Fl_Window* send_motion;
@@ -978,6 +1003,7 @@ void fl_open_callback(void (*cb)(const c
#endif
{
BOOL seen_open_file;
+ TSMDocumentID currentDoc;
}
- (void)windowDidMove:(NSNotification *)notif;
- (void)windowDidResize:(NSNotification *)notif;
@@ -991,6 +1017,7 @@ void fl_open_callback(void (*cb)(const c
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
- (void)applicationDidBecomeActive:(NSNotification *)notify;
- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification;
+- (void)applicationDidUpdate:(NSNotification *)aNotification;
- (void)applicationWillResignActive:(NSNotification *)notify;
- (void)applicationWillHide:(NSNotification *)notify;
- (void)applicationWillUnhide:(NSNotification *)notify;
@@ -1175,6 +1202,23 @@ void fl_open_callback(void (*cb)(const c
}
Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
}
+- (void)applicationDidUpdate:(NSNotification *)aNotification
+{
+ if ((fl_mac_os_version >= 100500) && (im_enabled != -1) &&
+ (TSMGetActiveDocument != NULL)) {
+ TSMDocumentID newDoc;
+ // It is extremely unclear when Cocoa decides to create/update
+ // the input context, but debugging reveals that it is done
+ // by NSApplication:updateWindows. So check if the input context
+ // has shifted after each such run so that we can update our
+ // input methods status.
+ newDoc = TSMGetActiveDocument();
+ if (newDoc != currentDoc) {
+ im_update();
+ currentDoc = newDoc;
+ }
+ }
+}
- (void)applicationWillResignActive:(NSNotification *)notify
{
fl_lock_function();
@@ -1322,6 +1365,13 @@ void fl_open_display() {
static char beenHereDoneThat = 0;
if ( !beenHereDoneThat ) {
beenHereDoneThat = 1;
+
+ TSMGetActiveDocument = (TSMGetActiveDocument_type)Fl_X::get_carbon_function("TSMGetActiveDocument");
+ TSMSetDocumentProperty = (TSMSetDocumentProperty_type)Fl_X::get_carbon_function("TSMSetDocumentProperty");
+ TSMRemoveDocumentProperty = (TSMRemoveDocumentProperty_type)Fl_X::get_carbon_function("TSMRemoveDocumentProperty");
+ TISCreateASCIICapableInputSourceList = (TISCreateASCIICapableInputSourceList_type)Fl_X::get_carbon_function("TISCreateASCIICapableInputSourceList");
+
+ KeyScript = (KeyScript_type)Fl_X::get_carbon_function("KeyScript");
BOOL need_new_nsapp = (NSApp == nil);
if (need_new_nsapp) [NSApplication sharedApplication];
@@ -1390,6 +1440,66 @@ void fl_open_display() {
void fl_close_display() {
}
+// Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
+// Safari people seem to think implies turning off advanced IME stuff
+// (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
+// in Safari/Webcore). Should be good enough for us then...
+
+static void im_update(void) {
+ if (fl_mac_os_version >= 100500) {
+ TSMDocumentID doc;
+
+ if ((TSMGetActiveDocument == NULL) ||
+ (TSMSetDocumentProperty == NULL) ||
+ (TSMRemoveDocumentProperty == NULL) ||
+ (TISCreateASCIICapableInputSourceList == NULL))
+ return;
+
+ doc = TSMGetActiveDocument();
+
+ if (im_enabled)
+ TSMRemoveDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag);
+ else {
+ CFArrayRef inputSources;
+
+ inputSources = TISCreateASCIICapableInputSourceList();
+ TSMSetDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag,
+ sizeof(CFArrayRef), &inputSources);
+ CFRelease(inputSources);
+ }
+ } else {
+ if (KeyScript == NULL)
+ return;
+
+ if (im_enabled)
+ KeyScript(smKeyEnableKybds);
+ else
+ KeyScript(smEnableRomanKybdsOnly);
+ }
+}
+
+void Fl::enable_im() {
+ fl_open_display();
+
+ im_enabled = 1;
+
+ if (fl_mac_os_version >= 100500)
+ [NSApp updateWindows];
+ else
+ im_update();
+}
+
+void Fl::disable_im() {
+ fl_open_display();
+
+ im_enabled = 0;
+
+ if (fl_mac_os_version >= 100500)
+ [NSApp updateWindows];
+ else
+ im_update();
+}
+
// Gets the border sizes and the titlebar size
static void get_window_frame_sizes(int &bx, int &by, int &bt) {
diff -up fltk-1.3.2/src/Fl.cxx.im fltk-1.3.2/src/Fl.cxx
--- fltk-1.3.2/src/Fl.cxx.im 2014-09-10 14:40:05.194265440 +0200
+++ fltk-1.3.2/src/Fl.cxx 2014-09-10 14:40:05.197265486 +0200
@@ -593,45 +593,6 @@ int Fl::run() {
return 0;
}
-#ifdef WIN32
-
-// Function to initialize COM/OLE for usage. This must be done only once.
-// We define a flag to register whether we called it:
-static char oleInitialized = 0;
-
-// This calls the Windows function OleInitialize() exactly once.
-void fl_OleInitialize() {
- if (!oleInitialized) {
- OleInitialize(0L);
- oleInitialized = 1;
- }
-}
-
-// This calls the Windows function OleUninitialize() only, if
-// OleInitialize has been called before.
-void fl_OleUninitialize() {
- if (oleInitialized) {
- OleUninitialize();
- oleInitialized = 0;
- }
-}
-
-class Fl_Win32_At_Exit {
-public:
- Fl_Win32_At_Exit() { }
- ~Fl_Win32_At_Exit() {
- fl_free_fonts(); // do some WIN32 cleanup
- fl_cleanup_pens();
- fl_OleUninitialize();
- fl_brush_action(1);
- fl_cleanup_dc_list();
- }
-};
-static Fl_Win32_At_Exit win32_at_exit;
-#endif
-
-
-
/**
Waits until "something happens" and then returns. Call this
repeatedly to "run" your program. You can also check what happened
diff -up fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx.im fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx
--- fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx.im 2012-06-26 09:03:46.000000000 +0200
+++ fltk-1.3.2/src/Fl_Native_File_Chooser_WIN32.cxx 2014-09-10 14:40:05.197265486 +0200
@@ -34,6 +34,7 @@ LPCWSTR utf8towchar(const char *in); //M
char *wchartoutf8(LPCWSTR in); //MG
#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/x.H>
#define LCURLY_CHR '{'
#define RCURLY_CHR '}'
@@ -41,8 +42,6 @@ char *wchartoutf8(LPCWSTR in); //MG
#define RBRACKET_CHR ']'
#define MAXFILTERS 80
-void fl_OleInitialize(); // in Fl.cxx (Windows only)
-
// STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG)
#ifdef DEBUG
static void dnullprint(char *wp) {
@@ -471,7 +470,7 @@ int CALLBACK Fl_Native_File_Chooser::Dir
// SHOW DIRECTORY BROWSER
int Fl_Native_File_Chooser::showdir() {
// initialize OLE only once
- fl_OleInitialize(); // init needed by BIF_USENEWUI
+ fl_open_display(); // init needed by BIF_USENEWUI
ClearBINF();
clear_pathnames();
// PARENT WINDOW
diff -up fltk-1.3.2/src/Fl_win32.cxx.im fltk-1.3.2/src/Fl_win32.cxx
--- fltk-1.3.2/src/Fl_win32.cxx.im 2014-09-10 14:40:05.194265440 +0200
+++ fltk-1.3.2/src/Fl_win32.cxx 2014-09-10 14:40:05.197265486 +0200
@@ -60,8 +60,6 @@
#include <ole2.h>
#include <shellapi.h>
-#include "aimm.h"
-
//
// USE_ASYNC_SELECT - define it if you have WSAAsyncSelect()...
// USE_ASYNC_SELECT is OBSOLETED in 1.3 for the following reasons:
@@ -121,27 +119,24 @@ static HMODULE get_wsock_mod() {
* size and link dependencies.
*/
static HMODULE s_imm_module = 0;
+typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
+static flTypeImmAssociateContextEx flImmAssociateContextEx = 0;
typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
static flTypeImmGetContext flImmGetContext = 0;
typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
static flTypeImmSetCompositionWindow flImmSetCompositionWindow = 0;
typedef BOOL (WINAPI* flTypeImmReleaseContext)(HWND, HIMC);
static flTypeImmReleaseContext flImmReleaseContext = 0;
-typedef BOOL (WINAPI* flTypeImmIsIME)(HKL);
-static flTypeImmIsIME flImmIsIME = 0;
-static HMODULE get_imm_module() {
- if (!s_imm_module) {
- s_imm_module = LoadLibrary("IMM32.DLL");
- if (!s_imm_module)
- Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
- "Please check your input method manager library accessibility.");
- flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
- flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
- flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
- flImmIsIME = (flTypeImmIsIME)GetProcAddress(s_imm_module, "ImmIsIME");
- }
- return s_imm_module;
+static void get_imm_module() {
+ s_imm_module = LoadLibrary("IMM32.DLL");
+ if (!s_imm_module)
+ Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
+ "Please check your input method manager library accessibility.");
+ flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
+ flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
+ flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
+ flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
}
// USE_TRACK_MOUSE - define NO_TRACK_MOUSE if you don't have
@@ -259,7 +254,9 @@ void fl_set_spot(int font, int size, int
Fl_Window* tw = win;
while (tw->parent()) tw = tw->window(); // find top level window
- get_imm_module();
+ if (!tw->shown())
+ return;
+
HIMC himc = flImmGetContext(fl_xid(tw));
if (himc) {
@@ -338,7 +335,6 @@ void* Fl::thread_message() {
extern int fl_send_system_handlers(void *e);
-IActiveIMMApp *fl_aimm = NULL;
MSG fl_msg;
// This is never called with time_to_wait < 0.0.
@@ -441,6 +437,58 @@ int fl_ready() {
return get_wsock_mod() ? s_wsock_select(0,&fdt[0],&fdt[1],&fdt[2],&t) : 0;
}
+void fl_open_display() {
+ static char beenHereDoneThat = 0;
+
+ if (beenHereDoneThat)
+ return;
+
+ beenHereDoneThat = 1;
+
+ OleInitialize(0L);
+
+ get_imm_module();
+}
+
+class Fl_Win32_At_Exit {
+public:
+ Fl_Win32_At_Exit() { }
+ ~Fl_Win32_At_Exit() {
+ fl_free_fonts(); // do some WIN32 cleanup
+ fl_cleanup_pens();
+ OleUninitialize();
+ fl_brush_action(1);
+ fl_cleanup_dc_list();
+ }
+};
+static Fl_Win32_At_Exit win32_at_exit;
+
+static char im_enabled = 1;
+
+void Fl::enable_im() {
+ fl_open_display();
+
+ Fl_X* i = Fl_X::first;
+ while (i) {
+ flImmAssociateContextEx(i->xid, 0, IACE_DEFAULT);
+ i = i->next;
+ }
+
+ im_enabled = 1;
+}
+
+void Fl::disable_im() {
+ fl_open_display();
+
+ Fl_X* i = Fl_X::first;
+ while (i) {
+ flImmAssociateContextEx(i->xid, 0, 0);
+ i = i->next;
+ }
+
+ im_enabled = 0;
+}
+
////////////////////////////////////////////////////////////////
int Fl::x()
@@ -683,7 +731,6 @@ void fl_clipboard_notify_untarget(HWND w
}
////////////////////////////////////////////////////////////////
-char fl_is_ime = 0;
void fl_get_codepage()
{
HKL hkl = GetKeyboardLayout(0);
@@ -691,14 +738,8 @@ void fl_get_codepage()
GetLocaleInfo (LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE, ld, 6);
DWORD ccp = atol(ld);
- fl_is_ime = 0;
fl_codepage = ccp;
- if (fl_aimm) {
- fl_aimm->GetCodePageA(GetKeyboardLayout(0), &fl_codepage);
- } else if (get_imm_module() && flImmIsIME(hkl)) {
- fl_is_ime = 1;
- }
}
HWND fl_capture;
@@ -1564,6 +1605,8 @@ int fl_disable_transient_for; // secret
Fl_X* Fl_X::make(Fl_Window* w) {
Fl_Group::current(0); // get rid of very common user bug: forgot end()
+ fl_open_display();
+
// if the window is a subwindow and our parent is not mapped yet, we
// mark this window visible, so that mapping the parent at a later
// point in time will call this function again to finally map the subwindow.
@@ -1767,16 +1810,10 @@ Fl_X* Fl_X::make(Fl_Window* w) {
(Fl::grab() || (styleEx & WS_EX_TOOLWINDOW)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
// Register all windows for potential drag'n'drop operations
- fl_OleInitialize();
RegisterDragDrop(x->xid, flIDropTarget);
- if (!fl_aimm) {
- CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER,
- IID_IActiveIMMApp, (void**) &fl_aimm);
- if (fl_aimm) {
- fl_aimm->Activate(TRUE);
- }
- }
+ if (!im_enabled)
+ flImmAssociateContextEx(x->xid, 0, 0);
return x;
}
diff -up fltk-1.3.2/src/Fl_x.cxx.im fltk-1.3.2/src/Fl_x.cxx
--- fltk-1.3.2/src/Fl_x.cxx.im 2014-09-10 14:40:05.194265440 +0200
+++ fltk-1.3.2/src/Fl_x.cxx 2014-09-10 14:40:05.198265502 +0200
@@ -313,6 +313,7 @@ XVisualInfo *fl_visual;
Colormap fl_colormap;
XIM fl_xim_im = 0;
XIC fl_xim_ic = 0;
+Window fl_xim_win = 0;
char fl_is_over_the_spot = 0;
static XRectangle status_area;
@@ -603,6 +604,55 @@ void fl_init_xim() {
if(xim_styles) XFree(xim_styles);
}
+void fl_xim_deactivate(void);
+
+void fl_xim_activate(Window xid) {
+ if (!fl_xim_im)
+ return;
+
+ // If the focused window has changed, then use the brute force method
+ // of completely recreating the input context.
+ if (fl_xim_win != xid) {
+ fl_xim_deactivate();
+
+ fl_new_ic();
+ fl_xim_win = xid;
+
+ XSetICValues(fl_xim_ic,
+ XNFocusWindow, fl_xim_win,
+ XNClientWindow, fl_xim_win,
+ NULL);
+ }
+
+ fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
+}
+
+void fl_xim_deactivate(void) {
+ if (!fl_xim_ic)
+ return;
+
+ XDestroyIC(fl_xim_ic);
+ fl_xim_ic = NULL;
+
+ fl_xim_win = 0;
+}
+
+void Fl::enable_im() {
+ Fl_Window *win;
+
+ win = Fl::first_window();
+ if (win && win->shown()) {
+ fl_xim_activate(fl_xid(win));
+ XSetICFocus(fl_xim_ic);
+ } else {
+ fl_new_ic();
+ }
+}
+
+void Fl::disable_im() {
+ fl_xim_deactivate();
+}
+
void fl_open_display() {
if (fl_display) return;
@@ -1053,10 +1103,9 @@ int fl_handle(const XEvent& thisevent)
XEvent xevent = thisevent;
fl_xevent = &thisevent;
Window xid = xevent.xany.window;
- static Window xim_win = 0;
if (fl_xim_ic && xevent.type == DestroyNotify &&
- xid != xim_win && !fl_find(xid))
+ xid != fl_xim_win && !fl_find(xid))
{
XIM xim_im;
xim_im = XOpenIM(fl_display, NULL, NULL, NULL);
@@ -1072,46 +1121,9 @@ int fl_handle(const XEvent& thisevent)
}
if (fl_xim_ic && (xevent.type == FocusIn))
- {
-#define POOR_XIM
-#ifdef POOR_XIM
- if (xim_win != xid)
- {
- xim_win = xid;
- XDestroyIC(fl_xim_ic);
- fl_xim_ic = NULL;
- fl_new_ic();
- XSetICValues(fl_xim_ic,
- XNFocusWindow, xevent.xclient.window,
- XNClientWindow, xid,
- NULL);
- }
- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
-#else
- if (Fl::first_window() && Fl::first_window()->modal()) {
- Window x = fl_xid(Fl::first_window());
- if (x != xim_win) {
- xim_win = x;
- XSetICValues(fl_xim_ic,
- XNFocusWindow, xim_win,
- XNClientWindow, xim_win,
- NULL);
- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
- }
- } else if (xim_win != xid && xid) {
- xim_win = xid;
- XSetICValues(fl_xim_ic,
- XNFocusWindow, xevent.xclient.window,
- XNClientWindow, xid,
- //XNFocusWindow, xim_win,
- //XNClientWindow, xim_win,
- NULL);
- fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height);
- }
-#endif
- }
+ fl_xim_activate(xid);
- if ( XFilterEvent((XEvent *)&xevent, 0) )
+ if (fl_xim_ic && XFilterEvent((XEvent *)&xevent, 0))
return(1);
#if USE_XRANDR

View File

@@ -0,0 +1,67 @@
>From 7a15d1c9a908afe429c1aba1c27516d18bdea299 Mon Sep 17 00:00:00 2001
From: DRC <information@virtualgl.org>
Date: Tue, 26 Feb 2013 03:37:12 -0600
Subject: [PATCH 1/4] Add BUILD_STATIC feature from TigerVNC to (optionally)
prevent FLTK from depending on libgcc and libstdc++
---
CMakeLists.txt | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1ee285..7d9d94b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -150,6 +150,49 @@ mark_as_advanced(LIB_CAIRO LIB_fontconfig LIB_freetype)
mark_as_advanced(LIB_GL LIB_MesaGL)
mark_as_advanced(LIB_jpeg LIB_png LIB_zlib)
+# This ensures that we don't depend on libstdc++ or libgcc
+if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE AND NOT CYGWIN)
+ option(BUILD_STATIC
+ "Link statically against libgcc and libstdc++, if possible" OFF)
+ if(BUILD_STATIC)
+ # For some reason, simply passing ${CMAKE_CXX_FLAGS} to the compiler in
+ # execute_process() doesn't work. Grrr...
+ if(CMAKE_SIZEOF_VOID_P MATCHES 8)
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} -m64
+ --print-file-name=libstdc++.a OUTPUT_VARIABLE LIBSTDCPLUSPLUS
+ RESULT_VARIABLE RESULT)
+ else()
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} -m32
+ --print-file-name=libstdc++.a OUTPUT_VARIABLE LIBSTDCPLUSPLUS
+ RESULT_VARIABLE RESULT)
+ endif()
+ string(REGEX REPLACE "\n" "" LIBSTDCPLUSPLUS ${LIBSTDCPLUSPLUS})
+ if(RESULT MATCHES 0 AND LIBSTDCPLUSPLUS)
+ message(STATUS "Linking with static libstdc++:\n ${LIBSTDCPLUSPLUS}")
+ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/staticlib)
+ execute_process(COMMAND ${CMAKE_COMMAND} -E remove
+ ${CMAKE_BINARY_DIR}/staticlib/libstdc++.a)
+ if(MINGW)
+ execute_process(COMMAND ${CMAKE_COMMAND} -E copy
+ ${LIBSTDCPLUSPLUS} ${CMAKE_BINARY_DIR}/staticlib/libstdc++.a)
+ else()
+ execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
+ ${LIBSTDCPLUSPLUS} ${CMAKE_BINARY_DIR}/staticlib/libstdc++.a)
+ endif()
+ set(CMAKE_EXE_LINKER_FLAGS
+ "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/staticlib")
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/staticlib")
+ else()
+ message(WARNING Cannot find static libstdc++. TigerVNC will depend on dynamic libstdc++.)
+ endif()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
+ set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc")
+ endif()
+endif()
+
#######################################################################
# functions
include(CheckFunctionExists)
--
1.8.1.3

View File

@@ -0,0 +1,26 @@
>From bf06cdf83375c11a47bddc3683143b3e2c0fdfcb Mon Sep 17 00:00:00 2001
From: DRC <information@virtualgl.org>
Date: Tue, 26 Feb 2013 03:38:45 -0600
Subject: [PATCH 2/4] Fl_cocoa.mm depends on some Carbon functions, so we need
to include that framework.
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d9d94b..cae895e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,7 +51,7 @@ if(APPLE)
set(HAVE_STRTOLL 1)
set(HAVE_STRCASECMP 1)
set(HAVE_DIRENT_H 1)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa -framework Carbon")
endif(APPLE)
if(WIN32)
--
1.8.1.3

View File

@@ -0,0 +1,30 @@
>From bb02d8426a9a279df76376313349c17774030753 Mon Sep 17 00:00:00 2001
From: DRC <information@virtualgl.org>
Date: Tue, 26 Feb 2013 04:01:36 -0600
Subject: [PATCH 3/4] We need to unset CMAKE_REQUIRED_LIBRARIES after checking
for the libpng functions. Otherwise, under certain circumstances (known to
be an issue when building on OS X with the in-tree libpng implementation),
the scandir() function check will fail, leaving HAVE_SCANDIR unset, and the
build will subsequently fail.
---
CMakeLists.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cae895e..0984aae 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -210,6 +210,9 @@ if(LIB_png)
endif(LIB_png)
CHECK_FUNCTION_EXISTS(png_get_valid HAVE_PNG_GET_VALID)
CHECK_FUNCTION_EXISTS(png_set_tRNS_to_alpha HAVE_PNG_SET_TRNS_TO_ALPHA)
+if(LIB_png)
+ set(CMAKE_REQUIRED_LIBRARIES "")
+endif(LIB_png)
CHECK_FUNCTION_EXISTS(scandir HAVE_SCANDIR)
CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
--
1.8.1.3

View File

@@ -0,0 +1,11 @@
--- fltk-1.3.2.org/src/Fl_cocoa.mm 2013-01-16 11:32:11.788478228 +0100
+++ fltk-1.3.2/src/Fl_cocoa.mm 2013-01-16 11:32:55.824101285 +0100
@@ -3727,7 +3727,7 @@ CGImageRef Fl_X::CGImage_from_window_rec
CGImageRef img;
if (fl_mac_os_version >= 100500) {
NSBitmapImageRep *bitmap = rect_to_NSBitmapImageRep(win, x, y, w, h);
- img = [bitmap CGImage]; // requires Mac OS 10.5
+ img = (CGImageRef)[bitmap CGImage]; // requires Mac OS 10.5
CGImageRetain(img);
[bitmap release];
}

View File

@@ -0,0 +1,77 @@
diff -up fltk-1.3.3/src/Fl_cocoa.mm.clip fltk-1.3.3/src/Fl_cocoa.mm
--- fltk-1.3.3/src/Fl_cocoa.mm.clip 2014-11-02 22:06:07.000000000 +0100
+++ fltk-1.3.3/src/Fl_cocoa.mm 2015-04-20 13:45:03.526688921 +0200
@@ -3061,6 +3061,14 @@ static void clipboard_check(void)
fl_trigger_clipboard_notify(1);
}
+static void resize_selection_buffer(int len, int clipboard) {
+ if (len <= fl_selection_buffer_length[clipboard])
+ return;
+ delete[] fl_selection_buffer[clipboard];
+ fl_selection_buffer[clipboard] = new char[len+100];
+ fl_selection_buffer_length[clipboard] = len+100;
+}
+
/*
* create a selection
* stuff: pointer to selected data
@@ -3069,11 +3077,7 @@ static void clipboard_check(void)
*/
void Fl::copy(const char *stuff, int len, int clipboard, const char *type) {
if (!stuff || len<0) return;
- if (len+1 > fl_selection_buffer_length[clipboard]) {
- delete[] fl_selection_buffer[clipboard];
- fl_selection_buffer[clipboard] = new char[len+100];
- fl_selection_buffer_length[clipboard] = len+100;
- }
+ resize_selection_buffer(len+1, clipboard);
memcpy(fl_selection_buffer[clipboard], stuff, len);
fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
fl_selection_length[clipboard] = len;
@@ -3087,7 +3091,7 @@ void Fl::copy(const char *stuff, int len
}
}
-static int get_plain_text_from_clipboard(char **buffer, int previous_length)
+static int get_plain_text_from_clipboard(int clipboard)
{
NSInteger length = 0;
NSPasteboard *clip = [NSPasteboard generalPasteboard];
@@ -3109,21 +3113,17 @@ static int get_plain_text_from_clipboard
len = strlen(aux_c) + 1;
}
else len = [data length] + 1;
- if ( len >= previous_length ) {
- length = len;
- delete[] *buffer;
- *buffer = new char[len];
- }
+ resize_selection_buffer(len, clipboard);
if (![found isEqualToString:utf8_format]) {
- strcpy(*buffer, aux_c);
- free(aux_c);
+ strcpy(fl_selection_buffer[clipboard], aux_c);
+ free(aux_c);
}
else {
- [data getBytes:*buffer];
+ [data getBytes:fl_selection_buffer[clipboard]];
}
- (*buffer)[len - 1] = 0;
+ fl_selection_buffer[clipboard][len - 1] = 0;
length = len - 1;
- convert_crlf(*buffer, len - 1); // turn all \r characters into \n:
+ convert_crlf(fl_selection_buffer[clipboard], len - 1); // turn all \r characters into \n:
Fl::e_clipboard_type = Fl::clipboard_plain_text;
}
}
@@ -3218,7 +3218,7 @@ void Fl::paste(Fl_Widget &receiver, int
if (clipboard) {
Fl::e_clipboard_type = "";
if (strcmp(type, Fl::clipboard_plain_text) == 0) {
- fl_selection_length[1] = get_plain_text_from_clipboard( &fl_selection_buffer[1], fl_selection_length[1]);
+ fl_selection_length[1] = get_plain_text_from_clipboard(1);
}
else if (strcmp(type, Fl::clipboard_image) == 0) {
Fl::e_clipboard_data = get_image_from_clipboard( );