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
This commit is contained in:
Michael R Sweet
2002-01-09 21:50:02 +00:00
parent 45ff84b1f5
commit 6eff9b3b14
9 changed files with 252 additions and 59 deletions
+5
View File
@@ -1,3 +1,8 @@
CHANGES IN FLTK 1.1.0b11
- Initial port of FLTK 2.0 drag-and-drop support.
CHANGES IN FLTK 1.1.0b10
- Fixed the new WIN32 TrackMouseEvent code.
+7 -3
View File
@@ -1,5 +1,5 @@
//
// "$Id: Enumerations.H,v 1.18.2.14.2.18 2002/01/01 15:11:27 easysw Exp $"
// "$Id: Enumerations.H,v 1.18.2.14.2.19 2002/01/09 21:50:02 easysw Exp $"
//
// Enumerations for the Fast Light Tool Kit (FLTK).
//
@@ -73,7 +73,11 @@ enum Fl_Event { // events
FL_SHOW = 16,
FL_PASTE = 17,
FL_SELECTIONCLEAR = 18,
FL_MOUSEWHEEL = 19
FL_MOUSEWHEEL = 19,
FL_DND_ENTER = 20,
FL_DND_DRAG = 21,
FL_DND_LEAVE = 22,
FL_DND_RELEASE = 23
};
#define FL_KEYBOARD FL_KEYDOWN
@@ -373,5 +377,5 @@ enum Fl_Damage {
#endif
//
// End of "$Id: Enumerations.H,v 1.18.2.14.2.18 2002/01/01 15:11:27 easysw Exp $".
// End of "$Id: Enumerations.H,v 1.18.2.14.2.19 2002/01/09 21:50:02 easysw Exp $".
//
+3 -2
View File
@@ -1,5 +1,5 @@
//
// "$Id: Fl.H,v 1.8.2.11.2.12 2002/01/01 15:11:27 easysw Exp $"
// "$Id: Fl.H,v 1.8.2.11.2.13 2002/01/09 21:50:02 easysw Exp $"
//
// Main header file for the Fast Light Tool Kit (FLTK).
//
@@ -173,6 +173,7 @@ public:
static FL_EXPORT void selection_owner(Fl_Widget*);
static FL_EXPORT void selection(Fl_Widget &owner, const char* stuff, int len);
static FL_EXPORT void paste(Fl_Widget &receiver);
static FL_EXPORT int dnd();
// screen size:
#if defined(WIN32) || defined(__APPLE__)
@@ -243,5 +244,5 @@ public:
#endif // !Fl_H
//
// End of "$Id: Fl.H,v 1.8.2.11.2.12 2002/01/01 15:11:27 easysw Exp $".
// End of "$Id: Fl.H,v 1.8.2.11.2.13 2002/01/09 21:50:02 easysw Exp $".
//
+4 -2
View File
@@ -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 $".
//
+65 -16
View File
@@ -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 $".
//
+138 -8
View File
@@ -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 $".
//
+9 -7
View File
@@ -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 $".
//
+7 -8
View File
@@ -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 $".
//
+14 -13
View File
@@ -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 $".
//