From 0e6b88f993e034f1e3083bf26f08bc1dfd5ccf2e Mon Sep 17 00:00:00 2001 From: Damien Plisson Date: Mon, 1 Feb 2010 09:11:18 +0000 Subject: Cocoa : implement opening .blend file by double-clicking on it in OSX Finder When the user double-clicks on a document file in the Finder, OSX doesn't simply give the filename as a command-line argument when calling Blender, as it is done in other OSes. Instead, it launches the app if needed, and then sends an "openFile" event. The user can also open a document file by dropping its icon on the app dock icon. But as this is not real Drag'n'drop, I've renamed the Ghost event to a less confusing "GHOST_kEventOpenMainFile" name. DND Ghost wiki page updated : http://wiki.blender.org/index.php/BlenderDev/Blender2.5/DragnDrop --- intern/ghost/GHOST_Types.h | 3 +- intern/ghost/intern/GHOST_EventPrinter.cpp | 26 +++------- intern/ghost/intern/GHOST_EventString.h | 66 +++++++++++++++++++++++++ intern/ghost/intern/GHOST_SystemCocoa.mm | 30 +++++++++-- source/blender/windowmanager/intern/wm_window.c | 23 +++++++++ 5 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 intern/ghost/intern/GHOST_EventString.h diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 9bb8def00d0..ff60aaf9c03 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -173,7 +173,8 @@ typedef enum { GHOST_kEventDraggingUpdated, GHOST_kEventDraggingExited, GHOST_kEventDraggingDropDone, - GHOST_kEventDraggingDropOnIcon, + + GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup GHOST_kEventTimer, diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp index 91b55474441..81dafb74333 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.cpp +++ b/intern/ghost/intern/GHOST_EventPrinter.cpp @@ -148,26 +148,14 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event) } break; - case GHOST_kEventDraggingDropOnIcon: + case GHOST_kEventOpenMainFile: { - GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData(); - std::cout << "GHOST_kEventDraggingDropOnIcon, dragged object type : " << dragnDropData->dataType; - switch (dragnDropData->dataType) { - case GHOST_kDragnDropTypeString: - std::cout << " string received = " << (char*)dragnDropData->data; - break; - case GHOST_kDragnDropTypeFilenames: - { - GHOST_TStringArray *strArray = (GHOST_TStringArray*)dragnDropData->data; - int i; - std::cout << "\nReceived " << strArray->count << " filenames"; - for (i=0;icount;i++) - std::cout << " Filename #" << i << ": " << strArray->strings[i]; - } - break; - default: - break; - } + GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData(); + + if (eventData) + std::cout << "GHOST_kEventOpenMainFile for path : " << (char*)eventData; + else + std::cout << "GHOST_kEventOpenMainFile with no path specified!!"; } break; diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h new file mode 100644 index 00000000000..812a413b06d --- /dev/null +++ b/intern/ghost/intern/GHOST_EventString.h @@ -0,0 +1,66 @@ +/** + * $Id: GHOST_EventString.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): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** + * @file GHOST_EventString.h + * Declaration of GHOST_EventString class. + */ + +#ifndef _GHOST_EVENTSTRING_H_ +#define _GHOST_EVENTSTRING_H_ + +#include "GHOST_Event.h" + + +/** + * Generic class for events with string data + * @author Damien Plisson + * @date Feb 1, 2010 + */ +class GHOST_EventString : public GHOST_Event +{ +public: + /** + * Constructor. + * @param msec The time this event was generated. + * @param type The type of this event. + * @param window The generating window (or NULL if system event). + * @param data_ptr Pointer to the (unformatted) data associated with the event + */ + GHOST_EventString(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TEventDataPtr data_ptr) + : GHOST_Event(msec, type, window) { + m_data = data_ptr; + } + + ~GHOST_EventString() + { + if (m_data) free(m_data); + } +}; + +#endif // _GHOST_EVENTSTRING_H_ + diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 23f95f95df4..440425757c6 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -43,6 +43,7 @@ #include "GHOST_EventNDOF.h" #include "GHOST_EventTrackpad.h" #include "GHOST_EventDragnDrop.h" +#include "GHOST_EventString.h" #include "GHOST_TimerManager.h" #include "GHOST_TimerTask.h" @@ -1025,7 +1026,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data) { - if (!validWindow(window) && (eventType != GHOST_kEventDraggingDropOnIcon)) { + if (!validWindow(window)) { return GHOST_kFailure; } switch(eventType) @@ -1037,7 +1038,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType break; case GHOST_kEventDraggingDropDone: - case GHOST_kEventDraggingDropOnIcon: { GHOST_TUns8 * temp_buff; GHOST_TStringArray *strArray; @@ -1158,7 +1158,18 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) NSString *filepath = (NSString*)filepathStr; int confirmOpen = NSAlertAlternateReturn; NSArray *windowsList; + char * temp_buff; + size_t filenameTextSize; + GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow(); + + if (!window) { + return NO; + } + //Discard event if we are in cursor grab sequence, it'll lead to "stuck cursor" situation if the alert panel is raised + if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal)) + return GHOST_kExitCancel; + //Check open windows if some changes are not saved if (m_windowManager->getAnyModifiedState()) { @@ -1175,7 +1186,20 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) if (confirmOpen == NSAlertAlternateReturn) { - handleDraggingEvent(GHOST_kEventDraggingDropOnIcon,GHOST_kDragnDropTypeFilenames,NULL,0,0, [NSArray arrayWithObject:filepath]); + filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; + + temp_buff = (char*) malloc(filenameTextSize+1); + + if (temp_buff == NULL) { + return GHOST_kFailure; + } + + strncpy(temp_buff, [filepath cStringUsingEncoding:NSISOLatin1StringEncoding], filenameTextSize); + + temp_buff[filenameTextSize] = '\0'; + + pushEvent(new GHOST_EventString(getMilliSeconds(),GHOST_kEventOpenMainFile,window,(GHOST_TEventDataPtr) temp_buff)); + return YES; } else return NO; diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ed593cb8dcd..71efdab1f59 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -34,6 +34,7 @@ #include "DNA_listBase.h" #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" +#include "RNA_access.h" #include "MEM_guardedalloc.h" @@ -714,6 +715,28 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) } break; } + + case GHOST_kEventOpenMainFile: + { + PointerRNA props_ptr; + wmWindow *oldWindow; + char *path = GHOST_GetEventData(evt); + + if (path) { + /* operator needs a valid window in context, ensures + it is correctly set */ + oldWindow = CTX_wm_window(C); + CTX_wm_window_set(C, win); + + WM_operator_properties_create(&props_ptr, "WM_OT_open_mainfile"); + RNA_string_set(&props_ptr, "path", path); + WM_operator_name_call(C, "WM_OT_open_mainfile", WM_OP_EXEC_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); + + CTX_wm_window_set(C, oldWindow); + } + break; + } case GHOST_kEventDraggingDropDone: { wmEvent event= *(win->eventstate); /* copy last state, like mouse coords */ -- cgit v1.2.3