summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt3
-rw-r--r--indra/llwindow/lldragdropwin32.cpp370
-rw-r--r--indra/llwindow/lldragdropwin32.h80
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp5
-rw-r--r--indra/llwindow/llwindowcallbacks.h15
-rw-r--r--indra/llwindow/llwindowmacosx.cpp195
-rw-r--r--indra/llwindow/llwindowmacosx.h16
-rw-r--r--indra/llwindow/llwindowwin32.cpp33
-rw-r--r--indra/llwindow/llwindowwin32.h6
9 files changed, 709 insertions, 14 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 7b1cab696f..77c6fa57b6 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -12,6 +12,7 @@ project(llwindow)
include(00-Common)
include(DirectX)
+include(DragDrop)
include(LLCommon)
include(LLImage)
include(LLMath)
@@ -102,11 +103,13 @@ if (WINDOWS)
llwindowwin32.cpp
lldxhardware.cpp
llkeyboardwin32.cpp
+ lldragdropwin32.cpp
)
list(APPEND llwindow_HEADER_FILES
llwindowwin32.h
lldxhardware.h
llkeyboardwin32.h
+ lldragdropwin32.h
)
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp
new file mode 100644
index 0000000000..9b80fe0a84
--- /dev/null
+++ b/indra/llwindow/lldragdropwin32.cpp
@@ -0,0 +1,370 @@
+/**
+ * @file lldragdrop32.cpp
+ * @brief Handler for Windows specific drag and drop (OS to client) code
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+
+#if LL_OS_DRAGDROP_ENABLED
+
+#include "linden_common.h"
+
+#include "llwindowwin32.h"
+#include "llkeyboardwin32.h"
+#include "llwindowcallbacks.h"
+#include "lldragdropwin32.h"
+
+class LLDragDropWin32Target:
+ public IDropTarget
+{
+ public:
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ LLDragDropWin32Target( HWND hWnd ) :
+ mRefCount( 1 ),
+ mAppWindowHandle( hWnd ),
+ mAllowDrop( false)
+ {
+ };
+
+ virtual ~LLDragDropWin32Target()
+ {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ ULONG __stdcall AddRef( void )
+ {
+ return InterlockedIncrement( &mRefCount );
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ ULONG __stdcall Release( void )
+ {
+ LONG count = InterlockedDecrement( &mRefCount );
+
+ if ( count == 0 )
+ {
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return count;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject )
+ {
+ if ( iid == IID_IUnknown || iid == IID_IDropTarget )
+ {
+ AddRef();
+ *ppvObject = this;
+ return S_OK;
+ }
+ else
+ {
+ *ppvObject = 0;
+ return E_NOINTERFACE;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
+ {
+ FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+
+ // support CF_TEXT using a HGLOBAL?
+ if ( S_OK == pDataObject->QueryGetData( &fmtetc ) )
+ {
+ mAllowDrop = true;
+ mDropUrl = std::string();
+ mIsSlurl = false;
+
+ STGMEDIUM stgmed;
+ if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) )
+ {
+ PVOID data = GlobalLock( stgmed.hGlobal );
+ mDropUrl = std::string( (char*)data );
+ // XXX MAJOR MAJOR HACK!
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ if (NULL != window_imp)
+ {
+ LLCoordGL gl_coord( 0, 0 );
+
+ POINT pt2;
+ pt2.x = pt.x;
+ pt2.y = pt.y;
+ ScreenToClient( mAppWindowHandle, &pt2 );
+
+ LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
+ window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ MASK mask = gKeyboard->currentMask(TRUE);
+
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
+
+ switch (result)
+ {
+ case LLWindowCallbacks::DND_COPY:
+ *pdwEffect = DROPEFFECT_COPY;
+ break;
+ case LLWindowCallbacks::DND_LINK:
+ *pdwEffect = DROPEFFECT_LINK;
+ break;
+ case LLWindowCallbacks::DND_MOVE:
+ *pdwEffect = DROPEFFECT_MOVE;
+ break;
+ case LLWindowCallbacks::DND_NONE:
+ default:
+ *pdwEffect = DROPEFFECT_NONE;
+ break;
+ }
+ };
+
+ GlobalUnlock( stgmed.hGlobal );
+ ReleaseStgMedium( &stgmed );
+ };
+ SetFocus( mAppWindowHandle );
+ }
+ else
+ {
+ mAllowDrop = false;
+ *pdwEffect = DROPEFFECT_NONE;
+ };
+
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
+ {
+ if ( mAllowDrop )
+ {
+ // XXX MAJOR MAJOR HACK!
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ if (NULL != window_imp)
+ {
+ LLCoordGL gl_coord( 0, 0 );
+
+ POINT pt2;
+ pt2.x = pt.x;
+ pt2.y = pt.y;
+ ScreenToClient( mAppWindowHandle, &pt2 );
+
+ LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
+ window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ MASK mask = gKeyboard->currentMask(TRUE);
+
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DNDA_TRACK, mDropUrl );
+
+ switch (result)
+ {
+ case LLWindowCallbacks::DND_COPY:
+ *pdwEffect = DROPEFFECT_COPY;
+ break;
+ case LLWindowCallbacks::DND_LINK:
+ *pdwEffect = DROPEFFECT_LINK;
+ break;
+ case LLWindowCallbacks::DND_MOVE:
+ *pdwEffect = DROPEFFECT_MOVE;
+ break;
+ case LLWindowCallbacks::DND_NONE:
+ default:
+ *pdwEffect = DROPEFFECT_NONE;
+ break;
+ }
+ };
+ }
+ else
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ };
+
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall DragLeave( void )
+ {
+ // XXX MAJOR MAJOR HACK!
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ if (NULL != window_imp)
+ {
+ LLCoordGL gl_coord( 0, 0 );
+ MASK mask = gKeyboard->currentMask(TRUE);
+ window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl );
+ };
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
+ {
+ if ( mAllowDrop )
+ {
+ // window impl stored in Window data (neat!)
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
+ if ( NULL != window_imp )
+ {
+ LLCoordGL gl_coord( 0, 0 );
+
+ POINT pt_client;
+ pt_client.x = pt.x;
+ pt_client.y = pt.y;
+ ScreenToClient( mAppWindowHandle, &pt_client );
+
+ LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
+ window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
+ llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl;
+ llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl;
+ llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl;
+ llinfos << llendl;
+
+ // no keyboard modifier option yet but we could one day
+ MASK mask = gKeyboard->currentMask( TRUE );
+
+ // actually do the drop
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DNDA_DROPPED, mDropUrl );
+
+ switch (result)
+ {
+ case LLWindowCallbacks::DND_COPY:
+ *pdwEffect = DROPEFFECT_COPY;
+ break;
+ case LLWindowCallbacks::DND_LINK:
+ *pdwEffect = DROPEFFECT_LINK;
+ break;
+ case LLWindowCallbacks::DND_MOVE:
+ *pdwEffect = DROPEFFECT_MOVE;
+ break;
+ case LLWindowCallbacks::DND_NONE:
+ default:
+ *pdwEffect = DROPEFFECT_NONE;
+ break;
+ }
+ };
+ }
+ else
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ };
+
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ private:
+ LONG mRefCount;
+ HWND mAppWindowHandle;
+ bool mAllowDrop;
+ std::string mDropUrl;
+ bool mIsSlurl;
+ friend class LLWindowWin32;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLDragDropWin32::LLDragDropWin32() :
+ mDropTarget( NULL ),
+ mDropWindowHandle( NULL )
+
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLDragDropWin32::~LLDragDropWin32()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLDragDropWin32::init( HWND hWnd )
+{
+ if ( NOERROR != OleInitialize( NULL ) )
+ return FALSE;
+
+ mDropTarget = new LLDragDropWin32Target( hWnd );
+ if ( mDropTarget )
+ {
+ HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE );
+ if ( S_OK == result )
+ {
+ result = RegisterDragDrop( hWnd, mDropTarget );
+ if ( S_OK != result )
+ {
+ // RegisterDragDrop failed
+ return false;
+ };
+
+ // all ok
+ mDropWindowHandle = hWnd;
+ }
+ else
+ {
+ // Unable to lock OLE object
+ return false;
+ };
+ };
+
+ // success
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLDragDropWin32::reset()
+{
+ if ( mDropTarget )
+ {
+ RevokeDragDrop( mDropWindowHandle );
+ CoLockObjectExternal( mDropTarget, FALSE, TRUE );
+ mDropTarget->Release();
+ };
+
+ OleUninitialize();
+}
+
+#endif // LL_OS_DRAGDROP_ENABLED
+
+#endif // LL_WINDOWS
+
diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h
new file mode 100644
index 0000000000..9686626d7c
--- /dev/null
+++ b/indra/llwindow/lldragdropwin32.h
@@ -0,0 +1,80 @@
+/**
+ * @file lldragdrop32.cpp
+ * @brief Handler for Windows specific drag and drop (OS to client) code
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+
+#if LL_OS_DRAGDROP_ENABLED
+
+#ifndef LL_LLDRAGDROP32_H
+#define LL_LLDRAGDROP32_H
+
+#include <windows.h>
+#include <ole2.h>
+
+class LLDragDropWin32
+{
+ public:
+ LLDragDropWin32();
+ ~LLDragDropWin32();
+
+ bool init( HWND hWnd );
+ void reset();
+
+ private:
+ IDropTarget* mDropTarget;
+ HWND mDropWindowHandle;
+};
+#endif // LL_LLDRAGDROP32_H
+
+#else // LL_OS_DRAGDROP_ENABLED
+
+#ifndef LL_LLDRAGDROP32_H
+#define LL_LLDRAGDROP32_H
+
+#include <windows.h>
+#include <ole2.h>
+
+// imposter class that does nothing
+class LLDragDropWin32
+{
+ public:
+ LLDragDropWin32() {};
+ ~LLDragDropWin32() {};
+
+ bool init( HWND hWnd ) { return false; };
+ void reset() { };
+};
+#endif // LL_LLDRAGDROP32_H
+
+#endif // LL_OS_DRAGDROP_ENABLED
+
+#endif // LL_WINDOWS
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 72f9997149..6d9f012cc3 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -163,6 +163,11 @@ void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *da
{
}
+LLWindowCallbacks::DragNDropResult LLWindowCallbacks::handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data )
+{
+ return LLWindowCallbacks::DND_NONE;
+}
+
BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window)
{
return FALSE;
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index abc66c42a2..42add8dde0 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -71,6 +71,21 @@ public:
virtual BOOL handleTimerEvent(LLWindow *window);
virtual BOOL handleDeviceChange(LLWindow *window);
+ enum DragNDropAction {
+ DNDA_START_TRACKING = 0,// Start tracking an incoming drag
+ DNDA_TRACK, // User is dragging an incoming drag around the window
+ DNDA_STOP_TRACKING, // User is no longer dragging an incoming drag around the window (may have either cancelled or dropped on the window)
+ DNDA_DROPPED // User dropped an incoming drag on the window (this is the "commit" event)
+ };
+
+ enum DragNDropResult {
+ DND_NONE = 0, // No drop allowed
+ DND_MOVE, // Drop accepted would result in a "move" operation
+ DND_COPY, // Drop accepted would result in a "copy" operation
+ DND_LINK // Drop accepted would result in a "link" operation
+ };
+ virtual DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data);
+
virtual void handlePingWatchdog(LLWindow *window, const char * msg);
virtual void handlePauseWatchdog(LLWindow *window);
virtual void handleResumeWatchdog(LLWindow *window);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index ed62faece6..9ccd4c7f97 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -278,6 +278,8 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator);
mGlobalHandlerRef = NULL;
mWindowHandlerRef = NULL;
+
+ mDragOverrideCursor = -1;
// We're not clipping yet
SetRect( &mOldMouseClip, 0, 0, 0, 0 );
@@ -499,8 +501,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
// Set up window event handlers (some window-related events ONLY go to window handlers.)
InstallStandardEventHandler(GetWindowEventTarget(mWindow));
- InstallWindowEventHandler (mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
-
+ InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
+#if LL_OS_DRAGDROP_ENABLED
+ InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this );
+ InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this );
+#endif // LL_OS_DRAGDROP_ENABLED
}
{
@@ -2174,11 +2179,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
}
else
{
- MASK mask = 0;
- if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
- if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
- if(modifiers & optionKey) { mask |= MASK_ALT; }
-
+ MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
+
llassert( actualType == typeUnicodeText );
// The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar.
@@ -2795,6 +2797,14 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
{
OSStatus result = noErr;
+ if (mDragOverrideCursor != -1)
+ {
+ // A drag is in progress...remember the requested cursor and we'll
+ // restore it when it is done
+ mCurrentCursor = cursor;
+ return;
+ }
+
if (cursor == UI_CURSOR_ARROW
&& mBusyCount > 0)
{
@@ -3379,3 +3389,174 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
return std::vector<std::string>();
}
+// static
+MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers)
+{
+ MASK mask = 0;
+ if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
+ if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
+ if(modifiers & optionKey) { mask |= MASK_ALT; }
+ return mask;
+}
+
+#if LL_OS_DRAGDROP_ENABLED
+
+OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
+ void * handlerRefCon, DragRef drag)
+{
+ OSErr result = noErr;
+ LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
+
+ lldebugs << "drag tracking handler, message = " << message << llendl;
+
+ switch(message)
+ {
+ case kDragTrackingInWindow:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK);
+ break;
+
+ case kDragTrackingEnterHandler:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING);
+ break;
+
+ case kDragTrackingLeaveHandler:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING);
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+}
+
+OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
+ DragRef drag)
+{
+ LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
+ return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
+
+}
+
+OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action)
+{
+ OSErr result = dragNotAcceptedErr; // overall function result
+ OSErr err = noErr; // for local error handling
+
+ // Get the mouse position and modifiers of this drag.
+ SInt16 modifiers, mouseDownModifiers, mouseUpModifiers;
+ ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers);
+ MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
+
+ Point mouse_point;
+ // This will return the mouse point in global screen coords
+ ::GetDragMouse(drag, &mouse_point, NULL);
+ LLCoordScreen screen_coords(mouse_point.h, mouse_point.v);
+ LLCoordGL gl_pos;
+ convertCoords(screen_coords, &gl_pos);
+
+ // Look at the pasteboard and try to extract an URL from it
+ PasteboardRef pasteboard;
+ if(GetDragPasteboard(drag, &pasteboard) == noErr)
+ {
+ ItemCount num_items = 0;
+ // Treat an error here as an item count of 0
+ (void)PasteboardGetItemCount(pasteboard, &num_items);
+
+ // Only deal with single-item drags.
+ if(num_items == 1)
+ {
+ PasteboardItemID item_id = NULL;
+ CFArrayRef flavors = NULL;
+ CFDataRef data = NULL;
+
+ err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based.
+
+ // Try to extract an URL from the pasteboard
+ if(err == noErr)
+ {
+ err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors);
+ }
+
+ if(err == noErr)
+ {
+ if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL))
+ {
+ // This is an URL.
+ err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data);
+ }
+ else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText))
+ {
+ // This is a string that might be an URL.
+ err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data);
+ }
+
+ }
+
+ if(flavors != NULL)
+ {
+ CFRelease(flavors);
+ }
+
+ if(data != NULL)
+ {
+ std::string url;
+ url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data));
+ CFRelease(data);
+
+ if(!url.empty())
+ {
+ LLWindowCallbacks::DragNDropResult res =
+ mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
+
+ switch (res) {
+ case LLWindowCallbacks::DND_NONE: // No drop allowed
+ if (action == LLWindowCallbacks::DNDA_TRACK)
+ {
+ mDragOverrideCursor = kThemeNotAllowedCursor;
+ }
+ else {
+ mDragOverrideCursor = -1;
+ }
+ break;
+ case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
+ mDragOverrideCursor = kThemePointingHandCursor;
+ result = noErr;
+ break;
+ case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
+ mDragOverrideCursor = kThemeCopyArrowCursor;
+ result = noErr;
+ break;
+ case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation:
+ mDragOverrideCursor = kThemeAliasArrowCursor;
+ result = noErr;
+ break;
+ default:
+ mDragOverrideCursor = -1;
+ break;
+ }
+ // This overrides the cursor being set by setCursor.
+ // This is a bit of a hack workaround because lots of areas
+ // within the viewer just blindly set the cursor.
+ if (mDragOverrideCursor == -1)
+ {
+ // Restore the cursor
+ ECursorType temp_cursor = mCurrentCursor;
+ // get around the "setting the same cursor" code in setCursor()
+ mCurrentCursor = UI_CURSOR_COUNT;
+ setCursor(temp_cursor);
+ }
+ else {
+ // Override the cursor
+ SetThemeCursor(mDragOverrideCursor);
+ }
+
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+#endif // LL_OS_DRAGDROP_ENABLED
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index fbfa07fab4..377f10b6d4 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -34,6 +34,7 @@
#define LL_LLWINDOWMACOSX_H
#include "llwindow.h"
+#include "llwindowcallbacks.h"
#include "lltimer.h"
@@ -159,8 +160,15 @@ protected:
void adjustCursorDecouple(bool warpingMouse = false);
void fixWindowSize(void);
void stopDockTileBounce();
-
-
+ static MASK modifiersToMask(SInt16 modifiers);
+
+#if LL_OS_DRAGDROP_ENABLED
+ static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
+ void * handlerRefCon, DragRef theDrag);
+ static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
+ OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action);
+#endif // LL_OS_DRAGDROP_ENABLED
+
//
// Platform specific variables
//
@@ -193,11 +201,13 @@ protected:
U32 mFSAASamples;
BOOL mForceRebuild;
+ S32 mDragOverrideCursor;
+
F32 mBounceTime;
NMRec mBounceRec;
LLTimer mBounceTimer;
- // Imput method management through Text Service Manager.
+ // Input method management through Text Service Manager.
TSMDocumentID mTSMDocument;
BOOL mLanguageTextInputAllowed;
ScriptCode mTSMScriptCode;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index b591111b75..57a4921d92 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -38,6 +38,7 @@
// LLWindow library includes
#include "llkeyboardwin32.h"
+#include "lldragdropwin32.h"
#include "llpreeditor.h"
#include "llwindowcallbacks.h"
@@ -52,6 +53,7 @@
#include <mapi.h>
#include <process.h> // for _spawn
#include <shellapi.h>
+#include <fstream>
#include <Imm.h>
// Require DirectInput version 8
@@ -383,6 +385,9 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
gKeyboard = new LLKeyboardWin32();
gKeyboard->setCallbacks(callbacks);
+ // Initialize the Drag and Drop functionality
+ mDragDrop = new LLDragDropWin32;
+
// Initialize (boot strap) the Language text input management,
// based on the system's (user's) default settings.
allowLanguageTextInput(mPreeditor, FALSE);
@@ -620,6 +625,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
LLWindowWin32::~LLWindowWin32()
{
+ delete mDragDrop;
+
delete [] mWindowTitle;
mWindowTitle = NULL;
@@ -671,6 +678,8 @@ void LLWindowWin32::close()
return;
}
+ mDragDrop->reset();
+
// Make sure cursor is visible and we haven't mangled the clipping state.
setMouseClipping(FALSE);
showCursor();
@@ -1349,6 +1358,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
}
SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
+
+ // register this window as handling drag/drop events from the OS
+ DragAcceptFiles( mWindowHandle, TRUE );
+
+ mDragDrop->init( mWindowHandle );
//register joystick timer callback
SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
@@ -2354,11 +2368,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return 0;
case WM_COPYDATA:
- window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA");
- // received a URL
- PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
- window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
+ {
+ window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA");
+ // received a URL
+ PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
+ window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
+ };
return 0;
+
+ break;
}
window_imp->mCallbacks->handlePauseWatchdog(window_imp);
@@ -3528,6 +3546,13 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng
return wtext.substr(start, end - start);
}
+// final stage of handling drop requests - both from WM_DROPFILES message
+// for files and via IDropTarget interface requests.
+LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url )
+{
+ return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url );
+}
+
// Handle WM_IME_REQUEST message.
// If it handled the message, returns TRUE. Otherwise, FALSE.
// When it handled the message, the value to be returned from
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index e4e9179db7..6aca31b63e 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -39,6 +39,8 @@
#include <windows.h>
#include "llwindow.h"
+#include "llwindowcallbacks.h"
+#include "lldragdropwin32.h"
// Hack for async host by name
#define LL_WM_HOST_RESOLVED (WM_APP + 1)
@@ -114,6 +116,8 @@ public:
/*virtual*/ void interruptLanguageTextInput();
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url);
+ LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
+
static std::vector<std::string> getDynamicFallbackFontList();
protected:
@@ -205,6 +209,8 @@ protected:
LLPreeditor *mPreeditor;
+ LLDragDropWin32* mDragDrop;
+
friend class LLWindowManager;
};