EXPERIMENTAL

Removed X event loops from GCPad and Wiimote plugins, and implemented an asynchronous check for keyboard and mouse buttons.
Also added an X event loop in core that handles events while the emulator is paused.  Prevents unexpected behavior from events that occur while the emulator is paused.
Now there is only one event loop running at a time (besides those hidden in SDL).
I will revert this commit if other devs are unhappy with it.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5048 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Glenn Rice 2010-02-13 20:47:23 +00:00
parent c63446827f
commit c2e0c75c93
12 changed files with 113 additions and 181 deletions

View File

@ -29,6 +29,11 @@
#include "MathUtil.h"
#include "MemoryUtil.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
#include <X11/keysym.h>
#endif
#include "Console.h"
#include "Core.h"
#include "CPUDetect.h"
@ -92,6 +97,9 @@ bool g_bStopping = false;
bool g_bHwInit = false;
bool g_bRealWiimote = false;
HWND g_pWindowHandle = NULL;
#if defined(HAVE_X11) && HAVE_X11
void *g_pXWindow = NULL;
#endif
Common::Thread* g_EmuThread = NULL;
SCoreStartupParameter g_CoreStartupParameter;
@ -234,7 +242,45 @@ void Stop() // - Hammertime!
g_EmuThread = 0;
}
#if defined(HAVE_X11) && HAVE_X11
void ProcessXEvents(void)
{
if (GetState() == CORE_PAUSE)
{
Display *dpy = (Display *)g_pWindowHandle;
XEvent event;
KeySym key;
int num_events;
for (num_events = XPending(dpy);num_events > 0;num_events--)
{
XNextEvent(dpy, &event);
switch(event.type) {
case KeyRelease:
key = XLookupKeysym((XKeyEvent*)&event, 0);
if(key == XK_F4 && ((event.xkey.state & Mod1Mask) == Mod1Mask))
Host_Message(WM_USER_STOP);
break;
case ClientMessage:
if ((ulong) event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
Host_Message(WM_USER_STOP);
break;
default:
break;
}
}
}
}
THREAD_RETURN XEventThread(void *pArg)
{
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{
ProcessXEvents();
Common::SleepCurrentThread(200);
}
return 0;
}
#endif
// Create the CPU thread. which would be a CPU + Video thread in Single Core mode.
@ -330,6 +376,9 @@ THREAD_RETURN EmuThread(void *pArg)
// Under linux, this is an X11 Display, not a HWND!
g_pWindowHandle = (HWND)VideoInitialize.pWindowHandle;
#if defined(HAVE_X11) && HAVE_X11
g_pXWindow = (Window *)VideoInitialize.pXWindow;
#endif
Callback_PeekMessages = VideoInitialize.pPeekMessages;
g_pUpdateFPSDisplay = VideoInitialize.pUpdateFPSDisplay;
@ -352,6 +401,7 @@ THREAD_RETURN EmuThread(void *pArg)
Plugins.GetDSP()->Initialize((void *)&dspInit);
// Load and init GCPadPlugin
SPADInitialize PADInitialize;
PADInitialize.hWnd = g_pWindowHandle;
PADInitialize.pLog = Callback_PADLog;
@ -364,6 +414,9 @@ THREAD_RETURN EmuThread(void *pArg)
{
SWiimoteInitialize WiimoteInitialize;
WiimoteInitialize.hWnd = g_pWindowHandle;
#if defined(HAVE_X11) && HAVE_X11
WiimoteInitialize.pXWindow = g_pXWindow;
#endif
WiimoteInitialize.ISOId = Ascii2Hex(_CoreParameter.m_strUniqueID);
WiimoteInitialize.pLog = Callback_WiimoteLog;
WiimoteInitialize.pWiimoteInput = Callback_WiimoteInput;
@ -392,6 +445,9 @@ THREAD_RETURN EmuThread(void *pArg)
// Spawn the CPU thread
Common::Thread *cpuThread = NULL;
#if defined(HAVE_X11) && HAVE_X11
Common::Thread *xEventThread = NULL;
#endif
// ENTER THE VIDEO THREAD LOOP
if (_CoreParameter.bCPUThread)
@ -401,6 +457,9 @@ THREAD_RETURN EmuThread(void *pArg)
Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
cpuThread = new Common::Thread(CpuThread, pArg);
#if defined(HAVE_X11) && HAVE_X11
xEventThread = new Common::Thread(XEventThread, pArg);
#endif
Common::SetCurrentThreadName("Video thread");
if (g_pUpdateFPSDisplay != NULL)
@ -435,6 +494,9 @@ THREAD_RETURN EmuThread(void *pArg)
{
if (Callback_PeekMessages)
Callback_PeekMessages();
#if defined(HAVE_X11) && HAVE_X11
ProcessXEvents();
#endif
Common::SleepCurrentThread(20);
}

View File

@ -70,6 +70,9 @@ typedef struct
typedef struct
{
void *pWindowHandle;
#if defined(HAVE_X11) && HAVE_X11
void *pXWindow;
#endif
TSetInterrupt pSetInterrupt;
TRegisterEvent pRegisterEvent;

View File

@ -19,6 +19,9 @@ typedef void (*TWiimoteInput)(int _number, u16 _channelID, const void* _pData, u
typedef struct
{
HWND hWnd;
#ifdef __linux__
void *pXWindow;
#endif
u32 ISOId;
TLogv pLog;
TWiimoteInput pWiimoteInput;

View File

@ -46,7 +46,6 @@
// Variables
// ---------
bool KeyStatus[LAST_CONSTANT];
bool g_SearchDeviceDone = false;
CONTROLLER_MAPPING_GC GCMapping[4];
std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
@ -55,7 +54,7 @@ int NumPads = 0, NumGoodPads = 0, g_ID = 0;
HWND m_hWnd = NULL; // Handle to window
#endif
#if defined(HAVE_X11) && HAVE_X11
Display* WMdisplay;
Display* GCdisplay;
#endif
SPADInitialize *g_PADInitialize = NULL;
PLUGIN_GLOBALS* globals = NULL;
@ -194,7 +193,7 @@ void Initialize(void *init)
m_hWnd = (HWND)g_PADInitialize->hWnd;
#endif
#if defined(HAVE_X11) && HAVE_X11
WMdisplay = (Display*)g_PADInitialize->hWnd;
GCdisplay = (Display*)g_PADInitialize->hWnd;
#endif
if (!g_SearchDeviceDone)
@ -268,7 +267,6 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
g_ID = _numPAD;
ReadLinuxKeyboard();
if (NumGoodPads && NumPads > GCMapping[_numPAD].ID)
UpdatePadState(GCMapping[_numPAD]);
@ -611,7 +609,11 @@ bool IsKey(int Key)
#else
if (MapKey < 256 || MapKey > 0xf000)
{
Ret = KeyStatus[Key]; // Keyboard (Linux)
char keys[32];
KeyCode keyCode;
XQueryKeymap(GCdisplay, keys);
keyCode = XKeysymToKeycode(GCdisplay, MapKey);
Ret = (keys[keyCode/8] & (1 << (keyCode%8))); // Keyboard (Linux)
#endif
}
else if (MapKey < 0x1100)
@ -631,67 +633,6 @@ bool IsKey(int Key)
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()

View File

@ -161,7 +161,6 @@ bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_N
void GetAxisState(CONTROLLER_MAPPING_GC &_GCMapping);
void UpdatePadState(CONTROLLER_MAPPING_GC &_GCMapping);
bool IsKey(int Key);
void ReadLinuxKeyboard();
bool IsFocus();
bool ReloadDLL();
void PAD_RumbleClose();

View File

@ -402,6 +402,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
"GPU", None, NULL, 0, NULL);
XMapRaised(GLWin.dpy, GLWin.win);
}
g_VideoInitialize.pXWindow = (Window *) &GLWin.win;
if (g_Config.bHideCursor)
{
// make a blank cursor
@ -475,8 +476,8 @@ bool OpenGL_MakeCurrent()
}
// better for pad plugin key input (thc)
XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask |
FocusChangeMask );
XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | KeyReleaseMask |
StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask );
#endif
return true;
}
@ -529,7 +530,6 @@ void OpenGL_Update()
// We just check all of our events here
XEvent event;
KeySym key;
static RECT rcWindow;
static bool ShiftPressed = false;
static bool ControlPressed = false;
static int FKeyPressed = -1;
@ -539,7 +539,7 @@ void OpenGL_Update()
switch(event.type) {
case KeyRelease:
key = XLookupKeysym((XKeyEvent*)&event, 0);
if((key >= XK_F1 && key <= XK_F9) || (key == XK_Escape)) {
if(key >= XK_F1 && key <= XK_F9) {
g_VideoInitialize.pKeyPress(FKeyPressed, ShiftPressed, ControlPressed);
FKeyPressed = -1;
} else {
@ -547,8 +547,6 @@ void OpenGL_Update()
ShiftPressed = false;
else if(key == XK_Control_L || key == XK_Control_R)
ControlPressed = false;
else
XPutBackEvent(GLWin.dpy, &event);
}
break;
case KeyPress:
@ -576,13 +574,10 @@ void OpenGL_Update()
ShiftPressed = true;
else if(key == XK_Control_L || key == XK_Control_R)
ControlPressed = true;
else
XPutBackEvent(GLWin.dpy, &event);
}
break;
case ButtonPress:
case ButtonRelease:
XPutBackEvent(GLWin.dpy, &event);
break;
case ConfigureNotify:
Window winDummy;
@ -591,10 +586,6 @@ void OpenGL_Update()
&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
s_backbuffer_width = GLWin.width;
s_backbuffer_height = GLWin.height;
rcWindow.left = 0;
rcWindow.top = 0;
rcWindow.right = GLWin.width;
rcWindow.bottom = GLWin.height;
break;
case ClientMessage:
if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))

