dolphin/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
Glenn Rice 13437c1f6b Fix segfault in linux if user clicks on the window manager close button of the
emulator.  Also added the ability to close the emulator with the escape key.
Fixed an issue that caused a segmentation fault when trying to close the
emulator when running in fullscreen mode, which can also be done using the
escape key.  This makes fullscreen mode useable in linux!


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5023 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-02-07 02:41:02 +00:00

711 lines
19 KiB
C++

// Project description
// -------------------
// Name: nJoy
// Description: A Dolphin Compatible Input Plugin
//
// Author: Falcon4ever (nJoy@falcon4ever.com)
// Site: www.multigesture.net
// Copyright (C) 2003 Dolphin Project.
//
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "GCPad.h"
#include "Config.h"
#include "LogManager.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigBox.h"
#endif
#ifdef _WIN32
#include "XInput.h"
#endif
// Declare config window so that we can write debugging info to it from functions in this file
#if defined(HAVE_WX) && HAVE_WX
GCPadConfigDialog* m_ConfigFrame = NULL;
#endif
// Variables
// ---------
bool KeyStatus[LAST_CONSTANT];
bool g_SearchDeviceDone = false;
CONTROLLER_MAPPING_GC GCMapping[4];
std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
int NumPads = 0, NumGoodPads = 0, g_ID = 0;
#ifdef _WIN32
HWND m_hWnd = NULL; // Handle to window
#endif
#if defined(HAVE_X11) && HAVE_X11
Display* WMdisplay;
#endif
SPADInitialize *g_PADInitialize = NULL;
PLUGIN_GLOBALS* globals = NULL;
// Standard crap to make wxWidgets happy
#ifdef _WIN32
HINSTANCE g_hInstance;
#if defined(HAVE_WX) && HAVE_WX
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
}
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
#if defined(HAVE_WX) && HAVE_WX
wxSetInstance((HINSTANCE)hinstDLL);
int argc = 0;
char **argv = NULL;
wxEntryStart(argc, argv);
if (!wxTheApp || !wxTheApp->CallOnInit())
return FALSE;
#endif
}
break;
case DLL_PROCESS_DETACH:
#if defined(HAVE_WX) && HAVE_WX
wxEntryCleanup();
#endif
break;
default:
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
#endif
#if defined(HAVE_WX) && HAVE_WX
wxWindow* GetParentedWxWindow(HWND Parent)
{
#ifdef _WIN32
wxSetInstance((HINSTANCE)g_hInstance);
#endif
wxWindow *win = new wxWindow();
#ifdef _WIN32
win->SetHWND((WXHWND)Parent);
win->AdoptAttributesFromHWND();
#endif
return win;
}
#endif
// Input Plugin Functions (from spec's)
// ------------------------------------
// Get properties of plugin
// ------------------------
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_PAD;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin GCPad Plugin (DebugFast)");
#else
#ifdef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin GCPad Plugin (Debug)");
#else
sprintf(_PluginInfo->Name, "Dolphin GCPad Plugin");
#endif
#endif
}
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
{
globals = _pPluginGlobals;
LogManager::SetInstance((LogManager *)globals->logManager);
}
// Call config dialog
// ------------------
void DllConfig(HWND _hParent)
{
if (!g_SearchDeviceDone)
{
g_Config.Load(); // load settings
// Init Joystick + Haptic (force feedback) subsystem on SDL 1.3
// Populate joyinfo for all attached devices
Search_Devices(joyinfo, NumPads, NumGoodPads);
g_SearchDeviceDone = true;
}
#if defined(HAVE_WX) && HAVE_WX
if (!m_ConfigFrame)
{
m_ConfigFrame = new GCPadConfigDialog(GetParentedWxWindow(_hParent));
m_ConfigFrame->ShowModal();
m_ConfigFrame->Destroy();
m_ConfigFrame = NULL;
}
#endif
}
void DllDebugger(HWND _hParent, bool Show)
{
}
// Init PAD (start emulation)
// --------------------------
void Initialize(void *init)
{
INFO_LOG(PAD, "Initialize: %i", SDL_WasInit(0));
g_PADInitialize = (SPADInitialize*)init;
#ifdef _WIN32
m_hWnd = (HWND)g_PADInitialize->hWnd;
#endif
#if defined(HAVE_X11) && HAVE_X11
WMdisplay = (Display*)g_PADInitialize->hWnd;
#endif
if (!g_SearchDeviceDone)
{
g_Config.Load(); // load settings
// Populate joyinfo for all attached devices
Search_Devices(joyinfo, NumPads, NumGoodPads);
g_SearchDeviceDone = true;
}
}
// Shutdown PAD (stop emulation)
// -----------------------------
void Shutdown()
{
INFO_LOG(PAD, "Shutdown: %i", SDL_WasInit(0));
Close_Devices();
// Finally close SDL
if (SDL_WasInit(0))
{
SDL_Quit();
}
// Remove the pointer to the initialize data
g_PADInitialize = NULL;
g_SearchDeviceDone = false;
}
// Save state
// --------------
void DoState(unsigned char **ptr, int mode)
{
#ifdef RERECORDING
Recording::DoState(ptr, mode);
#endif
}
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
}
// Set buttons status from keyboard input. Currently this is done from wxWidgets in the main application.
// --------------
void PAD_Input(u16 _Key, u8 _UpDown)
{
}
// Set PAD status
// --------------
// Called from: SI_DeviceGCController.cpp
// Function: Gives the current pad status to the Core
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
{
// Check if all is okay
if (_pPADStatus == NULL) return;
// Clear pad
memset(_pPADStatus, 0, sizeof(SPADStatus));
const int base = 0x80;
_pPADStatus->stickX = base;
_pPADStatus->stickY = base;
_pPADStatus->substickX = base;
_pPADStatus->substickY = base;
_pPADStatus->button |= PAD_USE_ORIGIN;
_pPADStatus->err = PAD_ERR_NONE;
// Check that Dolphin is in focus, otherwise don't update the pad status
if (!IsFocus()) return;
g_ID = _numPAD;
ReadLinuxKeyboard();
if (NumGoodPads && NumPads > GCMapping[_numPAD].ID)
UpdatePadState(GCMapping[_numPAD]);
if (IsKey(EGC_A))
{
_pPADStatus->button |= PAD_BUTTON_A;
_pPADStatus->analogA = DEF_BUTTON_FULL;
}
if (IsKey(EGC_B))
{
_pPADStatus->button |= PAD_BUTTON_B;
_pPADStatus->analogB = DEF_BUTTON_FULL;
}
if (IsKey(EGC_X)) _pPADStatus->button |= PAD_BUTTON_X;
if (IsKey(EGC_Y)) _pPADStatus->button |= PAD_BUTTON_Y;
if (IsKey(EGC_Z)) _pPADStatus->button |= PAD_TRIGGER_Z;
if (IsKey(EGC_START)) _pPADStatus->button |= PAD_BUTTON_START;
if (IsKey(EGC_DPAD_UP)) _pPADStatus->button |= PAD_BUTTON_UP;
if (IsKey(EGC_DPAD_DOWN)) _pPADStatus->button |= PAD_BUTTON_DOWN;
if (IsKey(EGC_DPAD_LEFT)) _pPADStatus->button |= PAD_BUTTON_LEFT;
if (IsKey(EGC_DPAD_RIGHT)) _pPADStatus->button |= PAD_BUTTON_RIGHT;
if (GCMapping[_numPAD].Stick.Main == FROM_KEYBOARD)
{
int iMagnitude = DEF_STICK_FULL;
bool bUp = false;
bool bDown = false;
bool bLeft = false;
bool bRight = false;
if (IsKey(EGC_STICK_SEMI)) iMagnitude = GCMapping[_numPAD].Pressure.Main;
if (IsKey(EGC_STICK_UP)) bUp = true;
else if (IsKey(EGC_STICK_DOWN)) bDown = true;
if (IsKey(EGC_STICK_LEFT)) bLeft = true;
else if (IsKey(EGC_STICK_RIGHT)) bRight = true;
EmulateAnalogStick(_pPADStatus->stickX, _pPADStatus->stickY, bUp, bDown, bLeft, bRight, iMagnitude);
}
else if (GCMapping[_numPAD].Stick.Main == FROM_ANALOG1)
{
_pPADStatus->stickX = GCMapping[_numPAD].AxisState.Lx;
// Y-axis is inverted
_pPADStatus->stickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ly;
}
else if (GCMapping[_numPAD].Stick.Main == FROM_ANALOG2)
{
_pPADStatus->stickX = GCMapping[_numPAD].AxisState.Rx;
// Y-axis is inverted
_pPADStatus->stickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ry;
}
else
{
_pPADStatus->stickX = GCMapping[_numPAD].AxisState.Tl;
_pPADStatus->stickY = GCMapping[_numPAD].AxisState.Tr;
}
if (GCMapping[_numPAD].Stick.Sub == FROM_KEYBOARD)
{
int iMagnitude = DEF_STICK_FULL;
bool bUp = false;
bool bDown = false;
bool bLeft = false;
bool bRight = false;
if (IsKey(EGC_CSTICK_SEMI)) iMagnitude = GCMapping[_numPAD].Pressure.Sub;
if (IsKey(EGC_CSTICK_UP)) bUp = true;
else if (IsKey(EGC_CSTICK_DOWN)) bDown = true;
if (IsKey(EGC_CSTICK_LEFT)) bLeft = true;
else if (IsKey(EGC_CSTICK_RIGHT)) bRight = true;
EmulateAnalogStick(_pPADStatus->substickX, _pPADStatus->substickY, bUp, bDown, bLeft, bRight, iMagnitude);
}
else if (GCMapping[_numPAD].Stick.Sub == FROM_ANALOG1)
{
_pPADStatus->substickX = GCMapping[_numPAD].AxisState.Lx;
// Y-axis is inverted
_pPADStatus->substickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ly;
}
else if (GCMapping[_numPAD].Stick.Sub == FROM_ANALOG2)
{
_pPADStatus->substickX = GCMapping[_numPAD].AxisState.Rx;
// Y-axis is inverted
_pPADStatus->substickY = 0xFF - (u8)GCMapping[_numPAD].AxisState.Ry;
}
else
{
_pPADStatus->substickX = GCMapping[_numPAD].AxisState.Tl;
_pPADStatus->substickY = GCMapping[_numPAD].AxisState.Tr;
}
if (GCMapping[_numPAD].Stick.Shoulder == FROM_KEYBOARD)
{
if (IsKey(EGC_TGR_L))
{
_pPADStatus->triggerLeft = DEF_TRIGGER_FULL;
_pPADStatus->button |= PAD_TRIGGER_L;
}
else if (IsKey(EGC_TGR_SEMI_L))
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].Pressure.Shoulder;
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
}
if (IsKey(EGC_TGR_R))
{
_pPADStatus->triggerRight = DEF_TRIGGER_FULL;
_pPADStatus->button |= PAD_TRIGGER_R;
}
else if (IsKey(EGC_TGR_SEMI_R))
{
_pPADStatus->triggerRight = GCMapping[_numPAD].Pressure.Shoulder;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
}
else if (GCMapping[_numPAD].Stick.Shoulder == FROM_ANALOG1)
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].AxisState.Lx;
_pPADStatus->triggerRight = GCMapping[_numPAD].AxisState.Ly;
EmulateAnalogTrigger(_pPADStatus->triggerLeft, _pPADStatus->triggerRight);
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
else if (GCMapping[_numPAD].Stick.Shoulder == FROM_ANALOG2)
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].AxisState.Rx;
_pPADStatus->triggerRight = GCMapping[_numPAD].AxisState.Ry;
EmulateAnalogTrigger(_pPADStatus->triggerLeft, _pPADStatus->triggerRight);
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
else
{
_pPADStatus->triggerLeft = GCMapping[_numPAD].AxisState.Tl;
_pPADStatus->triggerRight = GCMapping[_numPAD].AxisState.Tr;
EmulateAnalogTrigger(_pPADStatus->triggerLeft, _pPADStatus->triggerRight);
if (_pPADStatus->triggerLeft > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_L;
if (_pPADStatus->triggerRight > DEF_TRIGGER_THRESHOLD)
_pPADStatus->button |= PAD_TRIGGER_R;
}
}
//******************************************************************************
// Supporting functions
//******************************************************************************
// for same displacement should be sqrt(2)/2 (in theory)
// 3/4 = 0.75 is a little faster than sqrt(2)/2 = 0.7071...
// In SMS, 17/20 = 0.85 is perfect; in WW, 7/10 = 0.70 is closer.
#define DIAGONAL_SCALE 0.70710678
void EmulateAnalogStick(unsigned char &stickX, unsigned char &stickY, bool buttonUp, bool buttonDown, bool buttonLeft, bool buttonRight, int magnitude)
{
int mainX = 0;
int mainY = 0;
if (buttonUp)
mainY = magnitude;
else if (buttonDown)
mainY = -magnitude;
if (buttonLeft)
mainX = -magnitude;
else if (buttonRight)
mainX = magnitude;
if ((mainX == 0) || (mainY == 0))
{
stickX += mainX;
stickY += mainY;
}
else
{
stickX += mainX * DIAGONAL_SCALE;
stickY += mainY * DIAGONAL_SCALE;
}
}
void EmulateAnalogTrigger(unsigned char &trL, unsigned char &trR)
{
if (GCMapping[g_ID].TriggerType == InputCommon::CTL_TRIGGER_SDL)
{
int triggerL = abs((int)trL - 0x80) * 2;
int triggerR = abs((int)trR - 0x80) * 2;
trL = (triggerL > 0xFF) ? 0xFF : triggerL;
trR = (triggerR > 0xFF) ? 0xFF : triggerR;
}
}
void Close_Devices()
{
PAD_RumbleClose();
if (SDL_WasInit(0))
{
for (int i = 0; i < NumPads; i++)
{
if (joyinfo.at(i).joy)
{
if(SDL_JoystickOpened(i))
{
INFO_LOG(WIIMOTE, "Shut down Joypad: %i", i);
SDL_JoystickClose(joyinfo.at(i).joy);
}
}
}
}
for (int i = 0; i < 4; i++)
GCMapping[i].joy = NULL;
// Clear the physical device info
joyinfo.clear();
NumPads = 0;
NumGoodPads = 0;
}
// Search for SDL devices
// ----------------
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
{
// Close opened devices first
Close_Devices();
bool success = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads);
if (_NumGoodPads == 0)
return false;
for (int i = 0; i < 4; i++)
{
if (_NumPads > GCMapping[i].ID)
if(joyinfo.at(GCMapping[i].ID).Good)
{
GCMapping[i].joy = joyinfo.at(GCMapping[i].ID).joy;
#ifdef _WIN32
XINPUT_STATE xstate;
DWORD xresult = XInputGetState(GCMapping[i].ID, &xstate);
if (xresult == ERROR_SUCCESS)
GCMapping[i].TriggerType = InputCommon::CTL_TRIGGER_XINPUT;
#endif
}
}
return success;
}
void GetAxisState(CONTROLLER_MAPPING_GC &_GCMapping)
{
// Update the gamepad status
SDL_JoystickUpdate();
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
_GCMapping.AxisState.Lx = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Lx);
_GCMapping.AxisState.Ly = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Ly);
_GCMapping.AxisState.Rx = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Rx);
_GCMapping.AxisState.Ry = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Ry);
// Update the analog trigger axis values
#ifdef _WIN32
if (_GCMapping.TriggerType == InputCommon::CTL_TRIGGER_SDL)
{
#endif
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
// We must also check that we are not asking for a negative axis number because SDL_JoystickGetAxis() has
// no good way of handling that
if ((_GCMapping.AxisMapping.Tl - 1000) >= 0)
_GCMapping.AxisState.Tl = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Tl - 1000);
if ((_GCMapping.AxisMapping.Tr - 1000) >= 0)
_GCMapping.AxisState.Tr = SDL_JoystickGetAxis(_GCMapping.joy, _GCMapping.AxisMapping.Tr - 1000);
#ifdef _WIN32
}
else
{
_GCMapping.AxisState.Tl = XInput::GetXI(_GCMapping.ID, _GCMapping.AxisMapping.Tl - 1000);
_GCMapping.AxisState.Tr = XInput::GetXI(_GCMapping.ID, _GCMapping.AxisMapping.Tr - 1000);
}
#endif
}
void UpdatePadState(CONTROLLER_MAPPING_GC &_GCiMapping)
{
// Return if we have no pads
if (NumGoodPads == 0) return;
GetAxisState(_GCiMapping);
int &Lx = _GCiMapping.AxisState.Lx;
int &Ly = _GCiMapping.AxisState.Ly;
int &Rx = _GCiMapping.AxisState.Rx;
int &Ry = _GCiMapping.AxisState.Ry;
int &Tl = _GCiMapping.AxisState.Tl;
int &Tr = _GCiMapping.AxisState.Tr;
// Check the circle to square option
if(_GCiMapping.bSquare2Circle)
{
InputCommon::Square2Circle(Lx, Ly, _GCiMapping.Diagonal, false);
InputCommon::Square2Circle(Rx, Ry, _GCiMapping.Diagonal, false);
}
// Dead zone adjustment
float DeadZoneLeft = (float)_GCiMapping.DeadZoneL / 100.0f;
float DeadZoneRight = (float)_GCiMapping.DeadZoneR / 100.0f;
if (InputCommon::IsDeadZone(DeadZoneLeft, Lx, Ly))
{
Lx = 0;
Ly = 0;
}
if (InputCommon::IsDeadZone(DeadZoneRight, Rx, Ry))
{
Rx = 0;
Ry = 0;
}
// Downsize the values from 0x8000 to 0x80
Lx = InputCommon::Pad_Convert(Lx);
Ly = InputCommon::Pad_Convert(Ly);
Rx = InputCommon::Pad_Convert(Rx);
Ry = InputCommon::Pad_Convert(Ry);
// The XInput range is already 0 to 0x80
if (_GCiMapping.TriggerType == InputCommon::CTL_TRIGGER_SDL)
{
Tl = InputCommon::Pad_Convert(Tl);
Tr = InputCommon::Pad_Convert(Tr);
}
}
// Multi System Input Status Check
bool IsKey(int Key)
{
int Ret = NULL;
int MapKey = GCMapping[g_ID].Button[Key];
#ifdef _WIN32
if (MapKey < 256)
{
Ret = GetAsyncKeyState(MapKey); // Keyboard (Windows)
#else
if (MapKey < 256 || MapKey > 0xf000)
{
Ret = KeyStatus[Key]; // Keyboard (Linux)
#endif
}
else if (MapKey < 0x1100)
{
Ret = SDL_JoystickGetButton(GCMapping[g_ID].joy, MapKey - 0x1000); // Pad button
}
else // Pad hat
{
u8 HatCode, HatKey;
HatCode = SDL_JoystickGetHat(GCMapping[g_ID].joy, (MapKey - 0x1100) / 0x0010);
HatKey = (MapKey - 0x1100) % 0x0010;
if (HatCode & HatKey)
Ret = HatKey;
}
return (Ret) ? true : false;
}
void ReadLinuxKeyboard()
{
#if defined(HAVE_X11) && HAVE_X11
XEvent E;
KeySym key;
// keyboard input
int num_events;
for (num_events = XPending(WMdisplay); num_events > 0; num_events--)
{
XNextEvent(WMdisplay, &E);
switch (E.type)
{
case KeyPress:
{
key = XLookupKeysym((XKeyEvent*)&E, 0);
if ((key >= XK_F1 && key <= XK_F9) ||
key == XK_Shift_L || key == XK_Shift_R ||
key == XK_Control_L || key == XK_Control_R || key == XK_Escape)
{
XPutBackEvent(WMdisplay, &E);
break;
}
for (int i = 0; i < LAST_CONSTANT; i++)
{
if (((int) key) == GCMapping[g_ID].Button[i])
KeyStatus[i] = true;
}
break;
}
case KeyRelease:
{
key = XLookupKeysym((XKeyEvent*)&E, 0);
if ((key >= XK_F1 && key <= XK_F9) ||
key == XK_Shift_L || key == XK_Shift_R ||
key == XK_Control_L || key == XK_Control_R || key == XK_Escape) {
XPutBackEvent(WMdisplay, &E);
break;
}
for (int i = 0; i < LAST_CONSTANT; i++)
{
if (((int) key) == GCMapping[g_ID].Button[i])
KeyStatus[i] = false;
}
break;
}
case ConfigureNotify:
case ClientMessage:
XPutBackEvent(WMdisplay, &E);
break;
default:
break;
}
}
#endif
}
// Check if Dolphin is in focus
// ----------------
bool IsFocus()
{
#ifdef _WIN32
HWND RenderingWindow = (g_PADInitialize) ? g_PADInitialize->hWnd : NULL;
HWND Parent = GetParent(RenderingWindow);
HWND TopLevel = GetParent(Parent);
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow)
return true;
else
return false;
#else
return true;
#endif
}