From c2e0c75c93cca4b835e194d59b66a8bb705796be Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Sat, 13 Feb 2010 20:47:23 +0000 Subject: [PATCH] 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 --- Source/Core/Core/Src/Core.cpp | 64 ++++++++++++- Source/PluginSpecs/pluginspecs_video.h | 3 + Source/PluginSpecs/pluginspecs_wiimote.h | 3 + Source/Plugins/Plugin_GCPad/Src/GCPad.cpp | 73 ++------------- Source/Plugins/Plugin_GCPad/Src/GCPad.h | 1 - Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 17 +--- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 3 + .../Plugin_Wiimote/Src/EmuDefinitions.cpp | 3 - .../Plugin_Wiimote/Src/EmuDefinitions.h | 1 - Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp | 92 +------------------ Source/Plugins/Plugin_Wiimote/Src/EmuMain.h | 2 +- .../Plugins/Plugin_Wiimote/Src/FillReport.cpp | 32 ++++++- 12 files changed, 113 insertions(+), 181 deletions(-) diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 853a90a14b..9c7192f8ea 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -29,6 +29,11 @@ #include "MathUtil.h" #include "MemoryUtil.h" +#if defined(HAVE_X11) && HAVE_X11 +#include +#include +#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); } diff --git a/Source/PluginSpecs/pluginspecs_video.h b/Source/PluginSpecs/pluginspecs_video.h index e7c08c423b..4b7e282758 100644 --- a/Source/PluginSpecs/pluginspecs_video.h +++ b/Source/PluginSpecs/pluginspecs_video.h @@ -70,6 +70,9 @@ typedef struct typedef struct { void *pWindowHandle; +#if defined(HAVE_X11) && HAVE_X11 + void *pXWindow; +#endif TSetInterrupt pSetInterrupt; TRegisterEvent pRegisterEvent; diff --git a/Source/PluginSpecs/pluginspecs_wiimote.h b/Source/PluginSpecs/pluginspecs_wiimote.h index fe173ae000..ad9e2255cd 100644 --- a/Source/PluginSpecs/pluginspecs_wiimote.h +++ b/Source/PluginSpecs/pluginspecs_wiimote.h @@ -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; diff --git a/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp b/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp index 177d1129eb..77efbd905b 100644 --- a/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp +++ b/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp @@ -46,7 +46,6 @@ // Variables // --------- -bool KeyStatus[LAST_CONSTANT]; bool g_SearchDeviceDone = false; CONTROLLER_MAPPING_GC GCMapping[4]; std::vector 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() diff --git a/Source/Plugins/Plugin_GCPad/Src/GCPad.h b/Source/Plugins/Plugin_GCPad/Src/GCPad.h index da05c02c51..d56e5d4353 100644 --- a/Source/Plugins/Plugin_GCPad/Src/GCPad.h +++ b/Source/Plugins/Plugin_GCPad/Src/GCPad.h @@ -161,7 +161,6 @@ bool Search_Devices(std::vector &_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(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 4508debee7..504e4d0433 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -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)) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index ce900d9472..3c5417eb30 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -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); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index 615e691627..8792346ad4 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -61,9 +61,6 @@ int NumPads = 0, NumGoodPads = 0; // Number of goods pads std::vector joyinfo; CONTROLLER_MAPPING_WII WiiMapping[MAX_WIIMOTES]; -// Keyboard input -bool KeyStatus[LAST_CONSTANT]; - } // namespace #endif //_EMU_DECLARATIONS_ diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index 64709be80e..d6758a8fe2 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -307,7 +307,6 @@ struct CONTROLLER_MAPPING_WII // WII PAD MAPPING extern int NumPads, NumGoodPads; // Number of goods pads extern std::vector joyinfo; extern CONTROLLER_MAPPING_WII WiiMapping[4]; -extern bool KeyStatus[64]; } // namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 82d915d8b1..3965edf715 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h index feb7542c43..1fa17bdbf2 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 54759279cc..2249219686 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -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; }