mirror of
https://github.com/fltk/fltk.git
synced 2026-06-07 17:35:39 +08:00
- 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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 $".
|
||||
#
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
Reference in New Issue
Block a user