- added DDrag'N'Drop support for MacOS

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@1976 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher
2002-02-26 00:34:55 +00:00
parent 5dd2625d03
commit 7a6ed8c941
7 changed files with 310 additions and 26 deletions
+3
View File
@@ -1,3 +1,6 @@
RECENT CHANGES
- drag'n'drop support for MacOS
CHANGES IN FLTK 1.1.0b11
- Now conditionally use the WIN32 TrackMouseEvent API
-1
View File
@@ -596,7 +596,6 @@ version of FLTK:
<LI>Line styles are not well supported. This is due to
limitations in the QuickDraw interface.</LI>
<LI>File descriptors are not yet supported.</LI>
<LI>Drag'n'drop is not yet supported.</LI>
</UL>
+6 -2
View File
@@ -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 $".
//
+18 -18
View File
@@ -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 $".
//
+195 -3
View File
@@ -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[];
@@ -191,6 +192,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
@@ -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 $".
//
+3 -2
View File
@@ -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 $".
#
+85
View File
@@ -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;
}
//
//
//