Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Eagar <joeedh@gmail.com>2010-01-06 01:33:41 +0300
committerJoseph Eagar <joeedh@gmail.com>2010-01-06 01:33:41 +0300
commit67ff197cb1b0e79a95bf6546b5fe1a481b79fce1 (patch)
tree9f78d5cda71d200cab6475eb9c2747f7181adf3a /intern/ghost
parent473f235a6eee6c02cf41a1e173f53406b62440aa (diff)
parentffe13aeb232ac6bad3a98997b4a352f434293193 (diff)
Merge with trunk/2.5 at r25563
Most likely will not compile for others, I'd appreciate any build errors and missing files reports (I can never seem to get everything committed and all the build systems working without help). Porting over the sculpt/multires tools was a breeze, thanks goes to brecht for a design that didn't exclude ngons and was easy to port. Note that I've not tested externally-backed multires file support yet. Also, I still need to write version patch code for some cases. Some notes: * Like trunk, topological changes don't update multires right, so e.g. subdivide will duplicate multires data on the new faces, instead of subdividing it. * If you set the debug value (ctrl-alt-d) to 1 it'll turn on my experiments in speeding up sculpting on higher-res multires meshes (but note it makes partial redraw not completely accurate). * There's a bug where you have to go through editmode to get out of sculpt mode, not sure if I inherited or created this myself.
Diffstat (limited to 'intern/ghost')
-rw-r--r--intern/ghost/CMakeLists.txt6
-rw-r--r--intern/ghost/SConscript64
-rw-r--r--intern/ghost/intern/GHOST_Debug.h7
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp426
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.h155
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.cpp13
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h30
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm125
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp100
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h22
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp82
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h9
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm41
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp48
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h21
-rw-r--r--intern/ghost/intern/Makefile10
-rw-r--r--intern/ghost/make/msvc_9_0/ghost.vcproj8
18 files changed, 1093 insertions, 76 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 33af61baa07..77afcc929aa 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -41,9 +41,14 @@ IF(APPLE)
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerWin32.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemWin32.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowWin32.cpp")
+ LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DropTargetWin32.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerX11.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemX11.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowX11.cpp")
+
+ IF(WITH_QUICKTIME)
+ ADD_DEFINITIONS(-DWITH_QUICKTIME)
+ ENDIF(WITH_QUICKTIME)
ELSE(APPLE)
IF(WIN32)
SET(INC ${INC} ${WINTAB_INC})
@@ -59,6 +64,7 @@ ELSE(APPLE)
ELSE(WIN32)
SET(INC ${INC} ${X11_X11_INCLUDE_PATH})
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerWin32.cpp")
+ LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DropTargetWin32.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemWin32.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowWin32.cpp")
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCarbon.cpp")
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index 490b45afc1f..2a06a9d3c9e 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -8,37 +8,57 @@ window_system = env['OURPLATFORM']
sources = env.Glob('intern/*.cpp')
if window_system == 'darwin':
- sources += env.Glob('intern/*.mm')
+ sources += env.Glob('intern/*.mm')
-pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window']
+pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget']
+defs=['_USE_MATH_DEFINES']
if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6'):
- for f in pf:
- sources.remove('intern' + os.sep + f + 'Win32.cpp')
- sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+ for f in pf:
+ try:
+ sources.remove('intern' + os.sep + f + 'Win32.cpp')
+ sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+ except ValueError:
+ pass
elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
- for f in pf:
- sources.remove('intern' + os.sep + f + 'X11.cpp')
- sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+ for f in pf:
+ try:
+ sources.remove('intern' + os.sep + f + 'X11.cpp')
+ sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+ except ValueError:
+ pass
elif window_system == 'darwin':
- if env['WITH_GHOST_COCOA']:
- for f in pf:
- sources.remove('intern' + os.sep + f + 'Win32.cpp')
- sources.remove('intern' + os.sep + f + 'X11.cpp')
- sources.remove('intern' + os.sep + f + 'Carbon.cpp')
- else:
- for f in pf:
- sources.remove('intern' + os.sep + f + 'Win32.cpp')
- sources.remove('intern' + os.sep + f + 'X11.cpp')
- sources.remove('intern' + os.sep + f + 'Cocoa.mm')
+ if env['WITH_GHOST_COCOA']:
+ if env['WITH_BF_QUICKTIME']:
+ defs.append('WITH_QUICKTIME')
+ if env['USE_QTKIT']:
+ defs.append('USE_QTKIT')
+ for f in pf:
+ try:
+ sources.remove('intern' + os.sep + f + 'Win32.cpp')
+ sources.remove('intern' + os.sep + f + 'X11.cpp')
+ sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+ except ValueError:
+ pass
+ else:
+ for f in pf:
+ try:
+ sources.remove('intern' + os.sep + f + 'Win32.cpp')
+ sources.remove('intern' + os.sep + f + 'X11.cpp')
+ sources.remove('intern' + os.sep + f + 'Cocoa.mm')
+ except ValueError:
+ pass
else:
- print "Unknown window system specified."
- Exit()
+ print "Unknown window system specified."
+ Exit()
+if env['BF_GHOST_DEBUG']:
+ defs.append('BF_GHOST_DEBUG')
+
incs = '. ../string ' + env['BF_OPENGL_INC']
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
- incs = env['BF_WINTAB_INC'] + ' ' + incs
-env.BlenderLib ('bf_ghost', sources, Split(incs), defines=['_USE_MATH_DEFINES'], libtype=['intern','player'], priority = [40,15] )
+ incs = env['BF_WINTAB_INC'] + ' ' + incs
+env.BlenderLib ('bf_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index 7f836202720..1ca4ce2b6de 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -37,12 +37,17 @@
#ifdef WIN32
#ifdef _DEBUG
#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
- #define GHOST_DEBUG
+ // #define GHOST_DEBUG
#endif // _DEBUG
#endif // WIN32
+#ifdef BF_GHOST_DEBUG
+ #define GHOST_DEBUG // spit ghost events to stdout
+#endif // BF_GHOST_DEBUG
+
#ifdef GHOST_DEBUG
#include <iostream>
+ #include <stdio.h> //for printf()
#endif // GHOST_DEBUG
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
new file mode 100644
index 00000000000..631187cc6e8
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -0,0 +1,426 @@
+/**
+ * $Id$
+ * ***** 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 *****
+ */
+
+#include "GHOST_Debug.h"
+#include "GHOST_DropTargetWin32.h"
+
+#ifdef GHOST_DEBUG
+// utility
+void printLastError(void);
+#endif // GHOST_DEBUG
+
+
+GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 * window, GHOST_SystemWin32 * system)
+:
+m_window(window),
+m_system(system)
+{
+ m_cRef = 1;
+ m_hWnd = window->getHWND();
+ m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
+
+ // register our window as drop target
+ ::RegisterDragDrop(m_hWnd, this);
+}
+
+GHOST_DropTargetWin32::~GHOST_DropTargetWin32()
+{
+ ::RevokeDragDrop(m_hWnd);
+}
+
+
+/*
+ * IUnknown::QueryInterface
+ */
+HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface (REFIID riid, void ** ppvObj)
+{
+
+ if (!ppvObj)
+ return E_INVALIDARG;
+ *ppvObj = NULL;
+
+ if(riid == IID_IUnknown || riid == IID_IDropTarget)
+ {
+ AddRef();
+ *ppvObj = (void*)this;
+ return S_OK;
+ }
+ else
+ {
+ *ppvObj = 0;
+ return E_NOINTERFACE;
+ }
+}
+
+
+/*
+ * IUnknown::AddRef
+ */
+
+ULONG __stdcall GHOST_DropTargetWin32::AddRef(void)
+{
+ return ::InterlockedIncrement(&m_cRef);
+}
+
+/*
+ * IUnknown::Release
+ */
+ULONG __stdcall GHOST_DropTargetWin32::Release(void)
+{
+ ULONG refs = ::InterlockedDecrement(&m_cRef);
+
+ if(refs == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return refs;
+ }
+}
+
+/*
+ * Implementation of IDropTarget::DragEnter
+ */
+HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+{
+ // we don't know yet if we accept the drop.
+ m_window->setAcceptDragOperation(false);
+ *pdwEffect = DROPEFFECT_NONE;
+
+ m_draggedObjectType = getGhostType(pDataObject);
+ m_system->pushDragDropEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
+ return S_OK;
+}
+
+/*
+ * Implementation of IDropTarget::DragOver
+ */
+HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+{
+ if(m_window->canAcceptDragOperation())
+ {
+ *pdwEffect = allowedDropEffect(*pdwEffect);
+ }
+ else
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ //*pdwEffect = DROPEFFECT_COPY; // XXX Uncomment to test drop. Drop will not be called if pdwEffect == DROPEFFECT_NONE.
+ }
+ m_system->pushDragDropEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
+ return S_OK;
+}
+
+/*
+ * Implementation of IDropTarget::DragLeave
+ */
+HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
+{
+ m_system->pushDragDropEvent(GHOST_kEventDraggingExited, m_draggedObjectType, m_window, 0, 0, NULL);
+ m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
+ return S_OK;
+}
+
+/* Implementation of IDropTarget::Drop
+ * This function will not be called if pdwEffect is set to DROPEFFECT_NONE in
+ * the implementation of IDropTarget::DragOver
+ */
+HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
+{
+ void * data = getGhostData(pDataObject);
+ if(m_window->canAcceptDragOperation())
+ {
+ *pdwEffect = allowedDropEffect(*pdwEffect);
+
+ }
+ else
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ if (data)
+ m_system->pushDragDropEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, m_window, pt.x, pt.y, data );
+
+ m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
+ return S_OK;
+}
+
+/*
+ * Helpers
+ */
+
+DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dwAllowed)
+{
+ DWORD dwEffect = DROPEFFECT_NONE;
+ if(dwAllowed & DROPEFFECT_COPY)
+ dwEffect = DROPEFFECT_COPY;
+
+ return dwEffect;
+}
+
+GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject * pDataObject)
+{
+ /* Text
+ * Note: Unicode text is aviable as CF_TEXT too, the system can do the
+ * conversion, but we do the conversion ourself with WC_NO_BEST_FIT_CHARS.
+ */
+ FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ if(pDataObject->QueryGetData(&fmtetc) == S_OK)
+ {
+ return GHOST_kDragnDropTypeString;
+ }
+
+ // Filesnames
+ fmtetc.cfFormat = CF_HDROP;
+ if(pDataObject->QueryGetData(&fmtetc) == S_OK)
+ {
+ return GHOST_kDragnDropTypeFilenames;
+ }
+
+ return GHOST_kDragnDropTypeUnknown;
+}
+
+void * GHOST_DropTargetWin32::getGhostData(IDataObject * pDataObject)
+{
+ GHOST_TDragnDropTypes type = getGhostType(pDataObject);
+ switch(type)
+ {
+ case GHOST_kDragnDropTypeFilenames:
+ return getDropDataAsFilenames(pDataObject);
+ break;
+ case GHOST_kDragnDropTypeString:
+ return getDropDataAsString(pDataObject);
+ break;
+ case GHOST_kDragnDropTypeBitmap:
+ //return getDropDataAsBitmap(pDataObject);
+ break;
+ default:
+#ifdef GHOST_DEBUG
+ ::printf("\nGHOST_kDragnDropTypeUnknown");
+#endif // GHOST_DEBUG
+ return NULL;
+ break;
+ }
+ return NULL;
+}
+
+void * GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject * pDataObject)
+{
+ UINT totfiles, nvalid=0;
+ WCHAR fpath [MAX_PATH];
+ char * temp_path;
+ GHOST_TStringArray *strArray = NULL;
+ FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stgmed;
+ HDROP hdrop;
+
+ // Check if dataobject supplies the format we want.
+ // Double checking here, first in getGhostType.
+ if(pDataObject->QueryGetData(&fmtetc) == S_OK)
+ {
+ if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
+ {
+ hdrop = (HDROP)::GlobalLock(stgmed.hGlobal);
+
+ totfiles = ::DragQueryFileW ( hdrop, -1, NULL, 0 );
+ if (!totfiles)
+ {
+ ::GlobalUnlock(stgmed.hGlobal);
+ return NULL;
+ }
+
+ strArray = (GHOST_TStringArray*) ::malloc(sizeof(GHOST_TStringArray));
+ strArray->count = 0;
+ strArray->strings = (GHOST_TUns8**) ::malloc(totfiles*sizeof(GHOST_TUns8*));
+
+ for ( UINT nfile = 0; nfile < totfiles; nfile++ )
+ {
+ if ( ::DragQueryFileW ( hdrop, nfile, fpath, MAX_PATH ) > 0 )
+ {
+ if ( !WideCharToANSI(fpath, temp_path) )
+ {
+ continue;
+ }
+ // Just ignore paths that could not be converted verbatim.
+ if (strpbrk(temp_path, "?"))
+ {
+#ifdef GHOST_DEBUG
+ ::printf("\ndiscarding path that contains illegal characters: %s", temp_path);
+#endif // GHOST_DEBUG
+ ::free(temp_path);
+ temp_path = NULL;
+ continue;
+ }
+ strArray->strings[nvalid] = (GHOST_TUns8*) temp_path;
+ strArray->count = nvalid+1;
+ nvalid++;
+ }
+ }
+ // Free up memory.
+ ::GlobalUnlock(stgmed.hGlobal);
+ ::ReleaseStgMedium(&stgmed);
+
+ return strArray;
+ }
+ }
+ return NULL;
+}
+
+void * GHOST_DropTargetWin32::getDropDataAsString(IDataObject * pDataObject)
+{
+ char* tmp_string;
+ FORMATETC fmtetc = { CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stgmed;
+
+ // Try unicode first.
+ // Check if dataobject supplies the format we want.
+ if(pDataObject->QueryGetData(&fmtetc) == S_OK)
+ {
+ if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
+ {
+ LPCWSTR wstr = (LPCWSTR)::GlobalLock(stgmed.hGlobal);
+ if ( !WideCharToANSI(wstr, tmp_string) )
+ {
+ ::GlobalUnlock(stgmed.hGlobal);
+ return NULL;
+ }
+ // Free memory
+ ::GlobalUnlock(stgmed.hGlobal);
+ ::ReleaseStgMedium(&stgmed);
+#ifdef GHOST_DEBUG
+ ::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",tmp_string);
+#endif // GHOST_DEBUG
+ return tmp_string;
+ }
+ }
+
+ fmtetc.cfFormat = CF_TEXT;
+
+ if(pDataObject->QueryGetData(&fmtetc) == S_OK)
+ {
+ if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
+ {
+ char * str = (char*)::GlobalLock(stgmed.hGlobal);
+
+ tmp_string = (char*)::malloc(::strlen(str)+1);
+ if ( !tmp_string )
+ {
+ ::GlobalUnlock(stgmed.hGlobal);
+ return NULL;
+ }
+
+ if ( !::strcpy(tmp_string, str) )
+ {
+ ::free(tmp_string);
+ ::GlobalUnlock(stgmed.hGlobal);
+ return NULL;
+ }
+ // Free memory
+ ::GlobalUnlock(stgmed.hGlobal);
+ ::ReleaseStgMedium(&stgmed);
+
+ return tmp_string;
+ }
+ }
+
+ return NULL;
+}
+
+int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
+{
+ int size;
+ out = NULL; //caller should free if != NULL
+
+ // Get the required size.
+ size = ::WideCharToMultiByte(CP_ACP, //System Default Codepage
+ 0x00000400, // WC_NO_BEST_FIT_CHARS
+ in,
+ -1, //-1 null terminated, makes output null terminated too.
+ NULL,
+ 0,
+ NULL,NULL
+ );
+
+ if(!size)
+ {
+#ifdef GHOST_DEBUG
+ ::printLastError();
+#endif // GHOST_DEBUG
+ return 0;
+ }
+
+ out = (char*)::malloc(size);
+ if (!out)
+ {
+ ::printf("\nmalloc failed!!!");
+ return 0;
+ }
+
+ size = ::WideCharToMultiByte(CP_ACP,
+ 0x00000400,
+ in,
+ -1,
+ (LPSTR) out,
+ size,
+ NULL,NULL
+ );
+
+ if(!size)
+ {
+#ifdef GHOST_DEBUG
+ ::printLastError();
+#endif //GHOST_DEBUG
+ ::free(out);
+ out = NULL;
+ }
+ return size;
+}
+
+#ifdef GHOST_DEBUG
+void printLastError(void)
+{
+ LPTSTR s;
+ DWORD err;
+
+ err = GetLastError();
+ if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ err,
+ 0,
+ (LPTSTR)&s,
+ 0,
+ NULL)
+ )
+ {
+ printf("\nLastError: (%d) %s\n", (int)err, s);
+ LocalFree(s);
+ }
+}
+#endif // GHOST_DEBUG
+
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h
new file mode 100644
index 00000000000..03afcf88102
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.h
@@ -0,0 +1,155 @@
+/**
+ * $Id$
+ * ***** 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 *****
+ */
+#ifndef _GHOST_DROP_TARGET_WIN32_H_
+#define _GHOST_DROP_TARGET_WIN32_H_
+
+#include <windows.h>
+#include <string.h>
+#include <GHOST_Types.h>
+#include "GHOST_WindowWin32.h"
+#include "GHOST_SystemWin32.h"
+
+class GHOST_DropTargetWin32 : public IDropTarget
+{
+public:
+ /* IUnknownd implementation.
+ * Enables clients to get pointers to other interfaces on a given object
+ * through the QueryInterface method, and manage the existence of the object
+ * through the AddRef and Release methods. All other COM interfaces are
+ * inherited, directly or indirectly, from IUnknown. Therefore, the three
+ * methods in IUnknown are the first entries in the VTable for every interface.
+ */
+ HRESULT __stdcall QueryInterface (REFIID riid, void ** ppvObj);
+ ULONG __stdcall AddRef (void);
+ ULONG __stdcall Release (void);
+
+ /* IDropTarget implementation
+ + The IDropTarget interface is one of the interfaces you implement to
+ provide drag-and-drop operations in your application. It contains methods
+ used in any application that can be a target for data during a
+ drag-and-drop operation. A drop-target application is responsible for:
+ *
+ * - Determining the effect of the drop on the target application.
+ * - Incorporating any valid dropped data when the drop occurs.
+ * - Communicating target feedback to the source so the source application
+ * can provide appropriate visual feedback such as setting the cursor.
+ * - Implementing drag scrolling.
+ * - Registering and revoking its application windows as drop targets.
+ *
+ * The IDropTarget interface contains methods that handle all these
+ * responsibilities except registering and revoking the application window
+ * as a drop target, for which you must call the RegisterDragDrop and the
+ * RevokeDragDrop functions.
+ */
+
+ HRESULT __stdcall DragEnter (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
+ HRESULT __stdcall DragOver (DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
+ HRESULT __stdcall DragLeave (void);
+ HRESULT __stdcall Drop (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
+
+ /**
+ * Constructor
+ * With the modifier keys, we want to distinguish left and right keys.
+ * Sometimes this is not possible (Windows ME for instance). Then, we want
+ * events generated for both keys.
+ * @param window The window to register as drop target.
+ * @param system The associated system.
+ */
+ GHOST_DropTargetWin32(GHOST_WindowWin32 * window, GHOST_SystemWin32 * system);
+
+ /**
+ * Destructor
+ * Do NOT destroy directly. Use Release() instead to make COM happy.
+ */
+ ~GHOST_DropTargetWin32();
+
+private:
+
+ /* Internal helper functions */
+
+ /**
+ * Base the effect on those allowed by the dropsource.
+ * @param dwAllowed Drop sources allowed drop effect.
+ * @return The allowed drop effect.
+ */
+ DWORD allowedDropEffect(DWORD dwAllowed);
+
+ /**
+ * Query DataObject for the data types it supports.
+ * @param pDataObject Pointer to the DataObject.
+ * @return GHOST data type.
+ */
+ GHOST_TDragnDropTypes getGhostType(IDataObject * pDataObject);
+
+ /**
+ * Get data to pass in event.
+ * It checks the type and calls specific functions for each type.
+ * @param pDataObject Pointer to the DataObject.
+ * @return Pointer to data.
+ */
+ void * getGhostData(IDataObject * pDataObject);
+
+ /**
+ * Allocate data as file array to pass in event.
+ * @param pDataObject Pointer to the DataObject.
+ * @return Pointer to data.
+ */
+ void * getDropDataAsFilenames(IDataObject * pDataObject);
+
+ /**
+ * Allocate data as string to pass in event.
+ * @param pDataObject Pointer to the DataObject.
+ * @return Pointer to data.
+ */
+ void * getDropDataAsString(IDataObject * pDataObject);
+
+ /**
+ * Convert Unicode to ANSI, replacing unconvertable chars with '?'.
+ * The ANSI codepage is the system default codepage,
+ * and can change from system to system.
+ * @param in LPCWSTR.
+ * @param out char *. Is set to NULL on failure.
+ * @return 0 on failure. Else the size of the string including '\0'.
+ */
+ int WideCharToANSI(LPCWSTR in, char * &out);
+
+ /* Private member variables */
+ /* COM reference count. */
+ LONG m_cRef;
+ /* Handle of the associated window. */
+ HWND m_hWnd;
+ /* The associated GHOST_WindowWin32. */
+ GHOST_WindowWin32 * m_window;
+ /* The System. */
+ GHOST_SystemWin32 * m_system;
+ /* Data type of the dragged object */
+ GHOST_TDragnDropTypes m_draggedObjectType;
+
+};
+
+#endif // _GHOST_DROP_TARGET_WIN32_H_
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
index c6b3416669e..91b55474441 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.cpp
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -49,7 +49,7 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
if (event->getType() == GHOST_kEventWindowUpdate) return false;
- std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: ";
+ std::cout << "\nGHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: ";
switch (event->getType()) {
case GHOST_kEventUnknown:
std::cout << "GHOST_kEventUnknown"; handled = false;
@@ -125,19 +125,21 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
case GHOST_kEventDraggingDropDone:
{
GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData();
- std::cout << "GHOST_kEventDraggingDropDone, dragged object type : " << dragnDropData->dataType;
+ std::cout << "GHOST_kEventDraggingDropDone,";
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
switch (dragnDropData->dataType) {
case GHOST_kDragnDropTypeString:
- std::cout << " string received = " << (char*)dragnDropData->data;
+ std::cout << " type : GHOST_kDragnDropTypeString,";
+ std::cout << "\n String received = " << (char*)dragnDropData->data;
break;
case GHOST_kDragnDropTypeFilenames:
{
GHOST_TStringArray *strArray = (GHOST_TStringArray*)dragnDropData->data;
int i;
- std::cout << "\nReceived " << strArray->count << " filenames";
+ std::cout << " type : GHOST_kDragnDropTypeFilenames,";
+ std::cout << "\n Received " << strArray->count << " filename" << (strArray->count > 1 ? "s:" : ":");
for (i=0;i<strArray->count;i++)
- std::cout << " Filename #" << i << ": " << strArray->strings[i];
+ std::cout << "\n File[" << i << "] : " << strArray->strings[i];
}
break;
default:
@@ -192,7 +194,6 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
std::cout << "not found"; handled = false;
break;
}
- std::cout << "\n";
return handled;
}
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 97fae12a31f..8a93e9559ba 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -140,6 +140,24 @@ public:
*/
GHOST_TUns8 handleQuitRequest();
+ /**
+ * Handle Cocoa openFile event
+ * Display confirmation request panel if changes performed since last save
+ */
+ bool handleOpenDocumentRequest(void *filepathStr);
+
+ /**
+ * 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);
+
/***************************************************************************************
** Cursor management functionality
***************************************************************************************/
@@ -200,18 +218,12 @@ public:
*/
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
+ * Handles the Cocoa event telling the application has become active (again)
* @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);
+ GHOST_TSuccess handleApplicationBecomeActiveEvent();
+
protected:
/**
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index d8c46741ed0..cacacd368bb 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -389,7 +389,29 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
}
}
+#if defined(WITH_QUICKTIME) && !defined(USE_QTKIT)
+//Need to place this quicktime function in an ObjC file
+//It is used to avoid memory leak when raising the quicktime "compression settings" standard dialog
+extern "C" {
+ struct bContext;
+ struct wmOperator;
+ extern int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op);
+
+int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
+{
+ int result;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ result = fromcocoa_request_qtcodec_settings(C, op);
+
+ [pool drain];
+ return result;
+}
+};
+#endif
+
+
#pragma mark Cocoa objects
/**
@@ -403,6 +425,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
- (void)applicationWillTerminate:(NSNotification *)aNotification;
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification;
@end
@implementation CocoaAppDelegate : NSObject
@@ -413,9 +436,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;
+ return systemCocoa->handleOpenDocumentRequest(filename);
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
@@ -436,6 +457,11 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
/*G.afbreek = 0; //Let Cocoa perform the termination at the end
WM_exit(C);*/
}
+
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification
+{
+ systemCocoa->handleApplicationBecomeActiveEvent();
+}
@end
@@ -530,6 +556,9 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
[windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
+ menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
+ [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
+
menuItem = [[NSMenuItem alloc] init];
[menuItem setSubmenu:windowMenu];
@@ -706,13 +735,10 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
{
- unsigned int modifiers = [[NSApp currentEvent] modifierFlags];
- //Direct query to modifierFlags can be used in 10.6
-
- keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false);
- keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & NSAlternateKeyMask) ? true : false);
- keys.set(GHOST_kModifierKeyLeftShift, (modifiers & NSShiftKeyMask) ? true : false);
- keys.set(GHOST_kModifierKeyLeftControl, (modifiers & NSControlKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyCommand, (m_modifierMask & NSCommandKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false);
return GHOST_kSuccess;
}
@@ -740,8 +766,6 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
bool anyProcessed = false;
NSEvent *event;
- m_outsideLoopEventProcessed = false;
-
// SetMouseCoalescingEnabled(false, NULL);
//TODO : implement timer ??
@@ -838,9 +862,55 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
} while (event!= nil);
//} while (waitForEvent && !anyProcessed); Needed only for timer implementation
+ if (m_outsideLoopEventProcessed) {
+ m_outsideLoopEventProcessed = false;
+ return true;
+ }
+ return anyProcessed;
+}
+
+//Note: called from NSApplication delegate
+GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
+{
+ //Update the modifiers key mask, as its status may have changed when the application was not active
+ //(that is when update events are sent to another application)
+ unsigned int modifiers;
+ GHOST_IWindow* window = m_windowManager->getActiveWindow();
+
+#ifdef MAC_OS_X_VERSION_10_6
+ modifiers = [NSEvent modifierFlags];
+#else
+ //If build against an older SDK, check if running on 10.6 to use the correct function
+ if ([NSEvent respondsToSelector:@selector(modifierFlags)]) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+ modifiers = (unsigned int)[NSEvent modifierFlags];
+#else
+ modifiers = (NSUInteger)[NSEvent modifierFlags];
+#endif
+ }
+ else {
+ //TODO: need to find a better workaround for the missing cocoa "getModifierFlag" function in 10.4/10.5
+ modifiers = 0;
+ }
+#endif
- return anyProcessed || m_outsideLoopEventProcessed;
+ if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
+ }
+ if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
+ }
+ if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
+ }
+ if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
+ }
+
+ m_modifierMask = modifiers;
+
+ return GHOST_kSuccess;
}
//Note: called from NSWindow delegate
@@ -886,7 +956,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)) {
+ if (!validWindow(window) && (eventType != GHOST_kEventDraggingDropOnIcon)) {
return GHOST_kFailure;
}
switch(eventType)
@@ -1014,7 +1084,34 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
return GHOST_kExitCancel;
}
+bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
+{
+ NSString *filepath = (NSString*)filepathStr;
+ int confirmOpen = NSAlertAlternateReturn;
+ NSArray *windowsList;
+
+ //Check open windows if some changes are not saved
+ if (m_windowManager->getAnyModifiedState())
+ {
+ confirmOpen = NSRunAlertPanel([NSString stringWithFormat:@"Opening %@",[filepath lastPathComponent]],
+ @"Current document has not been saved.\nDo you really want to proceed?",
+ @"Cancel", @"Open", nil);
+ }
+ //Give back focus to the blender window
+ windowsList = [NSApp orderedWindows];
+ if ([windowsList count]) {
+ [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
+ }
+
+ if (confirmOpen == NSAlertAlternateReturn)
+ {
+ handleDraggingEvent(GHOST_kEventDraggingDropOnIcon,GHOST_kDragnDropTypeFilenames,NULL,0,0, [NSArray arrayWithObject:filepath]);
+ return YES;
+ }
+ else return NO;
+}
+
GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType)
{
NSEvent *event = (NSEvent *)eventPtr;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 8a17d455695..15914a5bf43 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -39,6 +39,7 @@
#endif
#include "GHOST_SystemWin32.h"
+#include "GHOST_EventDragnDrop.h"
// win64 doesn't define GWL_USERDATA
#ifdef WIN32
@@ -138,10 +139,15 @@ GHOST_SystemWin32::GHOST_SystemWin32()
m_displayManager = new GHOST_DisplayManagerWin32 ();
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
m_displayManager->initialize();
+
+ // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
+ OleInitialize(0);
}
GHOST_SystemWin32::~GHOST_SystemWin32()
{
+ // Shutdown COM
+ OleUninitialize();
}
@@ -187,7 +193,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow )
{
GHOST_Window* window = 0;
- window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual);
+ window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual);
if (window) {
if (window->getValid()) {
// Store the pointer to the window
@@ -248,10 +254,12 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
{
POINT point;
- ::GetCursorPos(&point);
- x = point.x;
- y = point.y;
- return GHOST_kSuccess;
+ if(::GetCursorPos(&point)){
+ x = point.x;
+ y = point.y;
+ return GHOST_kSuccess;
+ }
+ return GHOST_kFailure;
}
@@ -499,11 +507,56 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
}
-GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window)
+GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
{
- GHOST_TInt32 x, y;
- getSystem()->getCursorPosition(x, y);
- return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y);
+ GHOST_TInt32 x_screen, y_screen;
+ GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
+ GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
+
+ system->getCursorPosition(x_screen, y_screen);
+
+ if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
+ {
+ GHOST_TInt32 x_new= x_screen;
+ GHOST_TInt32 y_new= y_screen;
+ GHOST_TInt32 x_accum, y_accum;
+ GHOST_Rect bounds;
+
+ /* fallback to window bounds */
+ if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
+ window->getClientBounds(bounds);
+ }
+
+ /* could also clamp to screen bounds
+ * wrap with a window outside the view will fail atm */
+
+ bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
+
+ window->getCursorGrabAccum(x_accum, y_accum);
+ if(x_new != x_screen|| y_new != y_screen) {
+ /* when wrapping we don't need to add an event because the
+ * setCursorPosition call will cause a new event after */
+ system->setCursorPosition(x_new, y_new); /* wrap */
+ window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
+ }else{
+ return new GHOST_EventCursor(system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ x_screen + x_accum,
+ y_screen + y_accum
+ );
+ }
+
+ }
+ else {
+ return new GHOST_EventCursor(system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ x_screen,
+ y_screen
+ );
+ }
+ return NULL;
}
@@ -549,6 +602,26 @@ GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
}
+GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
+ GHOST_TDragnDropTypes draggedObjectType,
+ GHOST_IWindow* window,
+ int mouseX, int mouseY,
+ void* data)
+{
+ GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
+ return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
+ eventType,
+ draggedObjectType,
+ window,mouseX,mouseY,data)
+ );
+}
+
+void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
+{
+ minmax->ptMinTrackSize.x=320;
+ minmax->ptMinTrackSize.y=240;
+}
+
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@@ -793,6 +866,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processWindowEvent(GHOST_kEventWindowUpdate, window);
::ValidateRect(hwnd, NULL);
break;
+ case WM_GETMINMAXINFO:
+ /* The WM_GETMINMAXINFO message is sent to a window when the size or
+ * position of the window is about to change. An application can use
+ * this message to override the window's default maximized size and
+ * position, or its default minimum or maximum tracking size.
+ */
+ processMinMaxInfo((MINMAXINFO *) lParam);
+ /* Let DefWindowProc handle it. */
+ break;
case WM_SIZE:
/* The WM_SIZE message is sent to a window after its size has changed.
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 6a12975a3dd..517f7ddbeea 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -51,6 +51,7 @@ class GHOST_EventCursor;
class GHOST_EventKey;
class GHOST_EventWheel;
class GHOST_EventWindow;
+class GHOST_EventDragnDrop;
/**
* WIN32 Implementation of GHOST_System class.
@@ -181,6 +182,18 @@ public:
* @return No return
*/
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+
+ /**
+ * Creates a drag'n'drop event and pushes it immediately onto the event queue.
+ * Called by GHOST_DropTargetWin32 class.
+ * @param eventType The type of drag'n'drop event
+ * @param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap)
+ * @param mouseX x mouse coordinate (in window coordinates)
+ * @param mouseY y mouse coordinate
+ * @param window The window on which the event occured
+ * @return Indication whether the event was handled.
+ */
+ static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType,GHOST_IWindow* window, int mouseX, int mouseY, void* data);
protected:
/**
@@ -228,7 +241,7 @@ protected:
* @param window The window receiving the event (the active window).
* @return The event created.
*/
- static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window);
+ static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow);
/**
* Creates a mouse wheel event.
@@ -255,7 +268,12 @@ protected:
* @return The event created.
*/
static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
-
+ /**
+ * Handles minimum window size.
+ * @param minmax The MINMAXINFO structure.
+ */
+ static void processMinMaxInfo(MINMAXINFO * minmax);
+
/**
* Returns the local state of the modifier keys (from the message queue).
* @param keys The state of the keys.
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index ff4a5956a12..ad8647d2246 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -23,6 +23,9 @@
*
* Contributor(s): none yet.
*
+ * Part of this code has been taken from Qt, under LGPL license
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
* ***** END GPL LICENSE BLOCK *****
*/
@@ -63,8 +66,10 @@
#include <sys/time.h>
#include <unistd.h>
+#include <iostream>
#include <vector>
#include <stdio.h> // for fprintf only
+#include <cstdlib> // for exit
typedef struct NDOFPlatformInfo {
Display *display;
@@ -93,7 +98,10 @@ GHOST_SystemX11(
{
m_display = XOpenDisplay(NULL);
- if (!m_display) return;
+ if (!m_display) {
+ std::cerr << "Unable to open a display" << std::endl;
+ abort(); //was return before, but this would just mean it will crash later
+ }
#ifdef __sgi
m_delete_window_atom
@@ -126,6 +134,8 @@ GHOST_SystemX11(
m_xclip_out= XInternAtom(m_display, "XCLIP_OUT", False);
m_incr= XInternAtom(m_display, "INCR", False);
m_utf8_string= XInternAtom(m_display, "UTF8_STRING", False);
+ m_last_warp = 0;
+
// compute the initial time
timeval tv;
@@ -310,6 +320,61 @@ static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep) {
}
}
+/* This function borrowed from Qt's X11 support
+ * qclipboard_x11.cpp
+ * */
+struct init_timestamp_data
+{
+ Time timestamp;
+};
+
+static Bool init_timestamp_scanner(Display*, XEvent *event, XPointer arg)
+{
+ init_timestamp_data *data =
+ reinterpret_cast<init_timestamp_data*>(arg);
+ switch(event->type)
+ {
+ case ButtonPress:
+ case ButtonRelease:
+ data->timestamp = event->xbutton.time;
+ break;
+ case MotionNotify:
+ data->timestamp = event->xmotion.time;
+ break;
+ case KeyPress:
+ case KeyRelease:
+ data->timestamp = event->xkey.time;
+ break;
+ case PropertyNotify:
+ data->timestamp = event->xproperty.time;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ data->timestamp = event->xcrossing.time;
+ break;
+ case SelectionClear:
+ data->timestamp = event->xselectionclear.time;
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+Time
+GHOST_SystemX11::
+lastEventTime(Time default_time) {
+ init_timestamp_data data;
+ data.timestamp = default_time;
+ XEvent ev;
+ XCheckIfEvent(m_display, &ev, &init_timestamp_scanner, (XPointer)&data);
+
+ return data.timestamp;
+}
+
+
+
bool
GHOST_SystemX11::
processEvents(
@@ -405,10 +470,15 @@ GHOST_SystemX11::processEvent(XEvent *xe)
window->getCursorGrabAccum(x_accum, y_accum);
if(x_new != xme.x_root || y_new != xme.y_root) {
- /* when wrapping we don't need to add an event because the
- * setCursorPosition call will cause a new event after */
- setCursorPosition(x_new, y_new); /* wrap */
- window->setCursorGrabAccum(x_accum + (xme.x_root - x_new), y_accum + (xme.y_root - y_new));
+ if (xme.time > m_last_warp) {
+ /* when wrapping we don't need to add an event because the
+ * setCursorPosition call will cause a new event after */
+ setCursorPosition(x_new, y_new); /* wrap */
+ window->setCursorGrabAccum(x_accum + (xme.x_root - x_new), y_accum + (xme.y_root - y_new));
+ m_last_warp = lastEventTime(xme.time);
+ } else {
+ setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
+ }
}
else {
g_event = new
@@ -907,7 +977,7 @@ setCursorPosition(
int rely = y-cy;
XWarpPointer(m_display,None,None,0,0,0,0,relx,rely);
- XFlush(m_display);
+ XSync(m_display, 0); /* Sync to process all requests */
return GHOST_kSuccess;
}
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 782f08f6737..d76c3991beb 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -266,6 +266,10 @@ private :
/// A vector of keyboard key masks
char m_keyboard_vector[32];
+ /* to prevent multiple warp, we store the time of the last warp event
+ * and stop accumulating all events generated before that */
+ Time m_last_warp;
+
/**
* Return the ghost window associated with the
* X11 window xwind
@@ -281,6 +285,11 @@ private :
XEvent *xe
);
+ Time
+ lastEventTime(
+ Time default_time
+ );
+
bool
generateWindowExposeEvents(
);
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index e89e0274276..14a255e2e5e 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -109,6 +109,8 @@ GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rec
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1;
else if (bounds) {
m_cursorGrabBounds= *bounds;
+ } else { /* if bounds not defined, use window */
+ getClientBounds(m_cursorGrabBounds);
}
m_cursorGrab = mode;
return GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 909ba803a9d..3f52ea535bd 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -230,6 +230,32 @@ extern "C" {
- (void)keyDown:(NSEvent *)theEvent
{}
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+//Cmd+key are handled differently before 10.5
+- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
+{
+ NSString *chars = [theEvent charactersIgnoringModifiers];
+
+ if ([chars length] <1)
+ return NO;
+
+ //Let cocoa handle menu shortcuts
+ switch ([chars characterAtIndex:0]) {
+ case 'q':
+ case 'w':
+ case 'h':
+ case 'm':
+ case '<':
+ case '>':
+ case '~':
+ case '`':
+ return NO;
+ default:
+ return YES;
+ }
+}
+#endif
+
- (BOOL)isOpaque
{
return YES;
@@ -858,15 +884,18 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp
if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
#ifdef WAIT_FOR_VSYNC
+ {
+ GLint swapInt = 1;
/* wait for vsync, to avoid tearing artifacts */
- [tmpOpenGLContext setValues:1 forParameter:NSOpenGLCPSwapInterval];
+ [tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+ }
#endif
- [m_openGLView setOpenGLContext:tmpOpenGLContext];
- [tmpOpenGLContext setView:m_openGLView];
-
- m_openGLContext = tmpOpenGLContext;
+ [m_openGLView setOpenGLContext:tmpOpenGLContext];
+ [tmpOpenGLContext setView:m_openGLView];
+
+ m_openGLContext = tmpOpenGLContext;
break;
-
+
case GHOST_kDrawingContextTypeNone:
success = GHOST_kSuccess;
break;
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index e2caf31edee..ea14f1dfc1b 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -40,6 +40,8 @@
#include <string.h>
#include "GHOST_WindowWin32.h"
+#include "GHOST_SystemWin32.h"
+#include "GHOST_DropTargetWin32.h"
#include <GL/gl.h>
#include <math.h>
@@ -95,6 +97,7 @@ static PIXELFORMATDESCRIPTOR sPreferredFormat = {
};
GHOST_WindowWin32::GHOST_WindowWin32(
+ GHOST_SystemWin32 * system,
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -106,6 +109,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
:
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone,
stereoVisual),
+ m_system(system),
m_hDC(0),
m_hGlRc(0),
m_hasMouseCaptured(false),
@@ -167,6 +171,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(
0); // pointer to window-creation data
}
if (m_hWnd) {
+ // Register this window as a droptarget. Requires m_hWnd to be valid.
+ // Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32.
+ m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
// Store a pointer to this class in the window structure
::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR)this);
@@ -275,6 +282,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_hDC = 0;
}
if (m_hWnd) {
+ m_dropTarget->Release(); // frees itself.
::DestroyWindow(m_hWnd);
m_hWnd = 0;
}
@@ -285,6 +293,10 @@ bool GHOST_WindowWin32::getValid() const
return m_hWnd != 0;
}
+HWND GHOST_WindowWin32::getHWND() const
+{
+ return m_hWnd;
+}
void GHOST_WindowWin32::setTitle(const STR_String& title)
{
@@ -663,6 +675,41 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible)
return GHOST_kSuccess;
}
+GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
+{
+ if(mode != GHOST_kGrabDisable) {
+ if(mode != GHOST_kGrabNormal) {
+ m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
+ setCursorGrabAccum(0, 0);
+
+ if(mode == GHOST_kGrabHide)
+ setWindowCursorVisibility(false);
+ }
+ registerMouseClickEvent(true);
+ }
+ else {
+ if (m_cursorGrab==GHOST_kGrabHide) {
+ m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
+ setWindowCursorVisibility(true);
+ }
+ if(m_cursorGrab != GHOST_kGrabNormal) {
+ /* use to generate a mouse move event, otherwise the last event
+ * blender gets can be outside the screen causing menus not to show
+ * properly unless the user moves the mouse */
+ GHOST_TInt32 pos[2];
+ m_system->getCursorPosition(pos[0], pos[1]);
+ m_system->setCursorPosition(pos[0], pos[1]);
+ }
+
+ /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
+ setCursorGrabAccum(0, 0);
+ m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
+ registerMouseClickEvent(false);
+ }
+
+ return GHOST_kSuccess;
+}
+
GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape)
{
if (m_customCursor) {
@@ -676,6 +723,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur
return GHOST_kSuccess;
}
+
void GHOST_WindowWin32::processWin32TabletInitEvent()
{
if (m_wintab) {
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 8b461802fa4..07a31911a5e 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -47,6 +47,9 @@
#define PACKETMODE PK_BUTTONS
#include <pktdef.h>
+class GHOST_SystemWin32;
+class GHOST_DropTargetWin32;
+
// typedefs for WinTab functions to allow dynamic loading
typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID );
typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL);
@@ -74,6 +77,7 @@ public:
* @param stereoVisual Stereo visual for quad buffered stereo.
*/
GHOST_WindowWin32(
+ GHOST_SystemWin32 * system,
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
@@ -97,6 +101,12 @@ public:
virtual bool getValid() const;
/**
+ * Access to the handle of the window.
+ * @return The handle of the window.
+ */
+ virtual HWND getHWND() const;
+
+ /**
* Sets the title displayed in the title bar.
* @param title The title to display in the title bar.
*/
@@ -251,6 +261,13 @@ protected:
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
+ * Sets the cursor grab on the window using native window system calls.
+ * Using registerMouseClickEvent.
+ * @param mode GHOST_TGrabCursorMode.
+ */
+ virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
+
+ /**
* Sets the cursor shape on the window using
* native window system calls.
*/
@@ -273,6 +290,10 @@ protected:
int bg_color
);
+ /** Pointer to system */
+ GHOST_SystemWin32 * m_system;
+ /** Pointer to COM IDropTarget implementor */
+ GHOST_DropTargetWin32 * m_dropTarget;
/** Window handle. */
HWND m_hWnd;
/** Device context handle. */
diff --git a/intern/ghost/intern/Makefile b/intern/ghost/intern/Makefile
index 5b95bbb3b68..a6392662c30 100644
--- a/intern/ghost/intern/Makefile
+++ b/intern/ghost/intern/Makefile
@@ -41,7 +41,15 @@ CCSRCS += GHOST_CallbackEventConsumer.cpp
CCSRCS += GHOST_NDOFManager.cpp
ifeq ($(OS),$(findstring $(OS), "darwin"))
- CCSRCS += $(wildcard *Carbon.cpp)
+ ifeq ($(WITH_COCOA), true)
+ OCSRCS += $(wildcard *Cocoa.mm)
+ CPPFLAGS += -DGHOST_COCOA
+ ifeq ($(WITH_QUICKTIME), true)
+ CPPFLAGS += -DWITH_QUICKTIME
+ endif
+ else
+ CCSRCS += $(wildcard *Carbon.cpp)
+ endif
endif
ifeq ($(OS),$(findstring $(OS), "windows"))
diff --git a/intern/ghost/make/msvc_9_0/ghost.vcproj b/intern/ghost/make/msvc_9_0/ghost.vcproj
index 9569fba5a0e..4e4d9bb6598 100644
--- a/intern/ghost/make/msvc_9_0/ghost.vcproj
+++ b/intern/ghost/make/msvc_9_0/ghost.vcproj
@@ -353,6 +353,10 @@
>
</File>
<File
+ RelativePath="..\..\intern\GHOST_DropTargetWin32.h"
+ >
+ </File>
+ <File
RelativePath="..\..\intern\GHOST_Event.h"
>
</File>
@@ -490,6 +494,10 @@
>
</File>
<File
+ RelativePath="..\..\intern\GHOST_DropTargetWin32.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\intern\GHOST_EventManager.cpp"
>
</File>