diff options
author | Damien Plisson <damien.plisson@yahoo.fr> | 2009-11-10 15:56:46 +0300 |
---|---|---|
committer | Damien Plisson <damien.plisson@yahoo.fr> | 2009-11-10 15:56:46 +0300 |
commit | af2e6c38e99024d5055e66e2aea75de61c3280e9 (patch) | |
tree | f7c58a77af74ccdab2cb13bd48a2e587c6ad32a6 /intern/ghost | |
parent | 14f9e686fa7b729a36549778fcf8e2cfd31bf424 (diff) |
Drag & drop implementation at GHOST level (only OSX for now)
The dragging sequence is performed in four phases:
- Start sequence (GHOST_kEventDraggingEntered) that tells a drag'n'drop operation has started. Already gives the object data type, and the entering mouse location
- Update mouse position (GHOST_kEventDraggingUpdated) sent upon each mouse move until the drag'n'drop operation stops, to give the updated mouse position.
Useful to highlight a potential destination, and update the status (through GHOST_setAcceptDragOperation) telling if the object can be dropped at the current cursor position.
- Abort drag'n'drop sequence (GHOST_kEventDraggingExited) sent when the user moved the mouse outside the window.
- Send the dropped data (GHOST_kEventDraggingDropDone)
- Outside of the normal sequence, dropped data can be sent (GHOST_kEventDraggingDropOnIcon). This can happen when the user drops an object on the application icon. (Also used in OSX to pass the filename of the document the user doubled-clicked in the finder)
Note that the event handler is responsible for freeing the received data.
And the mouse position is sent directly in blender client coordinates (y=0 at bottom)
The GHOST_setAcceptDragOperation(TRUE) call must be placed before the user drops the object for it to be accepted.
Current handled data types :
- Text string
- Array of filenames (full paths)
- Bitmap image (not implemented yet)
Diffstat (limited to 'intern/ghost')
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 11 | ||||
-rw-r--r-- | intern/ghost/GHOST_ISystem.h | 21 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 30 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 7 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_EventDragnDrop.h | 91 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.cpp | 10 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.h | 18 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.h | 16 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.mm | 98 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowCocoa.h | 4 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowCocoa.mm | 77 |
11 files changed, 380 insertions, 3 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index bd812177f17..5e434c0eaa0 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -406,6 +406,17 @@ extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, GHOST_TButtonMask mask, int* isDown); + +/*************************************************************************************** + ** Drag'n'drop operations + ***************************************************************************************/ + +/** + * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop + */ +extern void GHOST_setAcceptDragOperation(GHOST_SystemHandle systemhandle, GHOST_TInt8 canAccept); + + /** * Returns the event type. * @param eventhandle The handle to the event diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 08794dfd085..e56a0dae879 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -351,6 +351,11 @@ public: */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; + + /*************************************************************************************** + ** Access to clipboard. + ***************************************************************************************/ + /** * Returns the selection buffer * @return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer @@ -363,6 +368,22 @@ public: */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; + + /*************************************************************************************** + ** Drag'n'drop operations + ***************************************************************************************/ + + /** + * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop + */ + virtual void setAcceptDragOperation(bool canAccept) = 0; + + /** + * Returns acceptance of the dropped object + * Usually called by the "object dropped" event handling function + */ + virtual bool canAcceptDragOperation() const = 0; + protected: /** * Initialize the system. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index e98e58740ad..5c888e218d8 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -167,6 +167,12 @@ typedef enum { GHOST_kEventWindowUpdate, GHOST_kEventWindowSize, GHOST_kEventWindowMove, + + GHOST_kEventDraggingEntered, + GHOST_kEventDraggingUpdated, + GHOST_kEventDraggingExited, + GHOST_kEventDraggingDropDone, + GHOST_kEventDraggingDropOnIcon, GHOST_kEventTimer, @@ -368,6 +374,30 @@ typedef struct { } GHOST_TEventWheelData; +typedef enum { + GHOST_kDragnDropTypeUnknown =0, + GHOST_kDragnDropTypeFilenames, /*Array of strings representing file names (full path) */ + GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string */ + GHOST_kDragnDropTypeBitmap /*Bitmap image data */ +} GHOST_TDragnDropTypes; + +typedef struct { + /** The x-coordinate of the cursor position. */ + GHOST_TInt32 x; + /** The y-coordinate of the cursor position. */ + GHOST_TInt32 y; + /** The dropped item type */ + GHOST_TDragnDropTypes dataType; + /** The "dropped content" */ + GHOST_TEventDataPtr data; +} GHOST_TEventDragnDropData; + +typedef struct { + int count; + GHOST_TUns8 **strings; +} GHOST_TStringArray; + + /* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */ /* as all USB device controls are likely to use ints, this is also more future proof */ //typedef struct { diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 0160df552cc..76b3d7caf7e 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -404,6 +404,13 @@ GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, } +void GHOST_setAcceptDragOperation(GHOST_SystemHandle systemhandle, GHOST_TInt8 canAccept) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + + system->setAcceptDragOperation(canAccept); +} + GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle) { diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h new file mode 100644 index 00000000000..9731ddf01dc --- /dev/null +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -0,0 +1,91 @@ +/** + * $Id: GHOST_EventDragnDrop.h 13161 2008-01-07 19:13:47Z hos $ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Damien Plisson 11/2009 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_EVENT_DRAGNDROP_H_ +#define _GHOST_EVENT_DRAGNDROP_H_ + +#include "GHOST_Event.h" + +/** + * Drag & drop event + * + * The dragging sequence is performed in four phases: + * + * <li> Start sequence (GHOST_kEventDraggingEntered) that tells a drag'n'drop operation has started. Already gives the object data type, + * and the entering mouse location + * + * <li> Update mouse position (GHOST_kEventDraggingUpdated) sent upon each mouse move until the drag'n'drop operation stops, to give the updated mouse position. + * Useful to highlight a potential destination, and update the status (through GHOST_setAcceptDragOperation) telling if the object can be dropped at + * the current cursor position. + * + * <li> Abort drag'n'drop sequence (GHOST_kEventDraggingExited) sent when the user moved the mouse outside the window. + * + * <li> Send the dropped data (GHOST_kEventDraggingDropDone) + * + * <li> Outside of the normal sequence, dropped data can be sent (GHOST_kEventDraggingDropOnIcon). This can happen when the user drops an object + * on the application icon. (Also used in OSX to pass the filename of the document the user doubled-clicked in the finder) + * + * <br><br>Note that the event handler is responsible for freeing the received data. + * <br>And the mouse positions are given in Blender coordinates (y=0 at bottom) + * + * <br>Currently supported object types : + * <li>UTF-8 string + * <li>array of strings representing filenames (GHOST_TStringArray) + * <li>bitmap image + */ +class GHOST_EventDragnDrop : public GHOST_Event +{ +public: + /** + * Constructor. + * @param time The time this event was generated. + * @param type The type of this event. + * @param dataType The type of the drop candidate object + * @param window The window where the event occured + * @param x The x-coordinate of the location the cursor was at at the time of the event. + * @param y The y-coordinate of the location the cursor was at at the time of the event. + * @param data The "content" dropped in the window + */ + GHOST_EventDragnDrop(GHOST_TUns64 time, GHOST_TEventType type, GHOST_TDragnDropTypes dataType, GHOST_IWindow* window, + int x, int y, GHOST_TEventDataPtr data) + : GHOST_Event(time, type, window) + { + m_dragnDropEventData.x = x; + m_dragnDropEventData.y = y; + m_dragnDropEventData.dataType = dataType; + m_dragnDropEventData.data = data; + m_data = &m_dragnDropEventData; + } + +protected: + /** The x,y-coordinates of the cursor position. */ + GHOST_TEventDragnDropData m_dragnDropEventData; +}; + +#endif // _GHOST_EVENT_DRAGNDROP_H_ + diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 84298d3e3ff..cccee12d696 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -54,6 +54,7 @@ GHOST_System::GHOST_System() : m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0) { + m_canAcceptDragOperation = false; } @@ -275,6 +276,15 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown return success; } +void GHOST_System::setAcceptDragOperation(bool canAccept) +{ + m_canAcceptDragOperation = canAccept; +} + +bool GHOST_System::canAcceptDragOperation() const +{ + return m_canAcceptDragOperation; +} GHOST_TSuccess GHOST_System::init() { diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 066fe4b93d3..542553e830e 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -231,6 +231,21 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const; + + /*************************************************************************************** + ** Drag'n'drop operations + ***************************************************************************************/ + + /** + * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop + */ + virtual void setAcceptDragOperation(bool canAccept); + + /** + * Returns acceptance of the dropped object + * Usually called by the "object dropped" event handling function + */ + virtual bool canAcceptDragOperation() const; /*************************************************************************************** ** Other (internal) functionality. @@ -332,6 +347,9 @@ protected: /** The N-degree of freedom device manager */ GHOST_NDOFManager* m_ndofManager; + + /** The acceptance of the "drop candidate" of the current drag'n'drop operation */ + bool m_canAcceptDragOperation; /** Prints all the events. */ #ifdef GHOST_DEBUG diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index e880f851267..5ba3a2b373b 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -194,11 +194,25 @@ public: /** * Handles a window event. Called by GHOST_WindowCocoa window delegate - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @param eventType The type of window event + * @param window The window on which the event occured * @return Indication whether the event was handled. */ GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); + + /** + * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass + * @param eventType The type of drag'n'drop event + * @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) + * @param mouseX x mouse coordinate (in cocoa base window coordinates) + * @param mouseY y mouse coordinate + * @param window The window on which the event occured + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, + GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data); + protected: /** * Initializes the system. diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 73be363dff1..c7127e26a4a 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -41,6 +41,7 @@ #include "GHOST_EventCursor.h" #include "GHOST_EventWheel.h" #include "GHOST_EventNDOF.h" +#include "GHOST_EventDragnDrop.h" #include "GHOST_TimerManager.h" #include "GHOST_TimerTask.h" @@ -413,6 +414,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { NSLog(@"\nGet open file event from cocoa : %@",filename); + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropOnIcon, GHOST_kDragnDropTypeFilenames, nil, 0, 0, [NSArray arrayWithObject:filename]); return YES; } @@ -880,6 +882,102 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, return GHOST_kSuccess; } +//Note: called from NSWindow subclass +GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, + GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data) +{ + if (!validWindow(window)) { + return GHOST_kFailure; + } + switch(eventType) + { + case GHOST_kEventDraggingEntered: + setAcceptDragOperation(FALSE); //Drag operation needs to be accepted explicitely by the event manager + case GHOST_kEventDraggingUpdated: + case GHOST_kEventDraggingExited: + pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),GHOST_kEventDraggingEntered,draggedObjectType,window,mouseX,mouseY,NULL)); + break; + + case GHOST_kEventDraggingDropDone: + case GHOST_kEventDraggingDropOnIcon: + { + GHOST_TUns8 * temp_buff; + GHOST_TStringArray *strArray; + NSArray *droppedArray; + size_t pastedTextSize; + NSString *droppedStr; + GHOST_TEventDataPtr eventData; + int i; + + if (!data) return GHOST_kFailure; + + switch (draggedObjectType) { + case GHOST_kDragnDropTypeBitmap: + //TODO: implement bitmap conversion to a blender friendly format + break; + case GHOST_kDragnDropTypeFilenames: + droppedArray = (NSArray*)data; + + strArray = (GHOST_TStringArray*)malloc(sizeof(GHOST_TStringArray)); + if (!strArray) return GHOST_kFailure; + + strArray->count = [droppedArray count]; + if (strArray->count == 0) return GHOST_kFailure; + + strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*)); + + for (i=0;i<strArray->count;i++) + { + droppedStr = [droppedArray objectAtIndex:i]; + + pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); + + if (!temp_buff) { + strArray->count = i; + break; + } + + strncpy((char*)temp_buff, [droppedStr UTF8String], pastedTextSize); + temp_buff[pastedTextSize] = '\0'; + + strArray->strings[i] = temp_buff; + } + + eventData = (GHOST_TEventDataPtr) strArray; + break; + + case GHOST_kDragnDropTypeString: + droppedStr = (NSString*)data; + pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); + + if (temp_buff == NULL) { + return GHOST_kFailure; + } + + strncpy((char*)temp_buff, [droppedStr UTF8String], pastedTextSize); + + temp_buff[pastedTextSize] = '\0'; + + eventData = (GHOST_TEventDataPtr) temp_buff; + break; + + default: + return GHOST_kFailure; + break; + } + pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),GHOST_kEventDraggingEntered,draggedObjectType,window,mouseX,mouseY,eventData)); + } + break; + default: + return GHOST_kFailure; + } + return GHOST_kSuccess; +} + + GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() { GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow(); diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index e3479ada5d6..e59d9c17333 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -40,6 +40,8 @@ #include "GHOST_Window.h" #include "STR_String.h" +@class CocoaWindow; + class GHOST_SystemCocoa; /** @@ -264,7 +266,7 @@ protected: virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); /** The window containing the OpenGL view */ - NSWindow *m_window; + CocoaWindow *m_window; /** The openGL view */ NSOpenGLView *m_openGLView; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 6d6829f3925..459a4a54ee3 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -124,16 +124,86 @@ extern "C" { //We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events) @interface CocoaWindow: NSWindow { - + GHOST_SystemCocoa *systemCocoa; + GHOST_WindowCocoa *associatedWindow; + GHOST_TDragnDropTypes m_draggedObjectType; } +- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; @end @implementation CocoaWindow +- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa +{ + systemCocoa = sysCocoa; + associatedWindow = winCocoa; +} -(BOOL)canBecomeKeyWindow { return YES; } +//The drag'n'drop dragging destination methods +- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender +{ + NSPoint mouseLocation = [sender draggingLocation]; + NSPasteboard *draggingPBoard = [sender draggingPasteboard]; + + if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeBitmap; + else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeFilenames; + else if ([[draggingPBoard types] containsObject:NSStringPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeString; + else return NSDragOperationNone; + + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); + return NSDragOperationCopy; +} + + +- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender +{ + NSPoint mouseLocation = [sender draggingLocation]; + + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); + return NSDragOperationCopy; +} + +- (void)draggingExited:(id < NSDraggingInfo >)sender +{ + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, associatedWindow, 0, 0, nil); + m_draggedObjectType = GHOST_kDragnDropTypeUnknown; +} + +- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender +{ + if (systemCocoa->canAcceptDragOperation()) + return YES; + else + return NO; +} + +- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender +{ + NSPoint mouseLocation = [sender draggingLocation]; + NSPasteboard *draggingPBoard = [sender draggingPasteboard]; + id data; + + switch (m_draggedObjectType) { + case GHOST_kDragnDropTypeBitmap: + data = [draggingPBoard dataForType:NSTIFFPboardType]; + break; + case GHOST_kDragnDropTypeFilenames: + data = [draggingPBoard propertyListForType:NSFilenamesPboardType]; + break; + case GHOST_kDragnDropTypeString: + data = [draggingPBoard stringForType:@"public.utf8-plain-text"]; + break; + default: + return NO; + break; + } + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, (void*)data); + return YES; +} + @end @@ -207,6 +277,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( return; } + [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; + //Forbid to resize the window below the blender defined minimum one minSize.width = 320; minSize.height = 240; @@ -259,6 +331,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( [m_window setAcceptsMouseMovedEvents:YES]; + [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, + NSStringPboardType, NSTIFFPboardType, nil]]; + if (state == GHOST_kWindowStateFullScreen) setState(GHOST_kWindowStateFullScreen); |