summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2005-08-15 19:18:49 +0000
committerMatthias Melcher <fltk@matthiasm.com>2005-08-15 19:18:49 +0000
commit379804873e02c93d73f8d6174cdf74af9829e8b3 (patch)
treea428a10e792b19a49e113338deaa43a8646e2e1a
parent128fda2fd61dd0ec639ea4e7eee27e57f24a36f0 (diff)
Fixed Fl::event_text() for FL_DND_* events on Windows (STR 968)
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@4511 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CHANGES2
-rw-r--r--src/fl_dnd_win32.cxx96
2 files changed, 73 insertions, 25 deletions
diff --git a/CHANGES b/CHANGES
index 4a9a2240f..4c99d5d73 100644
--- a/CHANGES
+++ b/CHANGES
@@ -8,7 +8,7 @@ CHANGES IN FLTK 1.1.7
- Borderless windows will not show in the taskbar anymore
on X11 (STR #933)
- Fixed event_text() field on FL_DND_* event on
- OS X (STR #968)
+ OS X and WIN32 (STR #968)
- The fltk-config utility now supports "--cc" and "--cxx"
options to get the C and C++ compilers that were used
to compile FLTK (STR #868)
diff --git a/src/fl_dnd_win32.cxx b/src/fl_dnd_win32.cxx
index 84c2cbfd6..fde478d23 100644
--- a/src/fl_dnd_win32.cxx
+++ b/src/fl_dnd_win32.cxx
@@ -84,6 +84,7 @@ public:
}
HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) {
if( !pDataObj ) return E_INVALIDARG;
+ printf("DND Enter\n");
// set e_modifiers here from grfKeyState, set e_x and e_root_x
// check if FLTK handles this drag and return if it can't (i.e. BMP drag without filename)
POINT ppt;
@@ -97,11 +98,15 @@ public:
}
fl_dnd_target_window = target;
px = pt.x; py = pt.y;
+ if (fillCurrentDragData(pDataObj)) {
// FLTK has no mechanism yet for the different drop effects, so we allow move and copy
- if ( target && Fl::handle( FL_DND_ENTER, target ) )
- *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK;
- else
+ if ( target && Fl::handle( FL_DND_ENTER, target ) )
+ *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK;
+ else
+ *pdwEffect = DROPEFFECT_NONE;
+ } else {
*pdwEffect = DROPEFFECT_NONE;
+ }
lastEffect = *pdwEffect;
return S_OK;
}
@@ -116,6 +121,7 @@ public:
*pdwEffect = lastEffect = DROPEFFECT_NONE;
return S_OK;
}
+ printf("DND Drag\n");
// set e_modifiers here from grfKeyState, set e_x and e_root_x
Fl::e_x_root = pt.x;
Fl::e_y_root = pt.y;
@@ -123,20 +129,26 @@ public:
Fl::e_x = Fl::e_x_root-fl_dnd_target_window->x();
Fl::e_y = Fl::e_y_root-fl_dnd_target_window->y();
}
- // Fl_Group will change DND_DRAG into DND_ENTER and DND_LEAVE if needed
- if ( Fl::handle( FL_DND_DRAG, fl_dnd_target_window ) )
- *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK;
- else
+ if (fillCurrentDragData(0)) {
+ // Fl_Group will change DND_DRAG into DND_ENTER and DND_LEAVE if needed
+ if ( Fl::handle( FL_DND_DRAG, fl_dnd_target_window ) )
+ *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK;
+ else
+ *pdwEffect = DROPEFFECT_NONE;
+ } else {
*pdwEffect = DROPEFFECT_NONE;
+ }
px = pt.x; py = pt.y;
lastEffect = *pdwEffect;
return S_OK;
}
HRESULT STDMETHODCALLTYPE DragLeave() {
- if ( fl_dnd_target_window )
+ printf("DND Leave\n");
+ if ( fl_dnd_target_window && fillCurrentDragData(0))
{
Fl::handle( FL_DND_LEAVE, fl_dnd_target_window );
fl_dnd_target_window = 0;
+ clearCurrentDragData();
}
return S_OK;
}
@@ -158,28 +170,62 @@ public:
Fl_Widget *w = target;
while (w->parent()) w = w->window();
HWND hwnd = fl_xid( (Fl_Window*)w );
+ if (fillCurrentDragData(data)) {
+ int old_event = Fl::e_number;
+ Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); // e_text will be invalid after this call
+ Fl::e_number = old_event;
+ SetForegroundWindow( hwnd );
+ clearCurrentDragData();
+ return S_OK;
+ }
+ return S_OK;
+ }
+private:
+
+ static IDataObject *currDragRef;
+ static char *currDragData;
+ static int currDragSize;
+ static char currDragResult;
+
+ static void clearCurrentDragData() {
+ currDragRef = 0;
+ if (currDragData) free(currDragData);
+ currDragData = 0;
+ currDragSize = 0;
+ currDragResult = 0;
+ }
+ static char fillCurrentDragData(IDataObject *data) {
+ // shortcut through this whole procedure if there is no fresh data
+ if (!data)
+ return currDragResult;
+ // shortcut through this whole procedure if this is still the same drag event
+ // (* this is safe, because 'currDragRef' is cleared on Leave and Drop events)
+ if (data==currDragRef)
+ return currDragResult;
+ // clear currDrag* for a new drag event
+ clearCurrentDragData();
+
+ // fill currDrag* with ASCII data, if available
FORMATETC fmt = { 0 };
STGMEDIUM medium = { 0 };
fmt.tymed = TYMED_HGLOBAL;
fmt.dwAspect = DVASPECT_CONTENT;
fmt.lindex = -1;
fmt.cfFormat = CF_TEXT;
- // if it is ASCII text, send an FL_PASTE with that text
+ // if it is ASCII text, return a copy of it
if ( data->GetData( &fmt, &medium )==S_OK )
{
void *stuff = GlobalLock( medium.hGlobal );
- //long len = GlobalSize( medium.hGlobal );
- Fl::e_length = strlen( (char*)stuff ); // min(strlen, len)
- Fl::e_text = (char*)stuff;
- int old_event = Fl::e_number;
- Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); // e_text will be invalid after this call
- Fl::e_number = old_event;
+ Fl::e_length = strlen((char*)stuff);
+ Fl::e_text = strdup((char*)stuff);
GlobalUnlock( medium.hGlobal );
ReleaseStgMedium( &medium );
- SetForegroundWindow( hwnd );
- return S_OK;
+ currDragResult = 1;
+ return currDragResult;
}
+ // else fill currDrag* with filenames, if possible
+ memset(&fmt, 0, sizeof(fmt));
fmt.tymed = TYMED_HGLOBAL;
fmt.dwAspect = DVASPECT_CONTENT;
fmt.lindex = -1;
@@ -199,20 +245,22 @@ public:
if ( i<nf-1 ) *dst++ = '\n';
}
*dst = 0;
- int old_event = Fl::e_number;
- Fl::belowmouse()->handle(Fl::e_number = FL_PASTE);
- Fl::e_number = old_event;
- free( Fl::e_text );
ReleaseStgMedium( &medium );
- SetForegroundWindow( hwnd );
- return S_OK;
+ currDragResult = 1;
+ return currDragResult;
}
- return S_OK;
+ currDragResult = 0;
+ return currDragResult;
}
} flDropTarget;
IDropTarget *flIDropTarget = &flDropTarget;
+IDataObject *FLDropTarget::currDragRef = 0;
+char *FLDropTarget::currDragData = 0;
+int FLDropTarget::currDragSize = 0;
+char FLDropTarget::currDragResult = 0;
+
/**
* this class is needed to allow FLTK apps to be a DnD source
*/