diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2002-02-26 00:34:55 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2002-02-26 00:34:55 +0000 |
| commit | 7a6ed8c9419b914644936c7e25a2f1eb10d7c28e (patch) | |
| tree | 8fc202fc77c5897558c2c997e87dba625b841791 /src | |
| parent | 5dd2625d0365b81093481b74e563e65f29666ef4 (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.cxx | 8 | ||||
| -rw-r--r-- | src/Fl_cutpaste_mac.cxx | 36 | ||||
| -rw-r--r-- | src/Fl_mac.cxx | 198 | ||||
| -rw-r--r-- | src/Makefile | 5 | ||||
| -rw-r--r-- | src/fl_dnd_mac.cxx | 85 |
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; +} + + +// +// +// |
