mirror of https://github.com/fltk/fltk
STR 2636. Add ability to get notifications whenever the
clipboard changes. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9974 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
f410352c7c
commit
1d6cc80d59
|
@ -513,6 +513,20 @@ else()
|
|||
set(FLTK_XINERAMA_FOUND FALSE)
|
||||
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)
|
||||
|
|
16
FL/Fl.H
16
FL/Fl.H
|
@ -109,6 +109,9 @@ typedef int (*Fl_Args_Handler)(int argc, char **argv, int &i);
|
|||
\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 */
|
||||
|
||||
|
||||
|
@ -749,6 +752,19 @@ public:
|
|||
copy/cut/paste operations.
|
||||
*/
|
||||
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 = 0);
|
||||
/**
|
||||
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
|
||||
|
|
|
@ -107,6 +107,14 @@
|
|||
|
||||
#define USE_XDBE HAVE_XDBE
|
||||
|
||||
/*
|
||||
* HAVE_XFIXES:
|
||||
*
|
||||
* Do we have the X fixes extension?
|
||||
*/
|
||||
|
||||
#cmakedefine01 HAVE_XFIXES
|
||||
|
||||
/*
|
||||
* __APPLE_QUARTZ__:
|
||||
*
|
||||
|
|
|
@ -107,6 +107,14 @@
|
|||
|
||||
#define USE_XDBE HAVE_XDBE
|
||||
|
||||
/*
|
||||
* HAVE_XFIXES:
|
||||
*
|
||||
* Do we have the X fixes extension?
|
||||
*/
|
||||
|
||||
#define HAVE_XFIXES 0
|
||||
|
||||
/*
|
||||
* __APPLE_QUARTZ__:
|
||||
*
|
||||
|
|
10
configure.in
10
configure.in
|
@ -995,6 +995,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,
|
||||
|
|
|
@ -239,6 +239,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)
|
||||
|
|
67
src/Fl.cxx
67
src/Fl.cxx
|
@ -434,6 +434,70 @@ static void run_checks()
|
|||
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, *next;
|
||||
|
||||
node = clip_notify_list;
|
||||
while (node != NULL) {
|
||||
next = node->next;
|
||||
node->handler(source, node->data);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// wait/run/check/ready:
|
||||
|
||||
|
@ -1358,6 +1422,7 @@ int Fl::handle_(int e, Fl_Window* window)
|
|||
// 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);
|
||||
|
@ -1408,6 +1473,8 @@ void Fl_Window::hide() {
|
|||
// 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);
|
||||
|
|
|
@ -90,6 +90,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 clipboard_check(void);
|
||||
|
||||
Fl_Display_Device *Fl_Display_Device::_display = new Fl_Display_Device(new Fl_Quartz_Graphics_Driver); // the platform display
|
||||
|
||||
|
@ -1109,16 +1110,21 @@ static void cocoaMouseHandler(NSEvent *theEvent)
|
|||
fl_unlock_function();
|
||||
return reply;
|
||||
}
|
||||
/**
|
||||
* Cocoa organizes the Z depth of windows on a global priority. FLTK however
|
||||
* expects the window manager to organize Z level by application. The trickery
|
||||
* below will change Z order during activation and deactivation.
|
||||
*/
|
||||
- (void)applicationDidBecomeActive:(NSNotification *)notify
|
||||
{
|
||||
fl_lock_function();
|
||||
Fl_X *x;
|
||||
FLWindow *top = 0, *topModal = 0, *topNonModal = 0;
|
||||
|
||||
fl_lock_function();
|
||||
|
||||
// update clipboard status
|
||||
clipboard_check();
|
||||
|
||||
/**
|
||||
* Cocoa organizes the Z depth of windows on a global priority. FLTK however
|
||||
* expects the window manager to organize Z level by application. The trickery
|
||||
* below will change Z order during activation and deactivation.
|
||||
*/
|
||||
for (x = Fl_X::first;x;x = x->next) {
|
||||
FLWindow *cw = x->xid;
|
||||
Fl_Window *win = x->w;
|
||||
|
@ -2720,6 +2726,26 @@ static void allocatePasteboard() {
|
|||
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
|
||||
|
|
|
@ -634,6 +634,38 @@ void Fl::paste(Fl_Widget &receiver, int clipboard) {
|
|||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
@ -1211,6 +1243,27 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
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;
|
||||
|
@ -1647,6 +1700,8 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
|||
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) {
|
||||
|
|
172
src/Fl_x.cxx
172
src/Fl_x.cxx
|
@ -53,6 +53,12 @@ static XRRUpdateConfiguration_type XRRUpdateConfiguration_f;
|
|||
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
|
||||
|
@ -306,6 +312,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;
|
||||
|
@ -608,6 +617,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);
|
||||
|
@ -655,6 +667,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);
|
||||
|
@ -842,6 +863,107 @@ void Fl::copy(const char *stuff, int len, int clipboard) {
|
|||
XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
@ -1005,7 +1127,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;
|
||||
|
@ -1021,6 +1142,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++) {
|
||||
|
@ -1061,6 +1195,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;
|
||||
|
@ -1081,6 +1218,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: {
|
||||
|
@ -1295,6 +1433,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:
|
||||
|
@ -1663,6 +1804,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);
|
||||
}
|
||||
|
||||
|
@ -1982,6 +2142,16 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
|
|||
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();
|
||||
|
|
Loading…
Reference in New Issue