View File

@ -348,6 +348,9 @@ void Initialize(void *init)
// Now the window handle is written
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
#if defined(HAVE_X11) && HAVE_X11
_pVideoInitialize->pXWindow = g_VideoInitialize.pXWindow;
#endif
OSD::AddMessage("Dolphin OpenGL Video Plugin" ,5000);
}

View File

@ -61,9 +61,6 @@ int NumPads = 0, NumGoodPads = 0; // Number of goods pads
std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
CONTROLLER_MAPPING_WII WiiMapping[MAX_WIIMOTES];
// Keyboard input
bool KeyStatus[LAST_CONSTANT];
} // namespace
#endif //_EMU_DECLARATIONS_

View File

@ -307,7 +307,6 @@ struct CONTROLLER_MAPPING_WII // WII PAD MAPPING
extern int NumPads, NumGoodPads; // Number of goods pads
extern std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
extern CONTROLLER_MAPPING_WII WiiMapping[4];
extern bool KeyStatus[64];
} // namespace

View File

@ -196,10 +196,6 @@ void LoadRecordedMovements()
}
}
#if defined(HAVE_X11) && HAVE_X11
Window GLWin;
#endif
/* Calibrate the mouse position to the emulation window. g_WiimoteInitialize.hWnd is the rendering window handle. */
void GetMousePos(float& x, float& y)
{
@ -223,6 +219,7 @@ void GetMousePos(float& x, float& y)
float WinWidth = 0, WinHeight = 0;
float XOffset = 0, YOffset = 0;
int root_x, root_y, win_x, win_y;
Window GLWin = *(Window *)g_WiimoteInitialize.pXWindow;
if (GLWin != 0)
{
XWindowAttributes WinAttribs;
@ -643,8 +640,6 @@ void Update(int _number)
// Read input or not
if (WiiMapping[g_ID].Source == 1)
{
ReadLinuxKeyboard();
// Check if the pad state should be updated
if (NumGoodPads > 0 && joyinfo.size() > (u32)WiiMapping[g_ID].ID)
UpdatePadState(WiiMapping[g_ID]);
@ -672,89 +667,4 @@ void Update(int _number)
}
}
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);
GLWin = E.xany.window;
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) == WiiMapping[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) == WiiMapping[g_ID].Button[i])
KeyStatus[i] = false;
}
break;
}
case ButtonPress:
{
int button = ((XButtonEvent*)&E)->button;
if (button == 1)
KeyStatus[EWM_A] = true;
else if (button == 3)
KeyStatus[EWM_B] = true;
else
XPutBackEvent(WMdisplay, &E);
break;
}
case ButtonRelease:
{
int button = ((XButtonEvent*)&E)->button;
if (button == 1)
KeyStatus[EWM_A] = false;
else if (button == 3)
KeyStatus[EWM_B] = false;
else
XPutBackEvent(WMdisplay, &E);
break;
}
case ConfigureNotify:
case ClientMessage:
XPutBackEvent(WMdisplay, &E);
break;
default:
break;
}
}
#endif
}
} // end of namespace

