summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>2002-01-09 21:50:02 +0000
committerMichael R Sweet <michael.r.sweet@gmail.com>2002-01-09 21:50:02 +0000
commit6eff9b3b146ec35f7bf0eaf89924d9f052ba4bb9 (patch)
tree661e5aac7aefbab26dab19477c736ec1bd3399ad /src
parent45ff84b1f5e2f920460f1efef342e50472b1e642 (diff)
First round of DND additions to 1.1 - just X11 code, and I haven't added
the support in widgets yet. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@1925 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl.cxx6
-rw-r--r--src/Fl_cutpaste.cxx81
-rw-r--r--src/Fl_x.cxx146
-rw-r--r--src/fl_dnd.cxx16
-rw-r--r--src/fl_dnd_win32.cxx15
-rw-r--r--src/fl_dnd_x.cxx27
6 files changed, 237 insertions, 54 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx
index 6278ec4c5..c4915666d 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl.cxx,v 1.24.2.41.2.17 2002/01/07 18:47:27 easysw Exp $"
+// "$Id: Fl.cxx,v 1.24.2.41.2.18 2002/01/09 21:50:02 easysw Exp $"
//
// Main event handling code for the Fast Light Tool Kit (FLTK).
//
@@ -390,6 +390,8 @@ void Fl::add_handler(int (*h)(int)) {
handlers = l;
}
+int (*fl_local_grab)(int); // used by fl_dnd.cxx
+
static int send_handlers(int event) {
for (const handler_link *h = handlers; h; h = h->next)
if (h->handle(event)) return 1;
@@ -853,5 +855,5 @@ void Fl_Window::flush() {
}
//
-// End of "$Id: Fl.cxx,v 1.24.2.41.2.17 2002/01/07 18:47:27 easysw Exp $".
+// End of "$Id: Fl.cxx,v 1.24.2.41.2.18 2002/01/09 21:50:02 easysw Exp $".
//
diff --git a/src/Fl_cutpaste.cxx b/src/Fl_cutpaste.cxx
index 303370c67..80ca75b7f 100644
--- a/src/Fl_cutpaste.cxx
+++ b/src/Fl_cutpaste.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_cutpaste.cxx,v 1.6.2.4.2.3 2002/01/01 15:11:31 easysw Exp $"
+// "$Id: Fl_cutpaste.cxx,v 1.6.2.4.2.4 2002/01/09 21:50:02 easysw Exp $"
//
// Cut/paste code for the Fast Light Tool Kit (FLTK).
//
@@ -39,6 +39,7 @@
# include <FL/x.H>
# include <FL/Fl_Window.H>
# include <string.h>
+# include <stdlib.h>
static char *selection_buffer;
static int selection_length;
@@ -47,6 +48,30 @@ static char beenhere;
static Atom TARGETS;
extern Fl_Widget *fl_selection_requestor; // widget doing request_paste()
+extern Atom fl_XdndAware;
+extern Atom fl_XdndSelection;
+extern Atom fl_XdndEnter;
+extern Atom fl_XdndTypeList;
+extern Atom fl_XdndPosition;
+extern Atom fl_XdndLeave;
+extern Atom fl_XdndDrop;
+extern Atom fl_XdndStatus;
+extern Atom fl_XdndActionCopy;
+extern Atom fl_XdndFinished;
+//extern Atom fl_XdndProxy;
+
+extern Window fl_dnd_source_window;
+extern Atom *fl_dnd_source_types; // null-terminated list of data types being supplied
+extern Atom fl_dnd_type;
+extern Atom fl_dnd_source_action;
+extern Atom fl_dnd_action;
+
+extern void fl_sendClientMessage(Window window, Atom message,
+ unsigned long d0,
+ unsigned long d1=0,
+ unsigned long d2=0,
+ unsigned long d3=0,
+ unsigned long d4=0);
static int selection_xevent_handler(int) {
@@ -54,21 +79,45 @@ static int selection_xevent_handler(int) {
case SelectionNotify: {
if (!fl_selection_requestor) return 0;
- static char *pastebuffer;
- if (pastebuffer) {XFree(pastebuffer); pastebuffer = 0;}
- if (fl_xevent->xselection.property != 0) {
- Atom a; int f; unsigned long n,b;
- if (!XGetWindowProperty(fl_display,
- fl_xevent->xselection.requestor,
- fl_xevent->xselection.property,
- 0,100000,1,0,&a,&f,&n,&b,
- (unsigned char**)&pastebuffer)) {
- Fl::e_text = pastebuffer;
- Fl::e_length = int(n);
- fl_selection_requestor->handle(FL_PASTE);
+ static unsigned char* buffer;
+ if (buffer) {XFree(buffer); buffer = 0;}
+ long read = 0;
+ if (fl_xevent->xselection.property) for (;;) {
+ // The Xdnd code pastes 64K chunks together, possibly to avoid
+ // bugs in X servers, or maybe to avoid an extra round-trip to
+ // get the property length. I copy this here:
+ Atom actual; int format; unsigned long count, remaining;
+ unsigned char* portion;
+ if (XGetWindowProperty(fl_display,
+ fl_xevent->xselection.requestor,
+ fl_xevent->xselection.property,
+ read/4, 65536, 1, 0,
+ &actual, &format, &count, &remaining,
+ &portion)) break; // quit on error
+ if (read) { // append to the accumulated buffer
+ buffer = (unsigned char*)realloc(buffer, read+count*format/8+remaining);
+ memcpy(buffer+read, portion, count*format/8);
+ XFree(portion);
+ } else { // Use the first section without moving the memory:
+ buffer = portion;
}
- }}
- return 1;
+ read += count*format/8;
+ if (!remaining) break;
+ }
+ Fl::e_text = (char*)buffer;
+ Fl::e_length = read;
+ fl_selection_requestor->handle(FL_PASTE);
+ // Detect if this paste is due to Xdnd by the property name (I use
+ // XA_SECONDARY for that) and send an XdndFinished message. It is not
+ // clear if this has to be delayed until now or if it can be done
+ // immediatly after calling XConvertSelection.
+ if (fl_xevent->xselection.property == XA_SECONDARY &&
+ fl_dnd_source_window) {
+ fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished,
+ fl_xevent->xselection.requestor);
+ fl_dnd_source_window = 0; // don't send a second time
+ }
+ return 1;}
case SelectionClear:
Fl::selection_owner(0);
@@ -160,5 +209,5 @@ void Fl::selection(Fl_Widget &owner, const char *stuff, int len) {
#endif
//
-// End of "$Id: Fl_cutpaste.cxx,v 1.6.2.4.2.3 2002/01/01 15:11:31 easysw Exp $".
+// End of "$Id: Fl_cutpaste.cxx,v 1.6.2.4.2.4 2002/01/09 21:50:02 easysw Exp $".
//
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index f287eed8b..faa6a90c1 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_x.cxx,v 1.24.2.24.2.10 2002/01/03 18:28:37 easysw Exp $"
+// "$Id: Fl_x.cxx,v 1.24.2.24.2.11 2002/01/09 21:50:02 easysw Exp $"
//
// X specific code for the Fast Light Tool Kit (FLTK).
//
@@ -263,10 +263,49 @@ Display *fl_display;
int fl_screen;
XVisualInfo *fl_visual;
Colormap fl_colormap;
+extern Fl_Widget *fl_selection_requestor; // widget doing request_paste()
static Atom wm_delete_window;
static Atom wm_protocols;
static Atom _motif_wm_hints;
+Atom fl_XdndAware;
+Atom fl_XdndSelection;
+Atom fl_XdndEnter;
+Atom fl_XdndTypeList;
+Atom fl_XdndPosition;
+Atom fl_XdndLeave;
+Atom fl_XdndDrop;
+Atom fl_XdndStatus;
+Atom fl_XdndActionCopy;
+Atom fl_XdndFinished;
+//Atom fl_XdndProxy;
+
+Window fl_dnd_source_window;
+Atom *fl_dnd_source_types; // null-terminated list of data types being supplied
+Atom fl_dnd_type;
+Atom fl_dnd_source_action;
+Atom fl_dnd_action;
+
+void fl_sendClientMessage(Window window, 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 = window;
+ e.xclient.message_type = message;
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = (long)d0;
+ e.xclient.data.l[1] = (long)d1;
+ e.xclient.data.l[2] = (long)d2;
+ e.xclient.data.l[3] = (long)d3;
+ e.xclient.data.l[4] = (long)d4;
+ XSendEvent(fl_display, window, 0, 0, &e);
+}
+
static void fd_callback(int,void *) {
do_queued_events();
@@ -303,9 +342,22 @@ void fl_open_display() {
void fl_open_display(Display* d) {
fl_display = d;
- wm_delete_window = XInternAtom(d,"WM_DELETE_WINDOW",0);
- wm_protocols = XInternAtom(d,"WM_PROTOCOLS",0);
- _motif_wm_hints = XInternAtom(d,"_MOTIF_WM_HINTS",0);
+ wm_delete_window = XInternAtom(d,"WM_DELETE_WINDOW",0);
+ wm_protocols = XInternAtom(d,"WM_PROTOCOLS",0);
+ _motif_wm_hints = XInternAtom(d,"_MOTIF_WM_HINTS",0);
+
+ fl_XdndAware = XInternAtom(d, "XdndAware", 0);
+ fl_XdndSelection = XInternAtom(d, "XdndSelection", 0);
+ fl_XdndEnter = XInternAtom(d, "XdndEnter", 0);
+ fl_XdndTypeList = XInternAtom(d, "XdndTypeList", 0);
+ fl_XdndPosition = XInternAtom(d, "XdndPosition", 0);
+ fl_XdndLeave = XInternAtom(d, "XdndLeave", 0);
+ fl_XdndDrop = XInternAtom(d, "XdndDrop", 0);
+ fl_XdndStatus = XInternAtom(d, "XdndStatus", 0);
+ fl_XdndActionCopy = XInternAtom(d, "XdndActionCopy", 0);
+ fl_XdndFinished = XInternAtom(d, "XdndFinished", 0);
+ //fl_XdndProxy = XInternAtom(d, "XdndProxy", 0);
+
Fl::add_fd(ConnectionNumber(d), POLLIN, fd_callback);
fl_screen = DefaultScreen(fl_display);
@@ -431,9 +483,87 @@ int fl_handle(const XEvent& xevent)
if (window) switch (xevent.type) {
- case ClientMessage:
- if ((Atom)(xevent.xclient.data.l[0]) == wm_delete_window) event = FL_CLOSE;
- break;
+ case ClientMessage: {
+ Atom message = fl_xevent->xclient.message_type;
+ const long* data = fl_xevent->xclient.data.l;
+ if ((Atom)(data[0]) == wm_delete_window) {
+ event = FL_CLOSE;
+ } else if (message == fl_XdndEnter) {
+ fl_dnd_source_window = data[0];
+ // version number is data[1]>>24
+ if (data[1]&1) {
+ // get list of data types:
+ Atom actual; int format; unsigned long count, remaining;
+ unsigned char *buffer = 0;
+ XGetWindowProperty(fl_display, fl_dnd_source_window, fl_XdndTypeList,
+ 0, 0x8000000L, False, XA_ATOM, &actual, &format,
+ &count, &remaining, &buffer);
+ if (actual != XA_ATOM || format != 32 || count<4 || !buffer)
+ goto FAILED;
+ delete [] fl_dnd_source_types;
+ fl_dnd_source_types = new Atom[count+1];
+ for (unsigned i = 0; i < count; i++)
+ fl_dnd_source_types[i] = ((Atom*)buffer)[i];
+ fl_dnd_source_types[count] = 0;
+ } else {
+ FAILED:
+ // less than four data types, or if the above messes up:
+ if (!fl_dnd_source_types) fl_dnd_source_types = new Atom[4];
+ fl_dnd_source_types[0] = data[2];
+ fl_dnd_source_types[1] = data[3];
+ fl_dnd_source_types[2] = data[4];
+ fl_dnd_source_types[3] = 0;
+ }
+ fl_dnd_type = fl_dnd_source_types[0]; // should pick text or url
+ event = FL_DND_ENTER;
+ break;
+
+ } else if (message == fl_XdndPosition) {
+ fl_dnd_source_window = data[0];
+ Fl::e_x_root = data[2]>>16;
+ Fl::e_y_root = data[2]&0xFFFF;
+ if (window) {
+ Fl::e_x = Fl::e_x_root-window->x();
+ Fl::e_y = Fl::e_y_root-window->y();
+ }
+ fl_event_time = data[3];
+ fl_dnd_source_action = data[4];
+ fl_dnd_action = fl_XdndActionCopy;
+ int accept = Fl::handle(FL_DND_DRAG, window);
+ fl_sendClientMessage(data[0], fl_XdndStatus,
+ fl_xevent->xclient.window,
+ accept ? 1 : 0,
+ 0, // used for xy rectangle to not send position inside
+ 0, // used for width+height of rectangle
+ accept ? fl_dnd_action : None);
+ return true;
+
+ } else if (message == fl_XdndLeave) {
+ fl_dnd_source_window = 0; // don't send a finished message to it
+ event = FL_DND_LEAVE;
+ break;
+
+ } else if (message == fl_XdndDrop) {
+ fl_dnd_source_window = data[0];
+ fl_event_time = data[2];
+ Window to_window = fl_xevent->xclient.window;
+ if (Fl::handle(FL_DND_RELEASE, window)) {
+ fl_selection_requestor = Fl::belowmouse();
+ XConvertSelection(fl_display, fl_XdndSelection,
+ fl_dnd_type, XA_SECONDARY,
+ to_window, fl_event_time);
+ } else {
+ // Send the finished message if I refuse the drop.
+ // It is not clear whether I can just send finished always,
+ // or if I have to wait for the SelectionNotify event as the
+ // code is currently doing.
+ fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished, to_window);
+ fl_dnd_source_window = 0;
+ }
+ return true;
+
+ }
+ break;}
case MapNotify:
event = FL_SHOW;
@@ -954,5 +1084,5 @@ void Fl_Window::make_current() {
#endif
//
-// End of "$Id: Fl_x.cxx,v 1.24.2.24.2.10 2002/01/03 18:28:37 easysw Exp $".
+// End of "$Id: Fl_x.cxx,v 1.24.2.24.2.11 2002/01/09 21:50:02 easysw Exp $".
//
diff --git a/src/fl_dnd.cxx b/src/fl_dnd.cxx
index 9390a272a..7f961c602 100644
--- a/src/fl_dnd.cxx
+++ b/src/fl_dnd.cxx
@@ -1,9 +1,9 @@
//
-// "$Id: fl_dnd.cxx,v 1.3 2001/07/29 22:04:44 spitzak Exp $"
+// "$Id: fl_dnd.cxx,v 1.3.2.1 2002/01/09 21:50:02 easysw Exp $"
//
// Drag & Drop code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-1999 by Bill Spitzak and others.
+// Copyright 1998-2002 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -20,15 +20,17 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
-// Please report all bugs and problems to "fltk-bugs@easysw.com".
+// Please report all bugs and problems to "fltk-bugs@fltk.org".
//
-#ifdef _WIN32
-#include "fl_dnd_win32.cxx"
+#ifdef WIN32
+# include "fl_dnd_win32.cxx"
+//#elif defined(__APPLE__)
+//# include "fl_dnd_mac.cxx"
#else
-#include "fl_dnd_x.cxx"
+# include "fl_dnd_x.cxx"
#endif
//
-// End of "$Id: fl_dnd.cxx,v 1.3 2001/07/29 22:04:44 spitzak Exp $".
+// End of "$Id: fl_dnd.cxx,v 1.3.2.1 2002/01/09 21:50:02 easysw Exp $".
//
diff --git a/src/fl_dnd_win32.cxx b/src/fl_dnd_win32.cxx
index 6d4b5ab48..128fb6ec8 100644
--- a/src/fl_dnd_win32.cxx
+++ b/src/fl_dnd_win32.cxx
@@ -1,9 +1,9 @@
//
-// "$Id: fl_dnd_win32.cxx,v 1.5 2001/09/10 01:16:17 spitzak Exp $"
+// "$Id: fl_dnd_win32.cxx,v 1.5.2.1 2002/01/09 21:50:02 easysw Exp $"
//
// Drag & Drop code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-1999 by Bill Spitzak and others.
+// Copyright 1998-2002 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -20,8 +20,7 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
-// Please report all bugs and problems to "fltk-bugs@easysw.com".
-//
+// Please report all bugs and problems to "fltk-bugs@fltk.org
// Dummy version of dnd for now, it waits until the FL_RELEASE and
@@ -34,14 +33,14 @@
#include <fltk/Fl.h>
#include <fltk/Fl_Window.h>
-static bool grabfunc(int event) {
+static int grabfunc(int event) {
if (event == FL_RELEASE) Fl::pushed(0);
return false;
}
-extern bool (*fl_local_grab)(int); // in Fl.cxx
+extern int (*fl_local_grab)(int); // in Fl.cxx
-bool Fl::dnd() {
+int Fl::dnd() {
Fl::first_window()->cursor(FL_CURSOR_HAND);
fl_local_grab = grabfunc;
while (Fl::pushed()) Fl::wait();
@@ -52,5 +51,5 @@ bool Fl::dnd() {
//
-// End of "$Id: fl_dnd_win32.cxx,v 1.5 2001/09/10 01:16:17 spitzak Exp $".
+// End of "$Id: fl_dnd_win32.cxx,v 1.5.2.1 2002/01/09 21:50:02 easysw Exp $".
//
diff --git a/src/fl_dnd_x.cxx b/src/fl_dnd_x.cxx
index 5c1a3a832..7ac02e722 100644
--- a/src/fl_dnd_x.cxx
+++ b/src/fl_dnd_x.cxx
@@ -1,9 +1,9 @@
//
-// "$Id: fl_dnd_x.cxx,v 1.5 2001/07/23 09:50:05 spitzak Exp $"
+// "$Id: fl_dnd_x.cxx,v 1.5.2.1 2002/01/09 21:50:02 easysw Exp $"
//
// Drag & Drop code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-1999 by Bill Spitzak and others.
+// Copyright 1998-2002 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -20,12 +20,13 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
-// Please report all bugs and problems to "fltk-bugs@easysw.com".
+// Please report all bugs and problems to "fltk-bugs@fltk.org".
//
-#include <fltk/Fl.h>
-#include <fltk/Fl_Window.h>
-#include <fltk/x.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/x.H>
+
extern Atom fl_XdndAware;
extern Atom fl_XdndSelection;
@@ -41,7 +42,7 @@ extern Atom fl_XdndFinished;
extern char fl_i_own_selection;
-void fl_sendClientMessage(Window window, Atom message,
+extern void fl_sendClientMessage(Window window, Atom message,
unsigned long d0,
unsigned long d1=0,
unsigned long d2=0,
@@ -49,7 +50,7 @@ void fl_sendClientMessage(Window window, Atom message,
unsigned long d4=0);
// return version # of Xdnd this window supports. Also change the
-// window the the proxy if it uses a proxy:
+// window to the proxy if it uses a proxy:
static int dnd_aware(Window& window) {
Atom actual; int format; unsigned long count, remaining;
unsigned char *data = 0;
@@ -62,15 +63,15 @@ static int dnd_aware(Window& window) {
return 0;
}
-static bool grabfunc(int event) {
+static int grabfunc(int event) {
if (event == FL_RELEASE) Fl::pushed(0);
return false;
}
-extern bool (*fl_local_grab)(int); // in Fl.cxx
+extern int (*fl_local_grab)(int); // in Fl.cxx
// send an event to an fltk window belonging to this program:
-static bool local_handle(int event, Fl_Window* window) {
+static int local_handle(int event, Fl_Window* window) {
fl_local_grab = 0;
Fl::e_x = Fl::e_x_root-window->x();
Fl::e_y = Fl::e_y_root-window->y();
@@ -79,7 +80,7 @@ static bool local_handle(int event, Fl_Window* window) {
return ret;
}
-bool Fl::dnd() {
+int Fl::dnd() {
Fl::first_window()->cursor((Fl_Cursor)21);
Window source_window = fl_xid(Fl::first_window());
fl_local_grab = grabfunc;
@@ -166,5 +167,5 @@ bool Fl::dnd() {
//
-// End of "$Id: fl_dnd_x.cxx,v 1.5 2001/07/23 09:50:05 spitzak Exp $".
+// End of "$Id: fl_dnd_x.cxx,v 1.5.2.1 2002/01/09 21:50:02 easysw Exp $".
//