Initial Cocoa drag and drop support.

master
Geenz 2013-01-22 19:59:49 -05:00
parent 29e747c4f1
commit 461ab912a5
6 changed files with 145 additions and 133 deletions

View File

@ -15,6 +15,7 @@
@interface LLOpenGLView : NSOpenGLView
{
NSPoint mousePos;
std::string mLastDraggedUrl;
}
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync;

View File

@ -61,12 +61,13 @@
- (id) init
{
//[self registerForDraggedTypes:[NSArray arrayWithObjects:NSURLPboardType, NSFilenamesPboardType, nil]];
return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
}
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync
{
[self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
[self initWithFrame:frame];
// Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6.
@ -234,6 +235,49 @@
return [_window resignFirstResponder];
}
- (NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender
{
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [sender draggingSourceOperationMask];
pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSURLPboardType])
{
if (sourceDragMask & NSDragOperationLink) {
NSURL *fileUrl = [[pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:[NSDictionary dictionary]] objectAtIndex:0];
mLastDraggedUrl = [[fileUrl absoluteString] UTF8String];
return NSDragOperationLink;
}
}
return NSDragOperationNone;
}
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
callHandleDragUpdated(mLastDraggedUrl);
return NSDragOperationLink;
}
- (void) draggingExited:(id<NSDraggingInfo>)sender
{
callHandleDragExited(mLastDraggedUrl);
}
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
{
return YES;
}
- (BOOL) performDragOperation:(id<NSDraggingInfo>)sender
{
callHandleDragDropped(mLastDraggedUrl);
return true;
}
@end
// We use a custom NSWindow for our event handling.
@ -244,7 +288,7 @@
- (id) init
{
//[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType, nil]];
return self;
}
@ -378,6 +422,8 @@
callMouseExit();
}
- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view
{
NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation];

View File

@ -24,14 +24,6 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <boost/tr1/functional.hpp>
typedef std::tr1::function<void(unsigned short, unsigned int)> KeyCallback;
typedef std::tr1::function<void(unsigned int)> ModifierCallback;
typedef std::tr1::function<void(float*, unsigned int)> MouseCallback;
typedef std::tr1::function<void(wchar_t, unsigned int)> UnicodeCallback;
typedef std::tr1::function<void(unsigned int, unsigned int)> ResizeCallback;
typedef std::tr1::function<void(float)> ScrollWheelCallback;
typedef std::tr1::function<void()> VoidCallback;
// This will actually hold an NSCursor*, but that type is only available in objective C.
typedef void *CursorRef;
@ -59,6 +51,7 @@ void setIBeamCursor();
void setPointingHandCursor();
void setCopyCursor();
void setCrossCursor();
void setNotAllowedCursor();
void hideNSCursor();
void showNSCursor();
void hideNSCursorTillMove(bool hide);
@ -103,6 +96,12 @@ void callMiddleMouseUp(float *pos, unsigned int mask);
void callFocus();
void callFocusLost();
#include <string>
void callHandleDragEntered(std::string url);
void callHandleDragExited(std::string url);
void callHandleDragUpdated(std::string url);
void callHandleDragDropped(std::string url);
NSWindowRef getMainAppWindow();
GLViewRef getGLView();

View File

@ -143,6 +143,12 @@ void setCrossCursor()
[cursor set];
}
void setNotAllowedCursor()
{
NSCursor *cursor = [NSCursor operationNotAllowedCursor];
[cursor set];
}
void hideNSCursor()
{
[NSCursor hide];

View File

@ -248,7 +248,6 @@ void callLeftMouseDown(float *pos, MASK mask)
outCoords.mX = llround(pos[0]);
outCoords.mY = llround(pos[1]);
gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
LL_INFOS("Window") << outCoords.mX << ", " << outCoords.mY << LL_ENDL;
}
void callLeftMouseUp(float *pos, MASK mask)
@ -285,7 +284,6 @@ void callMouseMoved(float *pos, MASK mask)
gWindowImplementation->getMouseDeltas(deltas);
outCoords.mX += deltas[0];
outCoords.mY += deltas[1];
LL_INFOS("Mouse Movement") << "Moved coords: " << outCoords.mX << ", " << outCoords.mY << LL_ENDL;
gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0);
}
@ -339,6 +337,26 @@ void callMiddleMouseUp(float *pos, MASK mask)
gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask);
}
void callHandleDragEntered(std::string url)
{
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING);
}
void callHandleDragExited(std::string url)
{
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING);
}
void callHandleDragUpdated(std::string url)
{
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK);
}
void callHandleDragDropped(std::string url)
{
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED);
}
void LLWindowMacOSX::updateMouseDeltas(float* deltas)
{
if (mCursorDecoupled)
@ -1784,7 +1802,6 @@ S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef t
return result;
}
OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
DragRef drag)
{
@ -1792,126 +1809,69 @@ OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefC
return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
}
OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action)
*/
void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action)
{
OSErr result = dragNotAcceptedErr; // overall function result
OSErr err = noErr; // for local error handling
MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers());
// 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;
float mouse_point[2];
// This will return the mouse point in global screen coords
::GetDragMouse(drag, &mouse_point, NULL);
LLCoordScreen screen_coords(mouse_point.h, mouse_point.v);
getCursorPos(mWindow, mouse_point);
LLCoordScreen screen_coords(mouse_point[0], mouse_point[1]);
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)
if(!url.empty())
{
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)
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 = 0;
}
else {
mDragOverrideCursor = -1;
}
break;
case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
mDragOverrideCursor = UI_CURSOR_NO;
break;
case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
mDragOverrideCursor = UI_CURSOR_ARROWCOPY;
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)
{
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);
}
}
}
// 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
switch (mDragOverrideCursor) {
case 0:
setArrowCursor();
break;
case UI_CURSOR_NO:
setNotAllowedCursor();
case UI_CURSOR_ARROWCOPY:
setCopyCursor();
default:
break;
};
}
}
return result;
}
*/
#endif // LL_OS_DRAGDROP_ENABLED

View File

@ -123,7 +123,8 @@ public:
void updateMouseDeltas(float* deltas);
void getMouseDeltas(float* delta);
void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
@ -164,12 +165,11 @@ protected:
static MASK modifiersToMask(S16 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);
*/
//static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
//static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
#endif // LL_OS_DRAGDROP_ENABLED
//
@ -202,7 +202,7 @@ protected:
U32 mFSAASamples;
BOOL mForceRebuild;
S32 mDragOverrideCursor;
S32 mDragOverrideCursor;
F32 mBounceTime;
//NMRec mBounceRec;