forked from bartvdbraak/blender
Apply patch [#20145] Ghost Win32 roundup patch: Minimum Window Size, Continuous Grab and Drag And Drop
This nice patch by Matt D. (matd in #blendercoders) adds three nice features that can be seen already in the other supported OSes: * minimum window size: to prevent some bugs with the window manager of Blender, system windows cannot be resized smaller than the minimum size. * Continuous Grab is finally in Windows! Default settings since alpha 0 already have the feature enabled by default, so grab a new build and enjoy :) * GHOST support for drag and drop added. This prepares Blender for drag and drop from OS -> Blender. Currently not very useful, since wm needs to be readied for that. But it does work (do BF_GHOST_DEBUG=1 build and drag a file onto a Blender window). Thanks Matt D.!
This commit is contained in:
parent
d86a27f7b6
commit
5a3791ab5b
@ -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']
|
||||
|
@ -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] )
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
426
intern/ghost/intern/GHOST_DropTargetWin32.cpp
Normal file
426
intern/ghost/intern/GHOST_DropTargetWin32.cpp
Normal file
@ -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
|
||||
|
155
intern/ghost/intern/GHOST_DropTargetWin32.h
Normal file
155
intern/ghost/intern/GHOST_DropTargetWin32.h
Normal file
@ -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_
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
@ -96,6 +100,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.
|
||||
@ -250,6 +260,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. */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user