diff options
author | Geenz <geenz@geenzo.com> | 2013-01-22 19:59:49 -0500 |
---|---|---|
committer | Geenz <geenz@geenzo.com> | 2013-01-22 19:59:49 -0500 |
commit | 461ab912a58b67579fffdf70ec7e38d682927185 (patch) | |
tree | 2489ae49226618c7797478ec5ac7b9cef8d540cf /indra/llwindow | |
parent | 29e747c4f17818816c502a3aa653b828e689be4a (diff) |
Initial Cocoa drag and drop support.
Diffstat (limited to 'indra/llwindow')
-rw-r--r-- | indra/llwindow/llopenglview-objc.h | 1 | ||||
-rw-r--r-- | indra/llwindow/llopenglview-objc.mm | 50 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx-objc.h | 15 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx-objc.mm | 6 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx.cpp | 186 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx.h | 16 |
6 files changed, 143 insertions, 131 deletions
diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index dd2f35aafc..1592e6e01d 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -15,6 +15,7 @@ @interface LLOpenGLView : NSOpenGLView { NSPoint mousePos; + std::string mLastDraggedUrl; } - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index ca66143b78..763cf0c981 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -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]; diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 57b3d11296..ebc1633f9d 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -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(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b6e5767203..7867226476 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -143,6 +143,12 @@ void setCrossCursor() [cursor set]; } +void setNotAllowedCursor() +{ + NSCursor *cursor = [NSCursor operationNotAllowedCursor]; + [cursor set]; +} + void hideNSCursor() { [NSCursor hide]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 95ad87d58f..f25fc82896 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -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 - - // Get the mouse position and modifiers of this drag. - SInt16 modifiers, mouseDownModifiers, mouseUpModifiers; - ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers); - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); + MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers()); - 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) - { - 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)) + 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) { - // This is a string that might be an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data); + mDragOverrideCursor = 0; } - - } - - 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); - } - + 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) + { + // 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 diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index c5e1b2290b..14d6e70fb3 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -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; |