Soren Jorvang 5c335a8c85 Fixed WXKeyToString which had several problems, mostly just to get
hotkey configuration working with wx 2.9, but it turned out to be
too tempting to use it to hack up OS X keyboard support using wx
key events in the "old" input plugins.

It was with some reluctance that I used PAD_Input (and copied it
for Wiimote as well) as that is clearly a deprecated interface,
but this way the hack is contained within the old plugins for when
the switchover to ControllerInterface happens.

The idea is to provide stable keyboard support on OS X for both
GCPad and Wiimote while we debug HID keyboard and real 'mote code.

It works pretty well, although the wx approach does impose a few
limitations like no arrow keys and left/right side modifier keys
are considered equivalent.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5622 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-06-05 19:03:37 +00:00

355 lines
9.1 KiB
C++

#include "Common.h"
#include "pluginspecs_wiimote.h"
#include "ControllerInterface/ControllerInterface.h"
#include "WiimoteEmu/WiimoteEmu.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDiag.h"
#endif
#include "../../InputPluginCommon/Src/Config.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
#if defined(HAVE_WX) && HAVE_WX
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#endif
#endif
#define PLUGIN_VERSION 0x0100
#define PLUGIN_NAME "Dolphin Wiimote New Incomplete"
#ifdef DEBUGFAST
#define PLUGIN_FULL_NAME PLUGIN_NAME" (DebugFast)"
#else
#ifdef _DEBUG
#define PLUGIN_FULL_NAME PLUGIN_NAME" (Debug)"
#else
#define PLUGIN_FULL_NAME PLUGIN_NAME
#endif
#endif
// plugin globals
static Plugin g_plugin( "WiimoteNew", "Wiimote", "Wiimote" );
SWiimoteInitialize g_WiimoteInitialize;
#ifdef _WIN32
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
};
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
// copied from GCPad
HINSTANCE g_hInstance;
// copied from GCPad
#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
// /
#ifdef _WIN32
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
wxSetInstance(hinstDLL);
wxInitialize();
break;
case DLL_PROCESS_DETACH:
wxUninitialize();
break;
default:
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
#endif
void DeInitPlugin()
{
if ( g_plugin.controller_interface.IsInit() )
{
std::vector<ControllerEmu*>::const_iterator
i = g_plugin.controllers.begin(),
e = g_plugin.controllers.end();
for ( ; i!=e; ++i )
delete *i;
g_plugin.controllers.clear();
g_plugin.controller_interface.DeInit();
}
}
// if plugin isn't initialized, init and load config
void InitPlugin( void* const hwnd )
{
if ( false == g_plugin.controller_interface.IsInit() )
{
// add 4 wiimotes
for ( unsigned int i = 0; i<4; ++i )
g_plugin.controllers.push_back( new WiimoteEmu::Wiimote(i) );
// load the saved controller config
g_plugin.LoadConfig();
// needed for Xlib and exclusive dinput
g_plugin.controller_interface.SetHwnd( hwnd );
g_plugin.controller_interface.Init();
// update control refs
std::vector<ControllerEmu*>::const_iterator i = g_plugin.controllers.begin(),
e = g_plugin.controllers.end();
for ( ; i!=e; ++i )
(*i)->UpdateReferences( g_plugin.controller_interface );
}
}
// I N T E R F A C E
// __________________________________________________________________________________________________
// Function: Wiimote_Output
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
// on the HID CONTROL channel.
// input: Da pakket.
// output: none
//
void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
{
//PanicAlert( "Wiimote_ControlChannel" );
((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->ControlChannel( _channelID, _pData, _Size );
}
// __________________________________________________________________________________________________
// Function: Send keyboard input to the plugin
// Purpose:
// input: The key and if it's pressed or released
// output: None
//
void Wiimote_Input(u16 _Key, u8 _UpDown)
{
return;
}
// __________________________________________________________________________________________________
// Function: Wiimote_InterruptChannel
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
// on the HID INTERRUPT channel.
// input: Da pakket.
// output: none
//
void Wiimote_InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
{
//PanicAlert( "Wiimote_InterruptChannel" );
((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->InterruptChannel( _channelID, _pData, _Size );
}
// __________________________________________________________________________________________________
// Function: Wiimote_Update
// Purpose: This function is called periodically by the Core.
// input: none
// output: none
//
void Wiimote_Update(int _number)
{
//PanicAlert( "Wiimote_Update" );
// TODO: change this to a TryEnter, and make it give empty input on failure
g_plugin.controls_crit.Enter();
static int _last_number = 4;
if ( _number <= _last_number && g_plugin.interface_crit.TryEnter() )
{
g_plugin.controller_interface.UpdateOutput();
g_plugin.controller_interface.UpdateInput();
g_plugin.interface_crit.Leave();
}
_last_number = _number;
((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->Update();
g_plugin.controls_crit.Leave();
}
// __________________________________________________________________________________________________
// Function: PAD_GetAttachedPads
// Purpose: Get mask of attached pads (eg: controller 1 & 4 -> 0x9)
// input: none
// output: number of pads
//
unsigned int Wiimote_GetAttachedControllers()
{
unsigned int attached = 0;
for (unsigned int i=0; i<4; ++i)
if (g_plugin.controllers[i]->default_device.ToString().length())
attached |= (1 << i);
return attached;
}
// GLOBAL I N T E R F A C E
// Function: GetDllInfo
// Purpose: This function allows the emulator to gather information
// about the DLL by filling in the PluginInfo structure.
// input: A pointer to a PLUGIN_INFO structure that needs to be
// filled by the function. (see def above)
// output: none
//
void GetDllInfo(PLUGIN_INFO* _pPluginInfo)
{
// don't feel like messing around with all those strcpy functions and warnings
//char *s1 = CIFACE_PLUGIN_FULL_NAME, *s2 = _pPluginInfo->Name;
//while ( *s2++ = *s1++ );
memcpy( _pPluginInfo->Name, PLUGIN_FULL_NAME, sizeof(PLUGIN_FULL_NAME) );
_pPluginInfo->Type = PLUGIN_TYPE_WIIMOTE;
_pPluginInfo->Version = PLUGIN_VERSION;
}
// ___________________________________________________________________________
// Function: DllConfig
// Purpose: This function is optional function that is provided
// to allow the user to configure the DLL
// input: A handle to the window that calls this function
// output: none
//
void DllConfig(HWND _hParent)
{
#if defined(HAVE_WX) && HAVE_WX
bool was_init = false;
if ( g_plugin.controller_interface.IsInit() ) // hack for showing dialog when game isnt running
was_init = true;
else
{
#if defined(HAVE_X11) && HAVE_X11
Window win = GDK_WINDOW_XID(GTK_WIDGET(_hParent)->window);
g_WiimoteInitialize.hWnd = GDK_WINDOW_XDISPLAY(GTK_WIDGET(_hParent)->window);
g_WiimoteInitialize.pXWindow = &win;
InitPlugin(g_WiimoteInitialize.hWnd);
#else
InitPlugin(_hParent);
#endif
}
// copied from GCPad
wxWindow *frame = GetParentedWxWindow(_hParent);
ConfigDialog* m_ConfigFrame = new ConfigDialog( frame, g_plugin, PLUGIN_FULL_NAME, was_init );
#ifdef _WIN32
frame->Disable();
m_ConfigFrame->ShowModal();
frame->Enable();
#else
m_ConfigFrame->ShowModal();
#endif
#ifdef _WIN32
wxMilliSleep( 50 ); // hooray for hacks
frame->SetFocus();
frame->SetHWND(NULL);
#endif
m_ConfigFrame->Destroy();
m_ConfigFrame = NULL;
frame->Destroy();
// /
if ( false == was_init ) // hack for showing dialog when game isnt running
DeInitPlugin();
#endif
}
// ___________________________________________________________________________
// Function: DllDebugger
// Purpose: Open the debugger
// input: a handle to the window that calls this function
// output: none
//
void DllDebugger(HWND _hParent, bool Show)
{
// wut?
}
// ___________________________________________________________________________
// Function: DllSetGlobals
// Purpose: Set the pointer for globals variables
// input: a pointer to the global struct
// output: none
//
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
{
// wut?
}
// ___________________________________________________________________________
// Function: Initialize
// Purpose: Initialize the plugin
// input: Init
// output: none
//
void Initialize(void *init)
{
g_WiimoteInitialize = *(SWiimoteInitialize*)init;
if ( false == g_plugin.controller_interface.IsInit() )
InitPlugin( g_WiimoteInitialize.hWnd );
}
// ___________________________________________________________________________
// Function: Shutdown
// Purpose: This function is called when the emulator is shutting down
// a game allowing the dll to de-initialise.
// input: none
// output: none
//
void Shutdown(void)
{
if ( g_plugin.controller_interface.IsInit() )
DeInitPlugin();
}
// ___________________________________________________________________________
// Function: DoState
// Purpose: Saves/load state
// input/output: ptr
// input: mode
//
void DoState(unsigned char **ptr, int mode)
{
PointerWrap p(ptr, mode);
for (unsigned int i=0; i<4; ++i)
((WiimoteEmu::Wiimote*)g_plugin.controllers[i])->DoState(p);
}
// ___________________________________________________________________________
// Function: EmuStateChange
// Purpose: Notifies the plugin of a change in emulation state
// input: newState
// output: none
//
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
// maybe use this later
}