View File

@ -42,7 +42,7 @@ void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size
void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) ;
void Update(int _number);
void DoState(PointerWrap &p);
void ReadLinuxKeyboard();
//void ReadLinuxKeyboard();
bool IsKey(int Key);
// Recordings

View File

@ -297,7 +297,7 @@ int RecordingCheckKeys(int WmNuIr)
// Multi System Input Status Check
bool IsKey(int Key)
{
int Ret = NULL;
int Ret = false;
if (WiiMapping[g_ID].Source == 1)
{
@ -310,7 +310,11 @@ bool IsKey(int Key)
#else
if (MapKey < 256 || MapKey >= 0xf000)
{
Ret = KeyStatus[Key]; // Keyboard (Linux)
char keys[32];
KeyCode keyCode;
XQueryKeymap(WMdisplay, keys);
keyCode = XKeysymToKeycode(WMdisplay, MapKey);
Ret = (keys[keyCode/8] & (1 << (keyCode%8))); // Keyboard (Linux)
#endif
}
else if (MapKey < 0x1100)
@ -337,8 +341,28 @@ bool IsKey(int Key)
Ret = !(x < 0 || x > 1 || y < 0 || y > 1);
}
#endif
}
#if defined(HAVE_X11) && HAVE_X11
if ((Key == EWM_SHAKE) || (Key == EWM_A) || (Key == EWM_B))
{
Window GLWin = *(Window *)g_WiimoteInitialize.pXWindow;
if (GLWin != 0)
{
int root_x, root_y, win_x, win_y;
Window rootDummy, childWin;
unsigned int mask;
XQueryPointer(WMdisplay, GLWin, &rootDummy, &childWin, &root_x, &root_y, &win_x, &win_y, &mask);
if (((Key == EWM_A) && (mask & Button1Mask))
|| ((Key == EWM_B) && (mask & Button3Mask))
|| ((Key == EWM_SHAKE) && (mask & Button3Mask)))
{
float x, y;
GetMousePos(x, y);
Ret = !(x < 0 || x > 1 || y < 0 || y > 1);
}
}
}
#endif
}
return (Ret) ? true : false;
}