mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 07:04:36 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
202
Engine/source/windowManager/win32/win32CursorController.cpp
Normal file
202
Engine/source/windowManager/win32/win32CursorController.cpp
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include "core/strings/unicode.h"
|
||||
#include "math/mMath.h"
|
||||
#include "windowManager/win32/win32Window.h"
|
||||
#include "windowManager/win32/win32WindowMgr.h"
|
||||
#include "windowManager/win32/winDispatch.h"
|
||||
#include "windowManager/win32/win32CursorController.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include <zmouse.h>
|
||||
|
||||
static struct { U32 id; LPTSTR resourceID; } sgCursorShapeMap[]=
|
||||
{
|
||||
{ PlatformCursorController::curArrow, IDC_ARROW },
|
||||
{ PlatformCursorController::curWait, IDC_WAIT },
|
||||
{ PlatformCursorController::curPlus, IDC_CROSS },
|
||||
{ PlatformCursorController::curResizeVert, IDC_SIZEWE },
|
||||
{ PlatformCursorController::curResizeHorz, IDC_SIZENS },
|
||||
{ PlatformCursorController::curResizeAll, IDC_SIZEALL },
|
||||
{ PlatformCursorController::curIBeam, IDC_IBEAM },
|
||||
{ PlatformCursorController::curResizeNESW, IDC_SIZENESW },
|
||||
{ PlatformCursorController::curResizeNWSE, IDC_SIZENWSE },
|
||||
{ PlatformCursorController::curHand, IDC_HAND },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
//static const EnumTable::Enums curManagerShapesEnums[] =
|
||||
//{
|
||||
// { Win32CursorController::curArrow, "Arrow" },
|
||||
// { Win32CursorController::curWait, "Wait" },
|
||||
// { Win32CursorController::curPlus, "Plus" },
|
||||
// { Win32CursorController::curResizeVert, "ResizeVert" },
|
||||
// { Win32CursorController::curResizeHorz, "ResizeHorz" },
|
||||
// { Win32CursorController::curResizeAll, "ResizeAll" },
|
||||
// { Win32CursorController::curIBeam, "ibeam" },
|
||||
// { Win32CursorController::curResizeNESW, "ResizeNESW" },
|
||||
// { Win32CursorController::curResizeNWSE, "ResizeNWSE" },
|
||||
//};
|
||||
//
|
||||
//static const EnumTable gCurManagerShapesTable(8, &curManagerShapesEnums[0]);
|
||||
|
||||
// CodeReview I've duplicated this 'cache' trick for system settings
|
||||
// because they're unlikely to change and calling into the OS for values
|
||||
// repeatedly is just silly to begin with. [6/29/2007 justind]
|
||||
U32 Win32CursorController::getDoubleClickTime()
|
||||
{
|
||||
static S32 sPlatWinDoubleClicktime = -1;
|
||||
if( sPlatWinDoubleClicktime == -1 )
|
||||
sPlatWinDoubleClicktime = GetDoubleClickTime();
|
||||
return sPlatWinDoubleClicktime;
|
||||
}
|
||||
S32 Win32CursorController::getDoubleClickWidth()
|
||||
{
|
||||
static S32 sPlatWinDoubleClickwidth = -1;
|
||||
if( sPlatWinDoubleClickwidth == -1 )
|
||||
sPlatWinDoubleClickwidth = GetSystemMetrics(SM_CXDOUBLECLK);
|
||||
return sPlatWinDoubleClickwidth;
|
||||
}
|
||||
S32 Win32CursorController::getDoubleClickHeight()
|
||||
{
|
||||
static S32 sPlatWinDoubleClickheight = -1;
|
||||
if( sPlatWinDoubleClickheight == -1 )
|
||||
sPlatWinDoubleClickheight = GetSystemMetrics(SM_CYDOUBLECLK);
|
||||
return sPlatWinDoubleClickheight;
|
||||
}
|
||||
|
||||
void Win32CursorController::setCursorPosition( S32 x, S32 y )
|
||||
{
|
||||
::SetCursorPos(x, y);
|
||||
}
|
||||
|
||||
void Win32CursorController::getCursorPosition( Point2I &point )
|
||||
{
|
||||
POINT rPoint;
|
||||
::GetCursorPos( &rPoint );
|
||||
|
||||
// Return
|
||||
point.x = rPoint.x;
|
||||
point.y = rPoint.y;
|
||||
}
|
||||
|
||||
void Win32CursorController::setCursorVisible( bool visible )
|
||||
{
|
||||
if( visible )
|
||||
ShowCursor( true );
|
||||
else
|
||||
while( ShowCursor(false) > 0 );
|
||||
}
|
||||
|
||||
bool Win32CursorController::isCursorVisible()
|
||||
{
|
||||
CURSORINFO rCursorInfo;
|
||||
rCursorInfo.cbSize = sizeof(CURSORINFO);
|
||||
if( !GetCursorInfo( &rCursorInfo ) )
|
||||
{
|
||||
//DWORD error = GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
// rCursorInfo.flags values :
|
||||
// 0 == Cursor is hidden
|
||||
// CURSOR_SHOWING == cursor is visible
|
||||
return (bool)(rCursorInfo.flags == CURSOR_SHOWING);
|
||||
}
|
||||
|
||||
void Win32CursorController::setCursorShape(U32 cursorID)
|
||||
{
|
||||
LPTSTR resourceID = NULL;
|
||||
|
||||
for(S32 i = 0;sgCursorShapeMap[i].resourceID != NULL;++i)
|
||||
{
|
||||
if(cursorID == sgCursorShapeMap[i].id)
|
||||
{
|
||||
resourceID = sgCursorShapeMap[i].resourceID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(resourceID == NULL)
|
||||
return;
|
||||
|
||||
HCURSOR cur = LoadCursor(NULL, resourceID);
|
||||
if(cur)
|
||||
SetCursor(cur);
|
||||
}
|
||||
|
||||
static HCURSOR gCursorShape = NULL;
|
||||
void Win32CursorController::setCursorShape( const UTF8 *fileName, bool reload )
|
||||
{
|
||||
#ifdef UNICODE
|
||||
const UTF16 *lFileName = convertUTF8toUTF16( fileName );
|
||||
#else
|
||||
const UTF8 *lFileName = fileName;
|
||||
#endif
|
||||
|
||||
if ( !gCursorShape || reload )
|
||||
gCursorShape = LoadCursorFromFile( lFileName );
|
||||
|
||||
if ( gCursorShape )
|
||||
SetCursor( gCursorShape );
|
||||
}
|
||||
|
||||
// Console function to set the current cursor shape given the cursor shape
|
||||
// name as defined in the enum above.
|
||||
//ConsoleFunction( inputPushCursor, void, 2, 2, "inputPushCursor(cursor shape name)" )
|
||||
//{
|
||||
// S32 val = 0;
|
||||
//
|
||||
// // Find the cursor shape
|
||||
// if(argc == 2)
|
||||
// {
|
||||
// for (S32 i = 0; i < gCurManagerShapesTable.size; i++)
|
||||
// {
|
||||
// if (! dStricmp(argv[1], gCurManagerShapesTable.table[i].label))
|
||||
// {
|
||||
// val = gCurManagerShapesTable.table[i].index;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Now set it
|
||||
// Win32CursorController* cm = Input::getCursorManager();
|
||||
// if(cm)
|
||||
// {
|
||||
// cm->pushCursor(val);
|
||||
// }
|
||||
//}
|
||||
//// Function to pop the current cursor shape
|
||||
//ConsoleFunction( inputPopCursor, void, 1, 1, "inputPopCursor()" )
|
||||
//{
|
||||
// argc;
|
||||
// argv;
|
||||
//
|
||||
// Win32CursorController* cm = Input::getCursorManager();
|
||||
// if(cm)
|
||||
// {
|
||||
// cm->popCursor();
|
||||
// }
|
||||
//}
|
||||
52
Engine/source/windowManager/win32/win32CursorController.h
Normal file
52
Engine/source/windowManager/win32/win32CursorController.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WIN32_CURSORCONTROLLER_H_
|
||||
#define _WIN32_CURSORCONTROLLER_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include "windowManager/platformCursorController.h"
|
||||
|
||||
class Win32CursorController : public PlatformCursorController
|
||||
{
|
||||
public:
|
||||
Win32CursorController( PlatformWindow *owner ) :
|
||||
PlatformCursorController( owner )
|
||||
{
|
||||
pushCursor( PlatformCursorController::curArrow );
|
||||
};
|
||||
|
||||
virtual void setCursorPosition( S32 x, S32 y );
|
||||
virtual void getCursorPosition( Point2I &point );
|
||||
virtual void setCursorVisible( bool visible );
|
||||
virtual bool isCursorVisible();
|
||||
|
||||
void setCursorShape( U32 cursorID );
|
||||
void setCursorShape( const UTF8 *fileName, bool reload );
|
||||
|
||||
U32 getDoubleClickTime();
|
||||
S32 getDoubleClickWidth();
|
||||
S32 getDoubleClickHeight();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
142
Engine/source/windowManager/win32/win32SplashScreen.cpp
Normal file
142
Engine/source/windowManager/win32/win32SplashScreen.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#include <windows.h>
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "console/console.h"
|
||||
|
||||
// from Torque.rc
|
||||
#define IDI_ICON1 103
|
||||
|
||||
// Window Class name
|
||||
static const TCHAR* c_szSplashClass = L"Torque3DSplashWindow";
|
||||
|
||||
static HWND gSplashWndOwner = NULL;
|
||||
static HWND gSplashWnd = NULL;
|
||||
static HBITMAP gSplashImage = NULL;
|
||||
|
||||
// Registers a window class for the splash and splash owner windows.
|
||||
static void RegisterWindowClass(HINSTANCE hinst)
|
||||
|
||||
{
|
||||
WNDCLASS wc = { 0 };
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.hInstance = hinst;
|
||||
wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON1));
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.lpszClassName = c_szSplashClass;
|
||||
RegisterClass(&wc);
|
||||
}
|
||||
|
||||
static void UnregisterSplashWindowClass(HINSTANCE hinst)
|
||||
{
|
||||
WNDCLASSEX classInfo;
|
||||
if (GetClassInfoEx(hinst,c_szSplashClass,&classInfo))
|
||||
UnregisterClass(c_szSplashClass,hinst);
|
||||
}
|
||||
|
||||
// Creates the splash owner window and the splash window.
|
||||
static HWND CreateSplashWindow(HINSTANCE hinst)
|
||||
|
||||
{
|
||||
RegisterWindowClass(hinst);
|
||||
|
||||
gSplashWndOwner = CreateWindow(c_szSplashClass, NULL, WS_POPUP,
|
||||
0, 0, 0, 0, NULL, NULL, hinst, NULL);
|
||||
|
||||
return CreateWindowEx(WS_EX_LAYERED, c_szSplashClass, NULL, WS_POPUP | WS_VISIBLE,
|
||||
0, 0, 0, 0, gSplashWndOwner, NULL, hinst, NULL);
|
||||
}
|
||||
|
||||
// Calls UpdateLayeredWindow to set a bitmap (with alpha) as the content of the splash window.
|
||||
static void SetSplashImage(HWND hwndSplash, HBITMAP hbmpSplash)
|
||||
|
||||
{
|
||||
// get the size of the bitmap
|
||||
BITMAP bm;
|
||||
GetObject(hbmpSplash, sizeof(bm), &bm);
|
||||
SIZE sizeSplash = { bm.bmWidth, bm.bmHeight };
|
||||
|
||||
// get the primary monitor's info
|
||||
POINT ptZero = { 0 };
|
||||
HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
|
||||
MONITORINFO monitorinfo = { 0 };
|
||||
monitorinfo.cbSize = sizeof(monitorinfo);
|
||||
GetMonitorInfo(hmonPrimary, &monitorinfo);
|
||||
|
||||
// center the splash screen in the middle of the primary work area
|
||||
const RECT & rcWork = monitorinfo.rcWork;
|
||||
POINT ptOrigin;
|
||||
ptOrigin.x = rcWork.left + (rcWork.right - rcWork.left - sizeSplash.cx) / 2;
|
||||
ptOrigin.y = rcWork.top + (rcWork.bottom - rcWork.top - sizeSplash.cy) / 2;
|
||||
|
||||
// create a memory DC holding the splash bitmap
|
||||
HDC hdcScreen = GetDC(NULL);
|
||||
HDC hdcMem = CreateCompatibleDC(hdcScreen);
|
||||
HBITMAP hbmpOld = (HBITMAP) SelectObject(hdcMem, hbmpSplash);
|
||||
|
||||
// paint the window (in the right location) with the alpha-blended bitmap
|
||||
UpdateLayeredWindow(hwndSplash, hdcScreen, &ptOrigin, &sizeSplash,
|
||||
hdcMem, &ptZero, RGB(0, 0, 0), NULL, ULW_OPAQUE);
|
||||
|
||||
// delete temporary objects
|
||||
SelectObject(hdcMem, hbmpOld);
|
||||
DeleteDC(hdcMem);
|
||||
ReleaseDC(NULL, hdcScreen);
|
||||
}
|
||||
|
||||
void CloseSplashWindow(HINSTANCE hinst)
|
||||
{
|
||||
if (gSplashWndOwner)
|
||||
{
|
||||
//ShowWindow(gSplashWnd, 0);
|
||||
DestroyWindow(gSplashWndOwner);
|
||||
UnregisterSplashWindowClass(hinst);
|
||||
}
|
||||
|
||||
gSplashWndOwner = NULL;
|
||||
gSplashWnd = NULL;
|
||||
|
||||
}
|
||||
|
||||
bool Platform::displaySplashWindow()
|
||||
{
|
||||
|
||||
gSplashImage = (HBITMAP) ::LoadImage(0, L"art\\gui\\splash.bmp",
|
||||
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
|
||||
|
||||
if (!gSplashImage)
|
||||
return false;
|
||||
|
||||
gSplashWnd = CreateSplashWindow(GetModuleHandle(NULL));
|
||||
|
||||
if (!gSplashWnd)
|
||||
return false;
|
||||
|
||||
SetSplashImage(gSplashWnd, gSplashImage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
1162
Engine/source/windowManager/win32/win32Window.cpp
Normal file
1162
Engine/source/windowManager/win32/win32Window.cpp
Normal file
File diff suppressed because it is too large
Load diff
231
Engine/source/windowManager/win32/win32Window.h
Normal file
231
Engine/source/windowManager/win32/win32Window.h
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WINDOWMANAGER_WIN32_WIN32WINDOW_
|
||||
#define _WINDOWMANAGER_WIN32_WIN32WINDOW_
|
||||
|
||||
#include <windows.h>
|
||||
#include "windowManager/platformWindowMgr.h"
|
||||
#include "gfx/gfxTarget.h"
|
||||
#include "gfx/gfxStructs.h"
|
||||
#include "sim/actionMap.h"
|
||||
|
||||
class Win32WindowManager;
|
||||
|
||||
/// Implementation of a window on Win32.
|
||||
class Win32Window : public PlatformWindow
|
||||
{
|
||||
friend class Win32WindowManager;
|
||||
friend class GFXPCD3D9Device;
|
||||
friend class GFXPCD3D9WindowTarget;
|
||||
friend class GFXD3D8WindowTarget;
|
||||
|
||||
public:
|
||||
struct Accelerator
|
||||
{
|
||||
U32 mID;
|
||||
EventDescriptor mDescriptor;
|
||||
};
|
||||
typedef Vector<Accelerator> AcceleratorList;
|
||||
|
||||
private:
|
||||
typedef Vector<ACCEL> WinAccelList;
|
||||
|
||||
/// @name Active window list
|
||||
///
|
||||
/// Items used to track window instances.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Which manager created us?
|
||||
Win32WindowManager *mOwningManager;
|
||||
|
||||
/// Which window comes next in list?
|
||||
Win32Window *mNextWindow;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Window Information
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Our HWND - Win32 window handle.
|
||||
HWND mWindowHandle;
|
||||
|
||||
/// Our former Parent HWND
|
||||
HWND mOldParent;
|
||||
|
||||
/// The Win32 window style we want to use when windowed.
|
||||
DWORD mWindowedWindowStyle;
|
||||
|
||||
/// The GFX device that we're tied to.
|
||||
GFXDevice *mDevice;
|
||||
|
||||
/// Reference to the render target allocated on this window.
|
||||
GFXWindowTargetRef mTarget;
|
||||
|
||||
/// Our current size/resolution/fullscreen status.
|
||||
GFXVideoMode mVideoMode;
|
||||
|
||||
/// Our position on the desktop.
|
||||
Point2I mPosition;
|
||||
|
||||
/// Windows HACCEL for accelerators
|
||||
HACCEL mAccelHandle;
|
||||
|
||||
/// Keyboard accelerators for menus
|
||||
WinAccelList mWinAccelList;
|
||||
|
||||
/// Is the mouse locked to this window?
|
||||
bool mMouseLocked;
|
||||
|
||||
/// The position the cursor was at when a mouse lock occured
|
||||
Point2I mMouseLockPosition;
|
||||
|
||||
/// Determines whether this window should lock the mouse when it has an opportunity
|
||||
bool mShouldLockMouse;
|
||||
|
||||
/// When set, we don't trigger device resets due to sizing events.
|
||||
bool mSuppressReset;
|
||||
|
||||
/// Menu associated with this window. This is a passive property of the window and is not required to be used at all.
|
||||
HMENU mMenuHandle;
|
||||
|
||||
/// Do we have a fullscreen window style set?
|
||||
bool mFullscreen;
|
||||
|
||||
/// @}
|
||||
|
||||
/// Helper to allocate our Win32 window class.
|
||||
void _registerWindowClass();
|
||||
void _unregisterWindowClass();
|
||||
|
||||
/// Windows message handler callback.
|
||||
static LRESULT PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/// Add an accelerator to the list of accelerators for this window. Intended for use by addAccelerators()
|
||||
void addAccelerator(Accelerator &accel);
|
||||
/// Remove an accelerator from the list of accelerators for this window. Intended for use by removeAccelerators()
|
||||
void removeAccelerator(Accelerator &accel);
|
||||
|
||||
public:
|
||||
Win32Window();
|
||||
~Win32Window();
|
||||
|
||||
/// Return the HWND (win32 window handle) for this window.
|
||||
HWND &getHWND()
|
||||
{
|
||||
return mWindowHandle;
|
||||
}
|
||||
|
||||
HMENU &getMenuHandle()
|
||||
{
|
||||
return mMenuHandle;
|
||||
}
|
||||
|
||||
void setMenuHandle( HMENU menuHandle )
|
||||
{
|
||||
mMenuHandle = menuHandle;
|
||||
if(!mFullscreen)
|
||||
SetMenu(mWindowHandle, mMenuHandle);
|
||||
}
|
||||
|
||||
/// Add a list of accelerators to this window
|
||||
void addAccelerators(AcceleratorList &list);
|
||||
/// Remove a list of accelerators from this window
|
||||
void removeAccelerators(AcceleratorList &list);
|
||||
|
||||
/// Returns true if @p info matches an accelerator
|
||||
bool isAccelerator(const InputEventInfo &info);
|
||||
|
||||
/// Allow windows to translate messages. Used for accelerators.
|
||||
bool translateMessage(MSG &msg);
|
||||
|
||||
virtual GFXDevice *getGFXDevice();
|
||||
virtual GFXWindowTarget *getGFXTarget();
|
||||
|
||||
virtual void setVideoMode(const GFXVideoMode &mode);
|
||||
virtual const GFXVideoMode &getVideoMode();
|
||||
virtual bool clearFullscreen();
|
||||
virtual bool isFullscreen();
|
||||
virtual void _setFullscreen(const bool fullscreen);
|
||||
|
||||
virtual bool setCaption(const char *cap);
|
||||
virtual const char *getCaption();
|
||||
|
||||
// Window Client Area Extent
|
||||
virtual void setClientExtent( const Point2I newExtent );
|
||||
virtual const Point2I getClientExtent();
|
||||
|
||||
// Window Bounds
|
||||
virtual void setBounds(const RectI &newBounds);
|
||||
virtual const RectI getBounds() const;
|
||||
|
||||
// Window Position
|
||||
virtual void setPosition( const Point2I newPosition );
|
||||
virtual const Point2I getPosition();
|
||||
virtual void centerWindow();
|
||||
virtual bool setSize(const Point2I &newSize);
|
||||
|
||||
// Coordinate space conversion.
|
||||
virtual Point2I clientToScreen( const Point2I& pos );
|
||||
virtual Point2I screenToClient( const Point2I& pos );
|
||||
|
||||
virtual bool isOpen();
|
||||
virtual bool isVisible();
|
||||
virtual bool isFocused();
|
||||
virtual bool isMinimized();
|
||||
virtual bool isMaximized();
|
||||
|
||||
virtual void minimize();
|
||||
virtual void maximize();
|
||||
virtual void hide();
|
||||
virtual void show();
|
||||
virtual void close();
|
||||
virtual void restore();
|
||||
virtual void setFocus();
|
||||
|
||||
virtual void setMouseLocked(bool enable);
|
||||
virtual bool isMouseLocked() const { return mMouseLocked; };
|
||||
virtual bool shouldLockMouse() const { return mShouldLockMouse; };
|
||||
|
||||
virtual WindowId getWindowId();
|
||||
|
||||
virtual PlatformWindow * getNextWindow() const
|
||||
{
|
||||
return mNextWindow;
|
||||
}
|
||||
|
||||
/// Provide a simple GDI-based render for when the game is not rendering.
|
||||
virtual void defaultRender();
|
||||
|
||||
/// Return the class name for the windows we create with this class.
|
||||
static const UTF16 *getWindowClassName();
|
||||
|
||||
/// Return the class name for the curtain window class.
|
||||
static const UTF16 *getCurtainWindowClassName();
|
||||
|
||||
/// Return the platform specific object needed to create or attach an
|
||||
/// accelerated graohics drawing context on or to the window
|
||||
virtual void* getPlatformDrawable() const { return mWindowHandle; }
|
||||
};
|
||||
#endif
|
||||
453
Engine/source/windowManager/win32/win32WindowMgr.cpp
Normal file
453
Engine/source/windowManager/win32/win32WindowMgr.cpp
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformWin32/platformWin32.h"
|
||||
#include "windowManager/win32/win32WindowMgr.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "windowManager/win32/winDispatch.h"
|
||||
#include "core/util/journal/process.h"
|
||||
#include "core/strings/unicode.h"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
void CloseSplashWindow(HINSTANCE hinst);
|
||||
|
||||
PlatformWindowManager * CreatePlatformWindowManager()
|
||||
{
|
||||
return new Win32WindowManager();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
Win32WindowManager::Win32WindowManager()
|
||||
{
|
||||
// Register in the process list.
|
||||
Process::notify(this, &Win32WindowManager::_process, PROCESS_INPUT_ORDER);
|
||||
|
||||
// Init our list of allocated windows.
|
||||
mWindowListHead = NULL;
|
||||
|
||||
// By default, we have no parent window.
|
||||
mParentWindow = NULL;
|
||||
|
||||
mCurtainWindow = NULL;
|
||||
|
||||
mOffscreenRender = false;
|
||||
}
|
||||
|
||||
Win32WindowManager::~Win32WindowManager()
|
||||
{
|
||||
// Get ourselves off the process list.
|
||||
Process::remove(this, &Win32WindowManager::_process);
|
||||
|
||||
// Kill all our windows first.
|
||||
while(mWindowListHead)
|
||||
// The destructors update the list, so this works just fine.
|
||||
delete mWindowListHead;
|
||||
}
|
||||
|
||||
RectI Win32WindowManager::getPrimaryDesktopArea()
|
||||
{
|
||||
RECT primaryWorkRect;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &primaryWorkRect, 0);
|
||||
|
||||
RectI res;
|
||||
res.point.x = primaryWorkRect.left;
|
||||
res.point.y = primaryWorkRect.top;
|
||||
res.extent.x = primaryWorkRect.right - primaryWorkRect.left;
|
||||
res.extent.y = primaryWorkRect.bottom - primaryWorkRect.top;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Point2I Win32WindowManager::getDesktopResolution()
|
||||
{
|
||||
DEVMODE devMode;
|
||||
dMemset( &devMode, 0, sizeof( devMode ) );
|
||||
devMode.dmSize = sizeof( devMode );
|
||||
|
||||
if (!::EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devMode))
|
||||
return Point2I(-1,-1);
|
||||
|
||||
// Return Resolution
|
||||
return Point2I(devMode.dmPelsWidth, devMode.dmPelsHeight);
|
||||
}
|
||||
|
||||
S32 Win32WindowManager::getDesktopBitDepth()
|
||||
{
|
||||
DEVMODE devMode;
|
||||
dMemset( &devMode, 0, sizeof( devMode ) );
|
||||
devMode.dmSize = sizeof( devMode );
|
||||
|
||||
if (!::EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devMode))
|
||||
return -1;
|
||||
|
||||
// Return Bits per Pixel
|
||||
return (S32)devMode.dmBitsPerPel;
|
||||
}
|
||||
|
||||
BOOL Win32WindowManager::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData )
|
||||
{
|
||||
Vector<RectI> * regions = (Vector<RectI>*)dwData;
|
||||
|
||||
regions->increment();
|
||||
regions->last().point.x = lprcMonitor->left;
|
||||
regions->last().point.y = lprcMonitor->top;
|
||||
regions->last().extent.x = lprcMonitor->right - lprcMonitor->left;
|
||||
regions->last().extent.y = lprcMonitor->bottom - lprcMonitor->top;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32WindowManager::getMonitorRegions(Vector<RectI> ®ions)
|
||||
{
|
||||
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (U32)(void*)®ions);
|
||||
}
|
||||
|
||||
void Win32WindowManager::getWindows(VectorPtr<PlatformWindow*> &windows)
|
||||
{
|
||||
Win32Window *win = mWindowListHead;
|
||||
while(win)
|
||||
{
|
||||
windows.push_back(win);
|
||||
win = win->mNextWindow;
|
||||
}
|
||||
}
|
||||
|
||||
PlatformWindow *Win32WindowManager::createWindow(GFXDevice *device, const GFXVideoMode &mode)
|
||||
{
|
||||
// Do the allocation.
|
||||
Win32Window *w32w = new Win32Window();
|
||||
w32w->setOffscreenRender(mOffscreenRender);
|
||||
w32w->mWindowId = getNextId();
|
||||
w32w->mOwningManager = this;
|
||||
|
||||
// Link into our list of windows.
|
||||
linkWindow(w32w);
|
||||
|
||||
DWORD dwExStyle;
|
||||
DWORD dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
dwStyle |= WS_OVERLAPPEDWINDOW | WS_THICKFRAME | WS_CAPTION;
|
||||
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
|
||||
// If we're parented, we want a different set of window styles.
|
||||
if(mParentWindow)
|
||||
dwStyle = WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CHILDWINDOW;
|
||||
|
||||
if (mOffscreenRender)
|
||||
{
|
||||
dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
dwExStyle = 0;
|
||||
}
|
||||
|
||||
// Create the window handle
|
||||
w32w->mWindowHandle = CreateWindowEx(
|
||||
dwExStyle,
|
||||
Win32Window::getWindowClassName(), //class name
|
||||
String( getEngineProductString() ).utf16(), //window title
|
||||
dwStyle, //style - need clip siblings/children for opengl
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
mParentWindow, //parent window
|
||||
NULL, //menu? No.
|
||||
NULL, //the hInstance
|
||||
NULL ); //no funky params
|
||||
|
||||
// Note the style we created with so we can switch back to it when we're
|
||||
// done with full-screen mode.
|
||||
w32w->mWindowedWindowStyle = dwStyle;
|
||||
|
||||
// Set the video mode on the window
|
||||
w32w->setVideoMode(mode);
|
||||
|
||||
// Associate our window struct with the HWND.
|
||||
SetWindowLongPtrW(w32w->mWindowHandle, GWLP_USERDATA, (LONG)w32w);
|
||||
|
||||
// Do some error checking.
|
||||
AssertFatal(w32w->mWindowHandle != NULL, "Win32WindowManager::createWindow - Could not create window!");
|
||||
if(w32w->mWindowHandle == NULL)
|
||||
{
|
||||
Con::errorf("Win32WindowManager::createWindow - Could not create window!");
|
||||
delete w32w;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If we're not rendering offscreen, make sure our window is shown and drawn to.
|
||||
|
||||
if (!mOffscreenRender)
|
||||
ShowWindow( w32w->mWindowHandle, SW_SHOWDEFAULT );
|
||||
|
||||
// Close any splash screen we created
|
||||
CloseSplashWindow(winState.appInstance);
|
||||
|
||||
// Bind the window to the specified device.
|
||||
if(device)
|
||||
{
|
||||
w32w->mDevice = device;
|
||||
w32w->mTarget = device->allocWindowTarget(w32w);
|
||||
AssertISV(w32w->mTarget,
|
||||
"Win32WindowManager::createWindow - failed to get a window target back from the device.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::warnf("Win32WindowManager::createWindow - created a window with no device!");
|
||||
}
|
||||
|
||||
// Update it if needed.
|
||||
UpdateWindow( w32w->mWindowHandle );
|
||||
|
||||
return w32w;
|
||||
}
|
||||
|
||||
|
||||
void Win32WindowManager::setParentWindow(void* newParent)
|
||||
{
|
||||
Con::printf( "Setting parent HWND: %d", newParent );
|
||||
mParentWindow = (HWND)newParent;
|
||||
if( mWindowListHead && mWindowListHead->mWindowHandle )
|
||||
::SetParent( mWindowListHead->mWindowHandle, mParentWindow);
|
||||
}
|
||||
|
||||
void* Win32WindowManager::getParentWindow()
|
||||
{
|
||||
return (void*)mParentWindow;
|
||||
}
|
||||
|
||||
void Win32WindowManager::_process()
|
||||
{
|
||||
MSG msg;
|
||||
bool _blocking = false;
|
||||
|
||||
// CodeReview [tom, 4/30/2007] Maintaining two completely separate message
|
||||
// handlers that are essentially the same is silly. The first one never
|
||||
// seems to run as _blocking is hard coded to false above, so is this even
|
||||
// needed ? If it is, this should be rewritten to use the one loop that
|
||||
// adjusts as needed based on _blocking and Journal::IsPlaying()
|
||||
|
||||
if (_blocking && !Journal::IsPlaying())
|
||||
{
|
||||
// In blocking mode, we process one message at a time.
|
||||
if (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
bool noTranslate = false;
|
||||
Win32Window *w32w = mWindowListHead;
|
||||
while(w32w)
|
||||
{
|
||||
noTranslate = w32w->translateMessage(msg);
|
||||
if(noTranslate) break;
|
||||
w32w = w32w->mNextWindow;
|
||||
}
|
||||
|
||||
if(! noTranslate)
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
// This should be WM_QUIT
|
||||
Dispatch(ImmediateDispatch,0,msg.message,msg.wParam,msg.lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Process all queued up messages
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
bool translated = false;
|
||||
|
||||
// Win32Window *w32w = mWindowListHead;
|
||||
// while(w32w)
|
||||
// {
|
||||
// noTranslate = w32w->translateMessage(msg);
|
||||
// if(noTranslate) break;
|
||||
// w32w = w32w->mNextWindow;
|
||||
// }
|
||||
|
||||
// [tom, 4/30/2007] I think this should work, but leaving the above commented
|
||||
// out just in case this is actually fubared with multiple windows.
|
||||
Win32Window* window = (Win32Window*)(GetWindowLong(msg.hwnd, GWL_USERDATA));
|
||||
if(window)
|
||||
translated = window->translateMessage(msg);
|
||||
|
||||
if(! translated)
|
||||
{
|
||||
// Win32Window::translateMessage() will post a WM_COMMAND event for
|
||||
// translated accelerator events, so dispatching again will cause a
|
||||
// the input event to be dispatched, which is usually not what we want.
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
Dispatch(ImmediateDispatch,0,msg.message,msg.wParam,msg.lParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch any delayed events
|
||||
while (DispatchNext());
|
||||
|
||||
// Fire off idle events for every window.
|
||||
Win32Window *w32w = mWindowListHead;
|
||||
while(w32w)
|
||||
{
|
||||
w32w->idleEvent.trigger();
|
||||
w32w = w32w->mNextWindow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PlatformWindow * Win32WindowManager::getWindowById( WindowId id )
|
||||
{
|
||||
// Walk the list and find the matching id, if any.
|
||||
Win32Window *win = mWindowListHead;
|
||||
while(win)
|
||||
{
|
||||
if(win->getWindowId() == id)
|
||||
return win;
|
||||
|
||||
win = win->mNextWindow;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PlatformWindow * Win32WindowManager::getFirstWindow()
|
||||
{
|
||||
return mWindowListHead != NULL ? mWindowListHead : NULL;
|
||||
}
|
||||
|
||||
PlatformWindow* Win32WindowManager::getFocusedWindow()
|
||||
{
|
||||
Win32Window* window = mWindowListHead;
|
||||
while( window )
|
||||
{
|
||||
if( window->isFocused() )
|
||||
return window;
|
||||
|
||||
window = window->mNextWindow;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Win32WindowManager::linkWindow( Win32Window *w )
|
||||
{
|
||||
w->mNextWindow = mWindowListHead;
|
||||
mWindowListHead = w;
|
||||
}
|
||||
|
||||
void Win32WindowManager::unlinkWindow( Win32Window *w )
|
||||
{
|
||||
Win32Window **walk = &mWindowListHead;
|
||||
while(*walk)
|
||||
{
|
||||
if(*walk != w)
|
||||
{
|
||||
// Advance to next item in list.
|
||||
walk = &(*walk)->mNextWindow;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Got a match - unlink and return.
|
||||
*walk = (*walk)->mNextWindow;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Win32WindowManager::_processCmdLineArgs( const S32 argc, const char **argv )
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if ( dStrnicmp( argv[i], "-window", 7 ) == 0 )
|
||||
{
|
||||
i++;
|
||||
|
||||
if ( i >= argc )
|
||||
{
|
||||
Con::errorf( "Command line error: -window requires an argument" );
|
||||
break;
|
||||
}
|
||||
|
||||
S32 hwnd = dAtoi( argv[i] );
|
||||
|
||||
if ( hwnd == 0 || hwnd == S32_MAX )
|
||||
{
|
||||
Con::errorf( "Command line error: -window requires a number, found [%s]", argv[i] );
|
||||
break;
|
||||
}
|
||||
|
||||
mParentWindow = (HWND)hwnd;
|
||||
Con::printf( "HWND from command line: %d", hwnd );
|
||||
}
|
||||
|
||||
if ( dStrnicmp( argv[i], "-offscreen", 10 ) == 0 )
|
||||
{
|
||||
mOffscreenRender = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Win32WindowManager::lowerCurtain()
|
||||
{
|
||||
if(mCurtainWindow)
|
||||
return;
|
||||
|
||||
// For now just grab monitor of the first window... we may need to
|
||||
// beef this up later on, maybe by passing in the window that's entering
|
||||
// leaving full-screen to lowerCurtain.
|
||||
HMONITOR hMon = MonitorFromWindow(mWindowListHead->getHWND(), MONITOR_DEFAULTTOPRIMARY);
|
||||
|
||||
// Get the monitor's extents.
|
||||
MONITORINFO monInfo;
|
||||
dMemset(&monInfo, 0, sizeof MONITORINFO);
|
||||
monInfo.cbSize = sizeof MONITORINFO;
|
||||
|
||||
GetMonitorInfo(hMon, &monInfo);
|
||||
|
||||
mCurtainWindow = CreateWindow(Win32Window::getCurtainWindowClassName(),
|
||||
dT(""), (WS_POPUP | WS_MAXIMIZE | WS_VISIBLE),
|
||||
monInfo.rcWork.left, monInfo.rcWork.top,
|
||||
monInfo.rcWork.right - monInfo.rcWork.left,
|
||||
monInfo.rcWork.bottom - monInfo.rcWork.top,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!mOffscreenRender)
|
||||
SetWindowPos(mCurtainWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
void Win32WindowManager::raiseCurtain()
|
||||
{
|
||||
if(!mCurtainWindow)
|
||||
return;
|
||||
|
||||
DestroyWindow(mCurtainWindow);
|
||||
mCurtainWindow = NULL;
|
||||
}
|
||||
93
Engine/source/windowManager/win32/win32WindowMgr.h
Normal file
93
Engine/source/windowManager/win32/win32WindowMgr.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WINDOWMANAGER_WIN32_WIN32WINDOWMANAGER_
|
||||
#define _WINDOWMANAGER_WIN32_WIN32WINDOWMANAGER_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "math/mMath.h"
|
||||
#include "gfx/gfxStructs.h"
|
||||
#include "windowManager/win32/win32Window.h"
|
||||
#include "core/util/tVector.h"
|
||||
|
||||
/// Win32 implementation of the window manager interface.
|
||||
class Win32WindowManager : public PlatformWindowManager
|
||||
{
|
||||
friend class Win32Window;
|
||||
|
||||
virtual void _processCmdLineArgs(const S32 argc, const char **argv);
|
||||
|
||||
/// Link the specified window into the window list.
|
||||
void linkWindow(Win32Window *w);
|
||||
|
||||
/// Remove specified window from the window list.
|
||||
void unlinkWindow(Win32Window *w);
|
||||
|
||||
/// Callback for the process list.
|
||||
void _process();
|
||||
|
||||
/// List of allocated windows.
|
||||
Win32Window *mWindowListHead;
|
||||
|
||||
/// Parent window, used in window setup in web plugin scenarios.
|
||||
HWND mParentWindow;
|
||||
|
||||
/// set via command line -offscreen option, controls whether rendering/input
|
||||
// is intended for offscreen rendering
|
||||
bool mOffscreenRender;
|
||||
|
||||
/// Callback to receive information about available monitors.
|
||||
static BOOL CALLBACK MonitorEnumProc(
|
||||
HMONITOR hMonitor, // handle to display monitor
|
||||
HDC hdcMonitor, // handle to monitor DC
|
||||
LPRECT lprcMonitor, // monitor intersection rectangle
|
||||
LPARAM dwData // data
|
||||
);
|
||||
|
||||
/// If a curtain window is present, then its HWND will be stored here.
|
||||
HWND mCurtainWindow;
|
||||
|
||||
public:
|
||||
Win32WindowManager();
|
||||
~Win32WindowManager();
|
||||
|
||||
virtual RectI getPrimaryDesktopArea();
|
||||
virtual S32 getDesktopBitDepth();
|
||||
virtual Point2I getDesktopResolution();
|
||||
|
||||
virtual void getMonitorRegions(Vector<RectI> ®ions);
|
||||
virtual PlatformWindow *createWindow(GFXDevice *device, const GFXVideoMode &mode);
|
||||
virtual void getWindows(VectorPtr<PlatformWindow*> &windows);
|
||||
|
||||
virtual void setParentWindow(void* newParent);
|
||||
virtual void* getParentWindow();
|
||||
|
||||
virtual PlatformWindow *getWindowById(WindowId id);
|
||||
virtual PlatformWindow *getFirstWindow();
|
||||
virtual PlatformWindow* getFocusedWindow();
|
||||
|
||||
virtual void lowerCurtain();
|
||||
virtual void raiseCurtain();
|
||||
};
|
||||
|
||||
#endif
|
||||
594
Engine/source/windowManager/win32/winDispatch.cpp
Normal file
594
Engine/source/windowManager/win32/winDispatch.cpp
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define NO_MINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
// This is a fix for mouse wheel support on
|
||||
// older versions of VC++.
|
||||
#if _MSC_VER < 1500
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "platform/event.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include "windowManager/win32/winDispatch.h"
|
||||
#include "windowManager/win32/win32Window.h"
|
||||
#include "windowManager/win32/win32CursorController.h"
|
||||
#include "platformWin32/winDirectInput.h"
|
||||
#include "core/util/journal/process.h"
|
||||
#include "core/util/journal/journaledSignal.h"
|
||||
|
||||
static U32 _ModifierKeys=0;
|
||||
static BYTE keyboardState[256];
|
||||
static bool initKBState = false;
|
||||
static bool sgDoubleByteEnabled = false;
|
||||
|
||||
// is keyboard input a standard (non-changing) VK keycode
|
||||
#define dIsStandardVK(c) (((0x08 <= (c)) && ((c) <= 0x12)) || \
|
||||
((c) == 0x1b) || \
|
||||
((0x20 <= (c)) && ((c) <= 0x2e)) || \
|
||||
((0x30 <= (c)) && ((c) <= 0x39)) || \
|
||||
((0x41 <= (c)) && ((c) <= 0x5a)) || \
|
||||
((0x70 <= (c)) && ((c) <= 0x7B)))
|
||||
|
||||
extern InputObjectInstances DIK_to_Key( U8 dikCode );
|
||||
|
||||
extern U8 TranslateOSKeyCode(U8 vcode );
|
||||
|
||||
extern InputModifiers convertModifierBits(const U32 in);
|
||||
|
||||
static void _keyboardEvent(Win32Window* window,UINT message, WPARAM wParam, WPARAM lParam)
|
||||
{
|
||||
if(!initKBState)
|
||||
{
|
||||
dMemset(keyboardState, 0, sizeof(keyboardState));
|
||||
initKBState = true;
|
||||
}
|
||||
|
||||
// Extract windows key info:
|
||||
// S32 repeatCount = (lParam & 0xffff);
|
||||
U32 scanCode = (lParam >> 16) & 0xff;
|
||||
bool extended = lParam & (1 << 24); // Enhanced keyboard key
|
||||
bool previous = lParam & (1 << 30); // Previously down
|
||||
bool make = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
|
||||
|
||||
// Translate the OS virtual key code to a Torque KEY_XXXX.
|
||||
S32 nVirtkey = TranslateOSKeyCode( wParam );
|
||||
|
||||
S32 keyCode;
|
||||
if ( wParam == VK_PROCESSKEY && sgDoubleByteEnabled )
|
||||
keyCode = MapVirtualKey( scanCode, 1 ); // This is the REAL virtual key...
|
||||
else
|
||||
keyCode = wParam;
|
||||
|
||||
// Convert alt/shift/ctrl to left or right variant if needed.
|
||||
S32 newVirtKey = nVirtkey;
|
||||
switch(nVirtkey)
|
||||
{
|
||||
case KEY_ALT:
|
||||
newVirtKey = extended ? KEY_RALT : KEY_LALT;
|
||||
break;
|
||||
case KEY_CONTROL:
|
||||
newVirtKey = extended ? KEY_RCONTROL : KEY_LCONTROL;
|
||||
break;
|
||||
case KEY_SHIFT:
|
||||
newVirtKey = (scanCode == 54) ? KEY_RSHIFT : KEY_LSHIFT;
|
||||
break;
|
||||
case KEY_RETURN:
|
||||
if ( extended )
|
||||
newVirtKey = KEY_NUMPADENTER;
|
||||
break;
|
||||
}
|
||||
|
||||
// Track modifier keys
|
||||
U32 modifier = 0;
|
||||
switch (newVirtKey)
|
||||
{
|
||||
case KEY_LALT: modifier = IM_LALT; break;
|
||||
case KEY_RALT: modifier = IM_RALT; break;
|
||||
case KEY_LSHIFT: modifier = IM_LSHIFT; break;
|
||||
case KEY_RSHIFT: modifier = IM_RSHIFT; break;
|
||||
case KEY_LCONTROL: modifier = IM_LCTRL; break;
|
||||
case KEY_RCONTROL: modifier = IM_RCTRL; break;
|
||||
}
|
||||
|
||||
if (make)
|
||||
{
|
||||
_ModifierKeys |= modifier;
|
||||
keyboardState[keyCode] |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ModifierKeys &= ~modifier;
|
||||
keyboardState[keyCode] &= 0x7f;
|
||||
}
|
||||
|
||||
U32 torqueMods = convertModifierBits( _ModifierKeys );
|
||||
Input::setModifierKeys( torqueMods );
|
||||
|
||||
// If character event translation is active and this isn't a key
|
||||
// mapped in the global action map, try converting the event into
|
||||
// a character event first.
|
||||
|
||||
if( make
|
||||
&& window->getKeyboardTranslation()
|
||||
&& !window->shouldNotTranslate( torqueMods, newVirtKey ) )
|
||||
{
|
||||
U16 chars[ 64 ];
|
||||
dMemset( chars, 0, sizeof( chars ) );
|
||||
|
||||
S32 res = ToUnicode( keyCode, scanCode, keyboardState, chars, sizeof( chars ) / sizeof( chars[ 0 ] ), 0 );
|
||||
|
||||
// This should only happen on Window 9x/ME systems
|
||||
if( res == 0 )
|
||||
res = ToAscii( keyCode, scanCode, keyboardState, chars, 0 );
|
||||
|
||||
if( res >= 1 )
|
||||
{
|
||||
// Post chars, but filter them to not be control codes... this is a bit hacky.
|
||||
|
||||
bool handledCharEvent = false;
|
||||
for( S32 i=0; i< res; i ++ )
|
||||
if( chars[i] >= 32)
|
||||
{
|
||||
window->charEvent.trigger(window->getWindowId(),_ModifierKeys,chars[i]);
|
||||
handledCharEvent = true;
|
||||
}
|
||||
|
||||
if( handledCharEvent )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Produce a key event.
|
||||
|
||||
U32 action = make ? (previous ? IA_REPEAT : IA_MAKE ) : IA_BREAK;
|
||||
window->keyEvent.trigger(window->getWindowId(),_ModifierKeys,action,newVirtKey);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool _dispatch(HWND hWnd,UINT message,WPARAM wParam,WPARAM lParam)
|
||||
{
|
||||
static bool button[3] = {false,false,false};
|
||||
static S32 mouseNCState = -1; // -1 denotes unchanged,
|
||||
// 0 denotes changed but was hidden
|
||||
// 1 denotes changed but was visible
|
||||
Win32Window* window = hWnd?(Win32Window*)GetWindowLong(hWnd, GWL_USERDATA): 0;
|
||||
const WindowId devId = window ? window->getWindowId() : 0;
|
||||
|
||||
// State tracking for focus/lose focus cursor management
|
||||
static bool cursorLocked = false;
|
||||
static bool cursorVisible = true;
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
// Skip it if we have no window!
|
||||
if (!window || !window->getCursorController())
|
||||
break;
|
||||
|
||||
|
||||
PlatformCursorController *pController = window->getCursorController();
|
||||
|
||||
// If we're locked and unfocused, ignore it.
|
||||
if(window->shouldLockMouse() && !window->isFocused())
|
||||
break;
|
||||
|
||||
// If the mouse was shown to accommodate a NC mouse move
|
||||
// we need to change it back to what it was
|
||||
if( mouseNCState != -1 )
|
||||
{
|
||||
pController->setCursorVisible( mouseNCState );
|
||||
mouseNCState = -1; // reset to unchanged
|
||||
}
|
||||
|
||||
// Let the cursor manager update the native cursor.
|
||||
pController->refreshCursor();
|
||||
|
||||
// Grab the mouse pos so we can modify it.
|
||||
S32 mouseX = S16(LOWORD(lParam));
|
||||
S32 mouseY = S16(HIWORD(lParam));
|
||||
|
||||
// Ensure mouse lock when appropriate
|
||||
window->setMouseLocked( window->shouldLockMouse() );
|
||||
|
||||
// Are we locked?
|
||||
if(window->isMouseLocked())
|
||||
{
|
||||
// Always invisible when locked.
|
||||
if( window->isCursorVisible() )
|
||||
window->setCursorVisible( false );
|
||||
|
||||
RECT r;
|
||||
GetWindowRect(window->getHWND(), &r);
|
||||
|
||||
// See Win32Window::setMouseLocked for explanation
|
||||
RECT rCopy = r;
|
||||
rCopy.top += 32; rCopy.bottom -= 64;
|
||||
rCopy.left += 32; rCopy.right -= 64;
|
||||
ClipCursor(&rCopy);
|
||||
|
||||
// Recenter the mouse if necessary (don't flood the message pump)
|
||||
Point2I curPos;
|
||||
pController->getCursorPosition( curPos );
|
||||
|
||||
const S32 centerX = (r.right + r.left) / 2;
|
||||
const S32 centerY = (r.bottom + r.top) / 2;
|
||||
|
||||
if( curPos.x != centerX || curPos.y != centerY )
|
||||
pController->setCursorPosition(centerX, centerY);
|
||||
|
||||
// Convert the incoming client pos into a screen pos, so we can
|
||||
// accurately convert to relative coordinates.
|
||||
POINT mousePos;
|
||||
mousePos.x = mouseX;
|
||||
mousePos.y = mouseY;
|
||||
|
||||
ClientToScreen(window->getHWND(), &mousePos);
|
||||
|
||||
// Now we can calculate the position relative to the center we set.
|
||||
mouseX = mousePos.x - centerX;
|
||||
mouseY = mousePos.y - centerY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Probably don't need to call this all the time but better
|
||||
// safe than sorry...
|
||||
ClipCursor(NULL);
|
||||
}
|
||||
|
||||
window->mouseEvent.trigger(devId,_ModifierKeys,mouseX,mouseY,window->isMouseLocked());
|
||||
break;
|
||||
}
|
||||
|
||||
// We want to show the system cursor whenever we leave
|
||||
// our window, and it'd be simple, except for one problem:
|
||||
// showcursor isn't a toggle. so, keep hammering it until
|
||||
// the cursor is *actually* going to be shown.
|
||||
case WM_NCMOUSEMOVE:
|
||||
{
|
||||
if( window )
|
||||
{
|
||||
mouseNCState = ( window->isCursorVisible() ? 1 : 0);
|
||||
window->setCursorVisible( true );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN: {
|
||||
int index = (message - WM_LBUTTONDOWN) / 3;
|
||||
button[index] = true;
|
||||
|
||||
// Capture the mouse on button down to allow dragging outside
|
||||
// of the window boundary.
|
||||
if (GetCapture() != hWnd)
|
||||
SetCapture(hWnd);
|
||||
|
||||
if (window)
|
||||
window->buttonEvent.trigger(devId,_ModifierKeys,IA_MAKE,index);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP: {
|
||||
int index = (message - WM_LBUTTONUP) / 3;
|
||||
button[index] = false;
|
||||
|
||||
// Release mouse capture from button down.
|
||||
if (!button[0] && !button[1] && !button[2])
|
||||
ReleaseCapture();
|
||||
|
||||
if (window)
|
||||
window->buttonEvent.trigger(devId,_ModifierKeys,IA_BREAK,index);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEWHEEL: // Vertical wheel.
|
||||
if (window)
|
||||
window->wheelEvent.trigger(devId,_ModifierKeys,0,GET_WHEEL_DELTA_WPARAM(wParam));
|
||||
break;
|
||||
|
||||
#ifdef WM_MOUSEHWHEEL // Vista
|
||||
case WM_MOUSEHWHEEL: // Horizontal wheel.
|
||||
if( window )
|
||||
window->wheelEvent.trigger( devId, _ModifierKeys, GET_WHEEL_DELTA_WPARAM( wParam ), 0 );
|
||||
break;
|
||||
#endif
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
if (window)
|
||||
_keyboardEvent(window,message,wParam,lParam);
|
||||
break;
|
||||
|
||||
// NOTE: if wParam is NOT equal to our window handle then we are GAINING focus
|
||||
case WM_SETFOCUS:
|
||||
|
||||
// clear any key states
|
||||
_ModifierKeys = 0;
|
||||
dMemset(keyboardState, 0, 256);
|
||||
Input::setModifierKeys(0);
|
||||
|
||||
// We must have a window present; otherwise there's nothing further
|
||||
// we can do about this event.
|
||||
if (window && window->getHWND() != (HWND)wParam)
|
||||
{
|
||||
if (cursorVisible == false)
|
||||
window->setCursorVisible(false);
|
||||
|
||||
if (cursorLocked == true)
|
||||
window->setMouseLocked(true);
|
||||
|
||||
// Update window state.
|
||||
window->setBackground(false);
|
||||
|
||||
// Fire event.
|
||||
window->appEvent.trigger(devId, GainFocus);
|
||||
|
||||
if (!Input::isActive())
|
||||
Input::activate();
|
||||
}
|
||||
break;
|
||||
|
||||
// NOTE: if wParam is NOT equal to our window handle then we are LOSING focus
|
||||
case WM_KILLFOCUS:
|
||||
|
||||
// clear any key states
|
||||
_ModifierKeys = 0;
|
||||
dMemset(keyboardState, 0, 256);
|
||||
Input::setModifierKeys(0);
|
||||
|
||||
// We must have a window present; otherwise there's nothing further
|
||||
// we can do about this event.
|
||||
if (window && window->getHWND() != (HWND)wParam)
|
||||
{
|
||||
HWND hwnd = (HWND)wParam;
|
||||
UTF16 classBuf[256];
|
||||
|
||||
if (hwnd)
|
||||
GetClassName(hwnd, classBuf, sizeof(classBuf));
|
||||
|
||||
// We toggle the mouse lock when we become inactive
|
||||
// causing the subsequent lock call to defer itself
|
||||
// until the window becomes active again.
|
||||
if (window && window->isMouseLocked())
|
||||
{
|
||||
window->setMouseLocked( false );
|
||||
window->setMouseLocked( true );
|
||||
}
|
||||
|
||||
// FIXME [tom, 5/1/2007] Hard coding this is lame since there's a const in win32Window.cpp
|
||||
// CodeReview - this fails if there is a second jug app in the arena.
|
||||
if (hwnd == NULL || dStrcmp(classBuf, L"TorqueJuggernaughtWindow") != 0)
|
||||
{
|
||||
// We are being made inactive and the window being made active isn't
|
||||
// a jugg window. Thus, we need to deactivate input.
|
||||
if (Input::isActive())
|
||||
Input::deactivate();
|
||||
}
|
||||
|
||||
cursorVisible = window->isCursorVisible();
|
||||
if (!cursorVisible)
|
||||
window->setCursorVisible(true);
|
||||
|
||||
cursorLocked = window->isMouseLocked();
|
||||
if (cursorLocked)
|
||||
window->setMouseLocked(false);
|
||||
|
||||
// Update window state.
|
||||
window->setBackground(true);
|
||||
|
||||
// Fire event.
|
||||
window->appEvent.trigger(devId, LoseFocus);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ACTIVATEAPP:
|
||||
if (wParam)
|
||||
{
|
||||
// Could extract current modifier state from windows.
|
||||
_ModifierKeys = 0;
|
||||
Input::setModifierKeys(_ModifierKeys);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
if (window)
|
||||
window->appEvent.trigger(devId,WindowClose);
|
||||
|
||||
// Force a quit if we're in play mode, otherwise there would be
|
||||
// no way to stop a journal playback.(
|
||||
if (Journal::IsPlaying())
|
||||
Process::requestShutdown();
|
||||
break;
|
||||
|
||||
case WM_TIMER: {
|
||||
if (window)
|
||||
window->appEvent.trigger(devId,Timer);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DESTROY:{
|
||||
// Only people who care about this currently are web plugins, because
|
||||
// everyone else will just handle the WM_CLOSE app event.
|
||||
if(window)
|
||||
window->appEvent.trigger(devId,WindowDestroy);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_QUIT: {
|
||||
// Quit indicates that we're not going to receive anymore Win32 messages.
|
||||
// Therefore, it's appropriate to flag our event loop for exit as well,
|
||||
// since we won't be getting any more messages.
|
||||
Process::requestShutdown();
|
||||
break;
|
||||
}
|
||||
|
||||
// CodeReview - This is not used now and will incur an overhead for rendering
|
||||
// since the renderThreadBlocked fix requires handling WM_PAINT and
|
||||
// triggering the displayEvent. May need to revisit this at a later
|
||||
// time if we want event driven rendering.
|
||||
//case WM_PAINT: {
|
||||
// // Checking for isOpen will keep us from generating an event
|
||||
// // during the window creation process, which can cause problems
|
||||
// // with the journaling.
|
||||
// if (window && window->isOpen() && !winState.renderThreadBlocked )
|
||||
// window->displayEvent.trigger(devId);
|
||||
//}
|
||||
case WM_SIZE: {
|
||||
if (window && wParam != SIZE_MINIMIZED && !Journal::IsPlaying())
|
||||
{
|
||||
window->resizeEvent.trigger(window->getWindowId(), LOWORD(lParam),HIWORD(lParam));
|
||||
|
||||
// Consume all existing mouse events and those posted to our own dispatch queue
|
||||
MSG msg;
|
||||
PeekMessage( &msg, 0,WM_MOUSEFIRST,WM_MOUSELAST , PM_QS_POSTMESSAGE | PM_NOYIELD | PM_REMOVE );
|
||||
RemoveMessages( NULL, WM_MOUSEMOVE, WM_MOUSEMOVE );
|
||||
|
||||
if( window->isMouseLocked())
|
||||
{
|
||||
RECT r;
|
||||
GetWindowRect(window->getHWND(), &r);
|
||||
|
||||
S32 centerX = (r.right + r.left) >> 1;
|
||||
S32 centerY = ((r.bottom + r.top) >> 1);
|
||||
window->setCursorPosition( centerX, centerY );
|
||||
|
||||
// Set the CursorPos
|
||||
SetCursorPos(centerX, centerY);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Structure used to store Windows events for delayed dispatching
|
||||
struct WinMessageQueue
|
||||
{
|
||||
public:
|
||||
struct Message {
|
||||
HWND hWnd;
|
||||
UINT message;
|
||||
WPARAM wparam;
|
||||
WPARAM lparam;
|
||||
};
|
||||
|
||||
WinMessageQueue()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION( _messageList );
|
||||
}
|
||||
bool isEmpty() {
|
||||
return !_messageList.size();
|
||||
}
|
||||
void post(HWND hWnd,UINT message,WPARAM wparam,WPARAM lparam) {
|
||||
Message msg;
|
||||
msg.hWnd = hWnd;
|
||||
msg.message = message;
|
||||
msg.wparam = wparam;
|
||||
msg.lparam = lparam;
|
||||
_messageList.push_back(msg);
|
||||
}
|
||||
bool next(Message* msg) {
|
||||
if (!_messageList.size())
|
||||
return false;
|
||||
*msg = _messageList.first();
|
||||
_messageList.pop_front();
|
||||
return true;
|
||||
}
|
||||
void remove(HWND hWnd, UINT msgBegin = -1, UINT msgEnd = -1) {
|
||||
for (S32 i = 0; i < _messageList.size(); i++)
|
||||
{
|
||||
// Match Window
|
||||
if( hWnd != NULL && _messageList[i].hWnd == hWnd)
|
||||
_messageList.erase_fast(i--);
|
||||
else if( msgBegin != -1 && msgEnd != -1 )
|
||||
{
|
||||
// CodeReview - Match Message Range [6/30/2007 justind]
|
||||
//
|
||||
// Word of caution : Use this only if you know what you're doing.
|
||||
// I cannot be responsible for you blowing your leg off destroying
|
||||
// a bunch of messages you didn't intend to if you specify a ridiculous
|
||||
// range of messages values.
|
||||
//
|
||||
// To filter a single message, pass the message as the begin and end.
|
||||
if( _messageList[i].message >= msgBegin && _messageList[i].message <= msgEnd )
|
||||
_messageList.erase_fast(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<Message> _messageList;
|
||||
};
|
||||
|
||||
static WinMessageQueue _MessageQueue;
|
||||
|
||||
|
||||
void RemoveMessages(HWND hWnd,UINT msgBegin,WPARAM msgEnd )
|
||||
{
|
||||
_MessageQueue.remove( hWnd, msgBegin, msgEnd );
|
||||
}
|
||||
|
||||
// Dispatch the window event, or queue up for later
|
||||
void Dispatch(DispatchType type,HWND hWnd,UINT message,WPARAM wparam,WPARAM lparam)
|
||||
{
|
||||
// If the message queue is not empty, then we'll need to delay
|
||||
// this dispatch in order to preserve message order.
|
||||
if (type == DelayedDispatch || !_MessageQueue.isEmpty())
|
||||
_MessageQueue.post(hWnd,message,wparam,lparam);
|
||||
else
|
||||
_dispatch(hWnd,message,wparam,lparam);
|
||||
}
|
||||
|
||||
// Dispatch next even in the queue
|
||||
bool DispatchNext()
|
||||
{
|
||||
WinMessageQueue::Message msg;
|
||||
if (!_MessageQueue.next(&msg))
|
||||
return false;
|
||||
_dispatch(msg.hWnd,msg.message,msg.wparam,msg.lparam);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove events from the queue
|
||||
void DispatchRemove(HWND hWnd)
|
||||
{
|
||||
_MessageQueue.remove(hWnd);
|
||||
}
|
||||
74
Engine/source/windowManager/win32/winDispatch.h
Normal file
74
Engine/source/windowManager/win32/winDispatch.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WINDOWMANAGER_WIN32_WINDISPATCH_H_
|
||||
#define _WINDOWMANAGER_WIN32_WINDISPATCH_H_
|
||||
|
||||
//
|
||||
// *** This header requires that Window.h be included before this.
|
||||
//
|
||||
|
||||
/// Some events must be processed immediately, and others can or should be
|
||||
/// processed later. This enum allows us to distinguish between the two
|
||||
/// types.
|
||||
enum DispatchType {
|
||||
DelayedDispatch,
|
||||
ImmediateDispatch,
|
||||
};
|
||||
|
||||
/// Dispatch the event into the journaling system.
|
||||
///
|
||||
/// Dispatch Win32 events into the journaling system. To avoid problems
|
||||
/// with journaling, events should normally use the DelayedDispatch type.
|
||||
///
|
||||
/// Delayed events are pushed onto a queue for later processing by DispatchNext().
|
||||
void Dispatch(DispatchType,HWND hWnd,UINT message,WPARAM wparam,WPARAM lparam);
|
||||
|
||||
/// Remove messages from the event queue, matching a msg value range or hWnd
|
||||
///
|
||||
/// If no filter is specified, either HWND or MessageRange, nothing will be removed
|
||||
/// You may not match HWND and MsgRange both, currently.
|
||||
///
|
||||
/// Message Range is calculated as follows.
|
||||
/// @li Both Begin and End are specified as message values, ex WM_MOUSEMOVE
|
||||
/// @li Specifying an identical set of begin/end will remove all messages matching that message value (WM_MOUSEMOVE)
|
||||
/// @li If you specify a range it will remove from that beginning value through the end value
|
||||
///
|
||||
/// @note : The range is useful because on windows messages declared such that you can filter a block of
|
||||
/// messages just by specifying the beginning value and end.
|
||||
/// ex. WM_MOUSEFIRST,WM_MOUSELAST range will match all mouse messages.
|
||||
|
||||
///
|
||||
/// @param hWnd The HWND to filter by, this cannot be combined with a msg range filter currently
|
||||
/// @param msgBegin The beginning msg value to filter from
|
||||
/// @param msgEnd The ending msg value to filter to
|
||||
void RemoveMessages(HWND hWnd,UINT msgBegin,UINT msgEnd );
|
||||
|
||||
/// Dispatch the next event in the delayed dispatch queue.
|
||||
/// This function should be called outside of any journaled calls.
|
||||
/// Returns true if an event was dispatched.
|
||||
bool DispatchNext();
|
||||
|
||||
/// Remove events related to the window from the dispatch queue.
|
||||
void DispatchRemove(HWND hWnd);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue