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:
-rw-r--r--config/win32-mingw-config.py2
-rw-r--r--intern/ghost/SConscript6
-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_SystemWin32.cpp100
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h22
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp48
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h21
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c7
-rwxr-xr-xtools/btools.py6
12 files changed, 788 insertions, 25 deletions
diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py
index 709261ec1ca..0f07ca4c2ee 100644
--- a/config/win32-mingw-config.py
+++ b/config/win32-mingw-config.py
@@ -145,7 +145,7 @@ C_WARN = [ '-Wno-char-subscripts', '-Wdeclaration-after-statement' ]
CC_WARN = [ '-Wall' ]
-LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++']
+LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid']
BF_DEBUG = False
BF_DEBUG_CCFLAGS= ['-g']
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index 09da6f94ddc..84ca97fdb93 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -37,8 +37,12 @@ else:
print "Unknown window system specified."
Exit()
+defs=['_USE_MATH_DEFINES']
+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] )
+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..d75770383fb
--- /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..6ea6ed85a93
--- /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_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_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/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 6145871f9d4..7decf7b2ed2 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -172,12 +172,13 @@ void WM_cursor_grab(wmWindow *win, int wrap, int hide, int *bounds)
if(hide) mode = GHOST_kGrabHide;
else if(wrap) mode = GHOST_kGrabWrap;
-
if ((G.f & G_DEBUG) == 0) {
if (win && win->ghostwin) {
const GHOST_TabletData *tabletdata= GHOST_GetTabletData(win->ghostwin);
-
- if ((tabletdata) && (tabletdata->Active == GHOST_kTabletModeNone))
+ // Note: There is no tabletdata on Windows if no tablet device is connected.
+ if (!tabletdata)
+ GHOST_SetCursorGrab(win->ghostwin, mode, bounds);
+ else if (tabletdata->Active == GHOST_kTabletModeNone)
GHOST_SetCursorGrab(win->ghostwin, mode, bounds);
}
}
diff --git a/tools/btools.py b/tools/btools.py
index e34ee05fbe7..f010a82fd6a 100755
--- a/tools/btools.py
+++ b/tools/btools.py
@@ -75,6 +75,7 @@ def validate_arguments(args, bc):
'BF_MSVS',
'WITH_BF_FHS',
'BF_VERSION',
+ 'BF_GHOST_DEBUG'
]
# Have options here that scons expects to be lists
@@ -418,8 +419,9 @@ def read_opts(cfg, args):
(BoolVariable('WITH_BF_FHS', 'Use the Unix "Filesystem Hierarchy Standard" rather then a redistributable directory layout', False)),
('BF_VERSION', 'The root path for Unix (non-apple)', '2.5'),
- (BoolVariable('BF_UNIT_TEST', 'Build with unit test support.', False))
-
+ (BoolVariable('BF_UNIT_TEST', 'Build with unit test support.', False)),
+
+ (BoolVariable('BF_GHOST_DEBUG', 'Make GHOST print events and info to stdout. (very verbose)', False))
) # end of opts.AddOptions()
return localopts