summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2002-02-26 00:34:55 +0000
committerMatthias Melcher <fltk@matthiasm.com>2002-02-26 00:34:55 +0000
commit7a6ed8c9419b914644936c7e25a2f1eb10d7c28e (patch)
tree8fc202fc77c5897558c2c997e87dba625b841791 /src
parent5dd2625d0365b81093481b74e563e65f29666ef4 (diff)
- added DDrag'N'Drop support for MacOS
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@1976 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl.cxx8
-rw-r--r--src/Fl_cutpaste_mac.cxx36
-rw-r--r--src/Fl_mac.cxx198
-rw-r--r--src/Makefile5
-rw-r--r--src/fl_dnd_mac.cxx85
5 files changed, 307 insertions, 25 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx
index f7aa5b027..1dff53f7f 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl.cxx,v 1.24.2.41.2.20 2002/02/24 17:52:17 matthiaswm Exp $"
+// "$Id: Fl.cxx,v 1.24.2.41.2.21 2002/02/26 00:34:55 matthiaswm Exp $"
//
// Main event handling code for the Fast Light Tool Kit (FLTK).
//
@@ -729,7 +729,11 @@ void Fl_Window::hide() {
#ifdef __APPLE__
if ( !parent() ) // don't destroy shared windows!
+ {
+ //+ RemoveTrackingHandler( dndTrackingHandler, x->xid );
+ //+ RemoveReceiveHandler( dndReceiveHandler, x->xid );
XDestroyWindow(fl_display, x->xid);
+ }
#else
XDestroyWindow(fl_display, x->xid);
#endif
@@ -876,5 +880,5 @@ void Fl_Window::flush() {
}
//
-// End of "$Id: Fl.cxx,v 1.24.2.41.2.20 2002/02/24 17:52:17 matthiaswm Exp $".
+// End of "$Id: Fl.cxx,v 1.24.2.41.2.21 2002/02/26 00:34:55 matthiaswm Exp $".
//
diff --git a/src/Fl_cutpaste_mac.cxx b/src/Fl_cutpaste_mac.cxx
index 99e7cb892..7633ac6f3 100644
--- a/src/Fl_cutpaste_mac.cxx
+++ b/src/Fl_cutpaste_mac.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_cutpaste_mac.cxx,v 1.1.2.3 2002/01/01 15:11:31 easysw Exp $"
+// "$Id: Fl_cutpaste_mac.cxx,v 1.1.2.4 2002/02/26 00:34:55 matthiaswm Exp $"
//
// MacOS cut/paste code for the Fast Light Tool Kit (FLTK).
//
@@ -30,8 +30,8 @@
#include <FL/Fl_Window.H>
#include <string.h>
-static char *selection_buffer = 0L;
-static int selection_length = 0;
+char *fl_selection_buffer = 0L;
+int fl_selection_length = 0;
static int selection_buffer_length = 0;
static ScrapRef myScrap = 0;
@@ -56,17 +56,17 @@ void Fl::paste( Fl_Widget &receiver )
if ( len > selection_buffer_length )
{
selection_buffer_length = len + 32;
- delete[] selection_buffer;
- selection_buffer = new char[len];
+ delete[] fl_selection_buffer;
+ fl_selection_buffer = new char[len];
selection_buffer_length = len;
}
- GetScrapFlavorData( scrap, kScrapFlavorTypeText, &len, selection_buffer );
- selection_length = len;
+ GetScrapFlavorData( scrap, kScrapFlavorTypeText, &len, fl_selection_buffer );
+ fl_selection_length = len;
}
- for ( char *s = selection_buffer+selection_length; s >= selection_buffer; s-- ) // this will fail on PC line endings (CR+LF)
+ for ( char *s = fl_selection_buffer+fl_selection_length; s >= fl_selection_buffer; s-- ) // this will fail on PC line endings (CR+LF)
if ( *s == 0x0d ) *s = 0x0a;
- Fl::e_text = selection_buffer;
- Fl::e_length = selection_length;
+ Fl::e_text = fl_selection_buffer;
+ Fl::e_length = fl_selection_length;
receiver.handle( FL_PASTE );
return;
}
@@ -82,15 +82,15 @@ void Fl::selection( Fl_Widget &owner, const char *stuff, int len ) {
if ( !stuff || len<0 )
return;
if ( len+1 > selection_buffer_length ) {
- delete[] selection_buffer;
- selection_buffer = new char[len+100];
+ delete[] fl_selection_buffer;
+ fl_selection_buffer = new char[len+100];
selection_buffer_length = len+100;
}
- memcpy( selection_buffer, stuff, len );
- for ( char *s = selection_buffer+len; s >= selection_buffer; s-- ) // this will fail on PC line endings (CR+LF)
+ memcpy( fl_selection_buffer, stuff, len );
+ for ( char *s = fl_selection_buffer+len; s >= fl_selection_buffer; s-- ) // this will fail on PC line endings (CR+LF)
if ( *s == 0x0a ) *s = 0x0d;
- selection_buffer[len] = 0;
- selection_length = len;
+ fl_selection_buffer[len] = 0;
+ fl_selection_length = len;
selection_owner( &owner );
ClearCurrentScrap();
@@ -100,10 +100,10 @@ void Fl::selection( Fl_Widget &owner, const char *stuff, int len ) {
myScrap = 0;
return;
}
- PutScrapFlavor( myScrap, kScrapFlavorTypeText, 0, selection_length, selection_buffer );
+ PutScrapFlavor( myScrap, kScrapFlavorTypeText, 0, fl_selection_length, fl_selection_buffer );
}
//
-// End of "$Id: Fl_cutpaste_mac.cxx,v 1.1.2.3 2002/01/01 15:11:31 easysw Exp $".
+// End of "$Id: Fl_cutpaste_mac.cxx,v 1.1.2.4 2002/02/26 00:34:55 matthiaswm Exp $".
//
diff --git a/src/Fl_mac.cxx b/src/Fl_mac.cxx
index b636b4e12..ee01b832f 100644
--- a/src/Fl_mac.cxx
+++ b/src/Fl_mac.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_mac.cxx,v 1.1.2.13 2002/01/03 18:28:36 easysw Exp $"
+// "$Id: Fl_mac.cxx,v 1.1.2.14 2002/02/26 00:34:55 matthiaswm Exp $"
//
// MacOS specific code for the Fast Light Tool Kit (FLTK).
//
@@ -59,7 +59,7 @@ extern void fl_fix_focus();
// forward definition of functions in this file
static void handleUpdateEvent( WindowPtr xid );
-int fl_handle(const EventRecord &event);
+//+ int fl_handle(const EventRecord &event);
// public variables
int fl_screen;
@@ -75,6 +75,7 @@ const Fl_Window* fl_modal_for; // parent of modal() window
Fl_Region fl_window_region = 0;
Window fl_window;
Fl_Window *Fl_Window::current_;
+EventRef fl_os_event; // last (mouse) event
// forward declarations of variables in this file
static unsigned short macKeyLookUp[];
@@ -192,6 +193,18 @@ static void timerProcCB( EventLoopTimerRef, void* )
/**
+ * break the current event loop
+ */
+static void breakMacEventLoop()
+{
+ EventRef breakEvent;
+ CreateEvent( 0, kEventClassFLTK, kEventFLTKBreakLoop, 0, kEventAttributeUserEvent, &breakEvent );
+ PostEventToQueue( GetCurrentEventQueue(), breakEvent, kEventPriorityStandard );
+ ReleaseEvent( breakEvent );
+}
+
+
+/**
* This function iss the central event handler.
* It reads events from the event queue using the given maximum time
* Funny enough, it returns the same time that it got as the argument.
@@ -407,6 +420,7 @@ static pascal OSStatus carbonMouseHandler( EventHandlerCallRef nextHandler, Even
{
static int keysym[] = { 0, FL_Button+1, FL_Button+3, FL_Button+2 };
static int px, py;
+ fl_os_event = event;
Fl_Window *window = (Fl_Window*)userData;
Point pos;
GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &pos );
@@ -786,6 +800,182 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by)
return ret;
}
+/**
+ * convert a Mac FSSpec structure into a Unix filename
+ */
+static int FSSpec2UnixPath( FSSpec *fs, char *dst )
+{
+ FSRef fsRef;
+ FSpMakeFSRef( fs, &fsRef );
+ FSRefMakePath( &fsRef, (UInt8*)dst, 1024 );
+ return strlen(dst);
+/* keep the code below. The above function is only implemented in OS X, so we might need the other code for OS 9 and friends
+ short offset = 0;
+ if ( fs->parID != fsRtParID )
+ {
+ FSSpec parent;
+ OSErr ret = FSMakeFSSpec( fs->vRefNum, fs->parID, 0, &parent );
+ if ( ret != noErr ) return 0;
+ offset = FSSpec2UnixPath( &parent, dst );
+ }
+
+ if ( fs->parID == fsRtParID && fs->vRefNum == -100 ) //+ bad hack: we assume that volume -100 is mounted as root
+ {
+ memcpy( dst, "/", 2 );
+ return 1; // don't add anything to the filename - we are fine already
+ }
+
+ short len = fs->name[0];
+ if ( fs->parID == fsRtParID ) { // assume tat all other volumes are in this directory (international name WILL vary!)
+ memcpy( dst, "/Volumes", 8 );
+ offset = 8;
+ }
+
+ if ( offset!=1 ) dst[ offset++ ] = '/'; // avoid double '/'
+ memcpy( dst+offset, fs->name+1, len );
+ dst[ len+offset ] = 0;
+ return len+offset;
+*/
+}
+
+Fl_Window *fl_dnd_target_window = 0;
+#include <Fl/fl_draw.h>
+/**
+ * Drag'n'drop tracking handler
+ */
+OSErr dndTrackingHandler( DragTrackingMessage msg, WindowPtr w, void *userData, DragReference dragRef )
+{
+ Fl_Window *target = (Fl_Window*)userData;
+ Point mp;
+ static int px, py;
+
+ switch ( msg )
+ {
+ case kDragTrackingEnterWindow:
+ // check if 'TEXT' is available
+ GetDragMouse( dragRef, &mp, 0 );
+ Fl::e_x_root = px = mp.h;
+ Fl::e_y_root = py = mp.v;
+ Fl::e_x = px - target->x();
+ Fl::e_y = py - target->y();
+ fl_dnd_target_window = target;
+ if ( Fl::handle( FL_DND_ENTER, target ) )
+ fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?!
+ else
+ fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
+ breakMacEventLoop();
+ return noErr;
+ case kDragTrackingInWindow:
+ GetDragMouse( dragRef, &mp, 0 );
+ if ( mp.h==px && mp.v==py )
+ break; //+ return previous condition for dnd hiliting
+ Fl::e_x_root = px = mp.h;
+ Fl::e_y_root = py = mp.v;
+ Fl::e_x = px - target->x();
+ Fl::e_y = py - target->y();
+ fl_dnd_target_window = target;
+ if ( Fl::handle( FL_DND_DRAG, target ) )
+ fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?!
+ else
+ fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
+ breakMacEventLoop();
+ return noErr;
+ break;
+ case kDragTrackingLeaveWindow:
+ // HideDragHilite()
+ fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
+ if ( fl_dnd_target_window )
+ {
+ Fl::handle( FL_DND_LEAVE, fl_dnd_target_window );
+ fl_dnd_target_window = 0;
+ }
+ breakMacEventLoop();
+ return noErr;
+ }
+ return noErr;
+}
+
+
+/**
+ * Drag'n'drop receive handler
+ */
+OSErr dndReceiveHandler( WindowPtr w, void *userData, DragReference dragRef )
+{
+ Point mp;
+ OSErr ret;
+
+ Fl_Window *target = fl_dnd_target_window = (Fl_Window*)userData;
+ GetDragMouse( dragRef, &mp, 0 );
+ Fl::e_x_root = mp.h;
+ Fl::e_y_root = mp.v;
+ Fl::e_x = Fl::e_x_root - target->x();
+ Fl::e_y = Fl::e_y_root - target->y();
+ if ( !Fl::handle( FL_DND_RELEASE, target ) )
+ return userCanceledErr;
+
+ // get the ASCII text
+ UInt16 i, nItem;
+ ItemReference itemRef;
+ FlavorFlags flags;
+ Size itemSize, size = 0;
+ CountDragItems( dragRef, &nItem );
+ for ( i = 1; i <= nItem; i++ )
+ {
+ GetDragItemReferenceNumber( dragRef, i, &itemRef );
+ ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags );
+ if ( ret == noErr )
+ {
+ GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize );
+ size += itemSize;
+ }
+ ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags );
+ if ( ret == noErr )
+ {
+ size += 1024; //++ ouch! We should create the full pathname and figure out its length
+ }
+ }
+
+ if ( !size )
+ return userCanceledErr;
+
+ Fl::e_length = size + nItem - 1;
+ char *dst = Fl::e_text = (char*)malloc( size+nItem );;
+
+ for ( i = 1; i <= nItem; i++ )
+ {
+ GetDragItemReferenceNumber( dragRef, i, &itemRef );
+ ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags );
+ if ( ret == noErr )
+ {
+ GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize );
+ GetFlavorData( dragRef, itemRef, 'TEXT', dst, &itemSize, 0L );
+ dst += itemSize;
+ *dst++ = '\n'; // add our element seperator
+ }
+ ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags );
+ if ( ret == noErr )
+ {
+ HFSFlavor hfs; itemSize = sizeof( hfs );
+ GetFlavorData( dragRef, itemRef, 'hfs ', &hfs, &itemSize, 0L );
+ itemSize = FSSpec2UnixPath( &hfs.fileSpec, dst );
+ dst += itemSize;
+ if ( itemSize>1 && ( hfs.fileType=='fold' || hfs.fileType=='disk' ) )
+ *dst++ = '/';
+ *dst++ = '\n'; // add our element seperator
+ }
+ }
+
+ dst[-1] = 0;
+// if ( Fl::e_text[Fl::e_length-1]==0 ) Fl::e_length--; // modify, if trailing 0 is part of string
+ Fl::e_length = dst - Fl::e_text - 1;
+ target->handle(FL_PASTE);
+ free( Fl::e_text );
+
+ fl_dnd_target_window = 0L;
+ breakMacEventLoop();
+ return noErr;
+}
+
/**
* go ahead, create that (sub)window
@@ -936,6 +1126,8 @@ void Fl_X::make(Fl_Window* w)
{ kEventClassWindow, kEventWindowClose },
{ kEventClassWindow, kEventWindowBoundsChanged } };
ret = InstallWindowEventHandler( x->xid, windowHandler, 7, windowEvents, w, 0L );
+ ret = InstallTrackingHandler( dndTrackingHandler, x->xid, w );
+ ret = InstallReceiveHandler( dndReceiveHandler, x->xid, w );
}
if ( ! Fl_X::first->next ) // if this is the first window, we need to bring the application to the front
@@ -1096,6 +1288,6 @@ void Fl_Window::make_current()
}
//
-// End of "$Id: Fl_mac.cxx,v 1.1.2.13 2002/01/03 18:28:36 easysw Exp $".
+// End of "$Id: Fl_mac.cxx,v 1.1.2.14 2002/02/26 00:34:55 matthiaswm Exp $".
//
diff --git a/src/Makefile b/src/Makefile
index f55dd18bd..e3488c1c2 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,5 +1,5 @@
#
-# "$Id: Makefile,v 1.18.2.14.2.33 2002/02/15 18:15:46 easysw Exp $"
+# "$Id: Makefile,v 1.18.2.14.2.34 2002/02/26 00:34:55 matthiaswm Exp $"
#
# Library makefile for the Fast Light Tool Kit (FLTK).
#
@@ -128,6 +128,7 @@ CPPFILES = \
fl_cursor.cxx \
fl_curve.cxx \
fl_diamond_box.cxx \
+ fl_dnd.cxx \
fl_draw.cxx \
fl_draw_image.cxx \
fl_draw_pixmap.cxx \
@@ -352,5 +353,5 @@ uninstall:
#
-# End of "$Id: Makefile,v 1.18.2.14.2.33 2002/02/15 18:15:46 easysw Exp $".
+# End of "$Id: Makefile,v 1.18.2.14.2.34 2002/02/26 00:34:55 matthiaswm Exp $".
#
diff --git a/src/fl_dnd_mac.cxx b/src/fl_dnd_mac.cxx
new file mode 100644
index 000000000..79de55324
--- /dev/null
+++ b/src/fl_dnd_mac.cxx
@@ -0,0 +1,85 @@
+//
+//
+//
+// Drag & Drop code for the Fast Light Tool Kit (FLTK).
+//
+// 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
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems to "fltk-bugs@fltk.org
+
+// This file contains win32-specific code for fltk which is always linked
+// in. Search other files for "WIN32" or filenames ending in _win32.cxx
+// for other system-specific code.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/mac.H>
+#include <FL/Fl_Window.H>
+
+extern EventRef fl_os_event;
+extern char *fl_selection_buffer;
+extern int fl_selection_length;
+
+
+/**
+ * drag and drop whatever is in the cut-copy-paste buffer
+ * - create a selection first using:
+ * Fl::selection(Fl_Widget &owner, const char *stuff, int len)
+ */
+int Fl::dnd()
+{
+ OSErr result;
+ DragReference dragRef;
+ result = NewDrag( &dragRef );
+ if ( result != noErr ) return false;
+
+ result = AddDragItemFlavor( dragRef, 1, 'TEXT', fl_selection_buffer, fl_selection_length, 0 );
+ if ( result != noErr ) { DisposeDrag( dragRef ); return false; }
+
+ Point mp;
+ GetMouse(&mp);
+ LocalToGlobal( &mp );
+ RgnHandle region = NewRgn();
+ SetRectRgn( region, mp.h-10, mp.v-10, mp.h+10, mp.v+10 );
+ RgnHandle r2 = NewRgn();
+ SetRectRgn( r2, mp.h-8, mp.v-8, mp.h+8, mp.v+8 );
+ DiffRgn( region, r2, region );
+ DisposeRgn( r2 );
+
+ EventRecord event;
+ ConvertEventRefToEventRecord( fl_os_event, &event );
+ result = TrackDrag( dragRef, &event, region );
+
+ Fl_Widget *w = Fl::pushed();
+ if ( w )
+ {
+ w->handle( FL_RELEASE );
+ Fl::pushed( 0 );
+ }
+
+ if ( result != noErr ) { DisposeRgn( region ); DisposeDrag( dragRef ); return false; }
+
+ DisposeRgn( region );
+ DisposeDrag( dragRef );
+ return true;
+}
+
+
+//
+//
+//