From 2015d252f02f422cd92c10c2a0aad4417ca2656e Mon Sep 17 00:00:00 2001
From: Glenn Rice <glennricster@gmail.com>
Date: Mon, 15 Mar 2010 23:25:11 +0000
Subject: [PATCH] Rewrite of fullscreen toggling in linux.  This goes back to
 using the EWMH specifications.  I wasn't using it right before, but now it
 should work on all EWMH compliant window managers (like KDE, Metacity,
 Compiz, etc).  Since this doesn't need an override redirect Alt-Tab works
 even in fullscreen mode.  This also allows for some other nice things to be
 done.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5199 8ced0084-cf51-0410-be5f-012b33b47a6e
---
 Source/Core/Core/Src/Core.cpp                 |  71 +--
 Source/Core/DolphinWX/Src/Frame.cpp           | 110 +++--
 Source/Core/DolphinWX/Src/Frame.h             |   3 +
 Source/Core/DolphinWX/Src/FrameTools.cpp      |  21 +-
 Source/Core/DolphinWX/Src/Main.cpp            |   2 +
 Source/PluginSpecs/pluginspecs_pad.h          |   3 +
 Source/PluginSpecs/pluginspecs_video.h        |   3 +
 Source/PluginSpecs/pluginspecs_wiimote.h      |   3 +
 Source/Plugins/Plugin_GCPad/Src/GCPad.cpp     |   8 +-
 Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 427 ++++++++++--------
 Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h   |  28 +-
 Source/Plugins/Plugin_Wiimote/Src/main.cpp    |   8 +-
 12 files changed, 387 insertions(+), 300 deletions(-)

diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index 7abb4612fd..45333463f5 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -29,11 +29,6 @@
 #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"
@@ -252,47 +247,6 @@ 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 KeyPress:
-					key = XLookupKeysym((XKeyEvent*)&event, 0);
-					if (key == XK_Escape)
-						Host_Message(WM_USER_PAUSE);
-				case ClientMessage:
-					if ((ulong) event.xclient.data.l[0] == XInternAtom(dpy, "WM_DELETE_WINDOW", False))
-						Host_Message(WM_USER_STOP);
-					if ((ulong) event.xclient.data.l[0] == XInternAtom(dpy, "WINDOW_REFOCUS", False))
-						XSetInputFocus(dpy, *(Window *)g_pXWindow, RevertToPointerRoot, CurrentTime);
-					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.
 
 THREAD_RETURN CpuThread(void *pArg)
@@ -368,6 +322,9 @@ THREAD_RETURN EmuThread(void *pArg)
 	VideoInitialize.pScheduleEvent_Threadsafe   = CoreTiming::ScheduleEvent_Threadsafe;
 	// This is first the m_Panel handle, then it is updated to have the new window handle
 	VideoInitialize.pWindowHandle		        = _CoreParameter.hMainWindow;
+#if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2
+	VideoInitialize.pPanel				        = _CoreParameter.hMainWindow;
+#endif
 	VideoInitialize.pLog				        = Callback_VideoLog;
 	VideoInitialize.pSysMessage			        = Host_SysMessage;
 	VideoInitialize.pRequestWindowSize	        = NULL; //Callback_VideoRequestWindowSize;
@@ -388,7 +345,7 @@ 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;
+	g_pXWindow					= (void *)VideoInitialize.pXWindow;
 #endif
 	Callback_PeekMessages	= VideoInitialize.pPeekMessages;
 	g_pUpdateFPSDisplay		= VideoInitialize.pUpdateFPSDisplay;
@@ -417,6 +374,9 @@ THREAD_RETURN EmuThread(void *pArg)
 	PADInitialize.hWnd		= g_pWindowHandle;
 #if defined(HAVE_X11) && HAVE_X11
 	PADInitialize.pXWindow	= g_pXWindow;
+#if defined(HAVE_GTK2) && HAVE_GTK2
+	PADInitialize.pPanel	= VideoInitialize.pPanel;
+#endif
 #endif
 	PADInitialize.pLog		= Callback_PADLog;
 	// This is may be needed to avoid a SDL problem
@@ -429,6 +389,9 @@ THREAD_RETURN EmuThread(void *pArg)
 		SWiimoteInitialize WiimoteInitialize;
 		WiimoteInitialize.hWnd			= g_pWindowHandle;
 #if defined(HAVE_X11) && HAVE_X11
+#if defined(HAVE_GTK2) && HAVE_GTK2
+		WiimoteInitialize.pPanel	= VideoInitialize.pPanel;
+#endif
 		WiimoteInitialize.pXWindow	= g_pXWindow;
 #endif
 		WiimoteInitialize.ISOId			= Ascii2Hex(_CoreParameter.m_strUniqueID);
@@ -459,10 +422,6 @@ 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)
 	{
@@ -471,9 +430,6 @@ 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)
@@ -508,9 +464,6 @@ THREAD_RETURN EmuThread(void *pArg)
 		{
 			if (Callback_PeekMessages)
 				Callback_PeekMessages();
-#if defined(HAVE_X11) && HAVE_X11
-			ProcessXEvents();
-#endif
 			Common::SleepCurrentThread(20);
 		}
 
@@ -817,11 +770,15 @@ void Callback_KeyPress(int key, bool shift, bool control)
 			State_UndoLoadState();	
 	}
 #if defined(HAVE_X11) && HAVE_X11
+	if (key == 0) 
+		Host_Message(WM_USER_CREATE);
 	// 0x1b == VK_ESCAPE
 	if (key == 0x1b) 
 		Host_Message(WM_USER_STOP);
 	if (key == 0x1c)
 		Host_Message(WM_USER_PAUSE);
+	if (key == 0x1d)
+		Host_Message(TOGGLE_FULLSCREEN);
 #endif
 }
 
diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp
index ea38e45bfa..333c5d4f46 100644
--- a/Source/Core/DolphinWX/Src/Frame.cpp
+++ b/Source/Core/DolphinWX/Src/Frame.cpp
@@ -523,7 +523,7 @@ void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event))
 }
 
 #if defined HAVE_X11 && HAVE_X11
-void X11_SendEvent(const char *message)
+void CFrame::X11_SendClientEvent(const char *message)
 {
 	XEvent event;
 	Display *dpy = (Display *)Core::GetWindowHandle();
@@ -536,9 +536,24 @@ void X11_SendEvent(const char *message)
 
 	// Send the event
 	if (!XSendEvent(dpy, win, False, False, &event))
-	{
 		ERROR_LOG(VIDEO, "Failed to send message %s to the emulator window.\n", message);
-	}
+}
+
+void X11_SendKeyEvent(int key)
+{
+	XEvent event;
+	Display *dpy = (Display *)Core::GetWindowHandle();
+	Window win = *(Window *)Core::GetXWindow();
+
+	// Init X event structure for key press event
+	event.xkey.type = KeyPress;
+	// WARNING:  This works for '3' to '7'.  If in the future other keys are needed
+	// convert with InputCommon::wxCharCodeWXToX from X11InputBase.cpp.
+	event.xkey.keycode = XKeysymToKeycode(dpy, key);
+
+	// Send the event
+	if (!XSendEvent(dpy, win, False, False, &event))
+		ERROR_LOG(VIDEO, "Failed to send key press event to the emulator window.\n");
 }
 #endif
 
@@ -547,8 +562,13 @@ void X11_SendEvent(const char *message)
 void CFrame::OnActive(wxActivateEvent& event)
 {
 #if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
-	if (event.GetActive() && (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE))
-		X11_SendEvent("WINDOW_REFOCUS");
+	if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
+	{
+		if (event.GetActive())
+			X11_SendClientEvent("FOCUSIN");
+		else
+			X11_SendClientEvent("FOCUSOUT");
+	}
 #endif
 	event.Skip();
 }
@@ -618,7 +638,7 @@ void CFrame::OnResizeAll(wxSizeEvent& event)
 	event.Skip();
 #if defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
 	if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE)
-		X11_SendEvent("MAIN_RESIZED");
+		X11_SendClientEvent("RESIZE");
 #endif
 	//wxWindow * Win = (wxWindow*)event.GetEventObject();
 	//NOTICE_LOG(CONSOLE, "OnResizeAll: %i", (HWND)Win->GetHWND());
@@ -675,11 +695,17 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
 		}
 		break;
 #if defined(HAVE_X11) && HAVE_X11
+	case WM_USER_CREATE:
+		bRenderToMain = true;
+		break;
+	case TOGGLE_FULLSCREEN:
+		DoFullscreen(!IsFullScreen());
+		break;
 	case WM_USER_STOP:
-		main_frame->DoStop();
+		DoStop();
 		break;
 	case WM_USER_PAUSE:
-		main_frame->DoPause();
+		DoPause();
 		break;
 #endif
 	}
@@ -787,8 +813,14 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
 	{
 		PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode());
 	}
+#elif defined(HAVE_X11) && HAVE_X11 && defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+	if (event.GetKeyCode() >= '3' && event.GetKeyCode() <= '7') // Send this to the video plugin
+	{
+		X11_SendKeyEvent(event.GetKeyCode());
+	}
 #endif
 
+
 	// Send the keyboard status to the Input plugin
 	if(Core::GetState() != Core::CORE_UNINITIALIZED)
 	    CPluginManager::GetInstance().GetPad(0)->PAD_Input(event.GetKeyCode(), 1); // 1 = Down
@@ -938,44 +970,46 @@ wxAuiNotebook* CFrame::CreateEmptyNotebook()
 
 void CFrame::DoFullscreen(bool bF)
 {
-#if defined HAVE_X11 && HAVE_X11
-	if ((Core::GetState() == Core::CORE_RUN))
-		X11_SendEvent("TOGGLE_FULLSCREEN");
-#endif
 	// Only switch this to fullscreen if we're rendering to main AND if we're running a game
 	// plus if a modal dialog is open, this will still process the keyboard events, and may cause
 	// the main window to become unresponsive, so we have to avoid that.
-	if ((bRenderToMain && Core::GetState() == Core::CORE_RUN))
+	if ((Core::GetState() == Core::CORE_RUN) || (Core::GetState() == Core::CORE_PAUSE))
 	{
-		ShowFullScreen(bF);
+		if (bRenderToMain)
+		{
+			ShowFullScreen(bF);
 
-		if (bF)
-		{
-			// Save the current mode before going to fullscreen
-			AuiCurrent = m_Mgr->SavePerspective();
-			m_Mgr->LoadPerspective(AuiFullscreen, true);
-		}
-		else
-		{
-			// Restore saved perspective
-			m_Mgr->LoadPerspective(AuiCurrent, true);
-		}
+			if (bF)
+			{
+				// Save the current mode before going to fullscreen
+				AuiCurrent = m_Mgr->SavePerspective();
+				m_Mgr->LoadPerspective(AuiFullscreen, true);
+			}
+			else
+			{
+				// Restore saved perspective
+				m_Mgr->LoadPerspective(AuiCurrent, true);
+			}
 
-		// Show the cursor again, in case it was hidden
-		if (IsFullScreen())
-		{
-			#ifdef _WIN32
-			MSWSetCursor(true);
-			#endif
-		}
-	}
 #ifdef _WIN32
-	else // Post the message to the separate rendering window which will then handle it.
-	{
-		BringWindowToTop((HWND)Core::GetWindowHandle());
-		PostMessage((HWND)Core::GetWindowHandle(), WM_USER, TOGGLE_FULLSCREEN, 0);
-	}
+			// Show the cursor again, in case it was hidden
+			if (IsFullScreen())
+			{
+				MSWSetCursor(true);
+			}
 #endif
+		}
+#ifdef _WIN32
+		else // Post the message to the separate rendering window which will then handle it.
+		{
+			BringWindowToTop((HWND)Core::GetWindowHandle());
+			PostMessage((HWND)Core::GetWindowHandle(), WM_USER, TOGGLE_FULLSCREEN, 0);
+		}
+#elif defined HAVE_X11 && HAVE_X11
+		else // Send the event to the separate rendering window which will then handle it.
+			X11_SendClientEvent("TOGGLE_FULLSCREEN");
+#endif
+	}
 }
 
 // Debugging, show loose windows
diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h
index 5d0656a477..c4e21c1a06 100644
--- a/Source/Core/DolphinWX/Src/Frame.h
+++ b/Source/Core/DolphinWX/Src/Frame.h
@@ -303,6 +303,9 @@ class CFrame : public wxFrame
 
 		void OnGameListCtrl_ItemActivated(wxListEvent& event);
 		void DoFullscreen(bool _F);
+#if defined HAVE_X11 && HAVE_X11
+		void X11_SendClientEvent(const char *message);
+#endif
 
 		// MenuBar
 		// File - Drive
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index 50d710ed49..6c7aca9b7e 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -629,16 +629,11 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event))
 			wxThread::Sleep(20);
 			g_pCodeWindow->JumpToAddress(PC);
 			g_pCodeWindow->Update();
+			// Update toolbar with Play/Pause status
+			UpdateGUI();
 		}
 		else
-		{
-			if (Core::GetState() == Core::CORE_RUN)
-				Core::SetState(Core::CORE_PAUSE);
-			else
-				Core::SetState(Core::CORE_RUN);
-		}
-		// Update toolbar with Play/Pause status
-		UpdateGUI();
+			DoPause();
 	}
 	else
 		// Core is uninitialized, start the game
@@ -692,9 +687,19 @@ void CFrame::OnScreenshot(wxCommandEvent& WXUNUSED (event))
 void CFrame::DoPause()
 {
 	if (Core::GetState() == Core::CORE_RUN)
+	{
+#if defined(HAVE_X11) && HAVE_X11
+		X11_SendClientEvent("PAUSE");
+#endif
 		Core::SetState(Core::CORE_PAUSE);
+	}
 	else
+	{
+#if defined(HAVE_X11) && HAVE_X11
+		X11_SendClientEvent("RESUME");
+#endif
 		Core::SetState(Core::CORE_RUN);
+	}
 	UpdateGUI();
 }
 
diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp
index 87ff3a7b6b..a8a9e600c0 100644
--- a/Source/Core/DolphinWX/Src/Main.cpp
+++ b/Source/Core/DolphinWX/Src/Main.cpp
@@ -533,6 +533,8 @@ void Host_Message(int Id)
 #if defined(HAVE_X11) && HAVE_X11
 	switch(Id)
 	{
+		case WM_USER_CREATE:
+		case TOGGLE_FULLSCREEN:
 		case WM_USER_STOP:
 		case WM_USER_PAUSE:
 			{
diff --git a/Source/PluginSpecs/pluginspecs_pad.h b/Source/PluginSpecs/pluginspecs_pad.h
index 4a0ef29c6a..3c6f50ba13 100644
--- a/Source/PluginSpecs/pluginspecs_pad.h
+++ b/Source/PluginSpecs/pluginspecs_pad.h
@@ -35,6 +35,9 @@ typedef struct
 {
 	HWND			hWnd;
 #if defined HAVE_X11 && HAVE_X11
+#if defined(HAVE_GTK2) && HAVE_GTK2
+	void *pPanel;
+#endif
 	void *pXWindow;
 #endif
 	TLog			pLog;
diff --git a/Source/PluginSpecs/pluginspecs_video.h b/Source/PluginSpecs/pluginspecs_video.h
index c11b8b4db7..ab0950901f 100644
--- a/Source/PluginSpecs/pluginspecs_video.h
+++ b/Source/PluginSpecs/pluginspecs_video.h
@@ -72,6 +72,9 @@ typedef struct
 {
 	void *pWindowHandle;
 #if defined(HAVE_X11) && HAVE_X11
+#if defined(HAVE_GTK2) && HAVE_GTK2
+	void *pPanel;
+#endif
 	void *pXWindow;
 #endif
 
diff --git a/Source/PluginSpecs/pluginspecs_wiimote.h b/Source/PluginSpecs/pluginspecs_wiimote.h
index f3900afef6..b473edfca7 100644
--- a/Source/PluginSpecs/pluginspecs_wiimote.h
+++ b/Source/PluginSpecs/pluginspecs_wiimote.h
@@ -20,6 +20,9 @@ typedef struct
 {
 	HWND hWnd;
 #if defined HAVE_X11 && HAVE_X11
+#if defined(HAVE_GTK2) && HAVE_GTK2
+	void *pPanel;
+#endif
 	void *pXWindow;
 #endif
 	u32 ISOId;
diff --git a/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp b/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
index f583dc273c..40988afc70 100644
--- a/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
+++ b/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
@@ -658,12 +658,14 @@ bool IsFocus()
 		return false;
 #elif defined HAVE_X11 && HAVE_X11
 	Window GLWin = *(Window *)g_PADInitialize->pXWindow;
+	bool bFocus = False;
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+	bFocus = (wxPanel *)g_PADInitialize->pPanel == wxWindow::FindFocus();
+#endif
 	Window FocusWin;
 	int Revert;
 	XGetInputFocus(GCdisplay, &FocusWin, &Revert);
-	XWindowAttributes WinAttribs;
-	XGetWindowAttributes (GCdisplay, GLWin, &WinAttribs);
-	return (GLWin != 0 && (GLWin == FocusWin || WinAttribs.override_redirect));
+	return (GLWin == FocusWin || bFocus);
 #else
 	return true;
 #endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
index 7a6a95b737..388aa73061 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
@@ -118,43 +118,61 @@ void UpdateFPSDisplay(const char *text)
 }
 
 #if defined(HAVE_X11) && HAVE_X11
+THREAD_RETURN XEventThread(void *pArg);
+
+void X11_EWMH_Fullscreen(int action)
+{
+	assert(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD
+			|| action == _NET_WM_STATE_TOGGLE);
+
+	// Init X event structure for _NET_WM_STATE_FULLSCREEN client message
+	XEvent event;
+	event.xclient.type = ClientMessage;
+	event.xclient.message_type = XInternAtom(GLWin.dpy, "_NET_WM_STATE", False);
+	event.xclient.window = GLWin.win;
+	event.xclient.format = 32;
+	event.xclient.data.l[0] = action;
+	event.xclient.data.l[1] = XInternAtom(GLWin.dpy, "_NET_WM_STATE_FULLSCREEN", False);
+
+	// Send the event
+	if (!XSendEvent(GLWin.dpy, DefaultRootWindow(GLWin.dpy), False,
+				SubstructureRedirectMask | SubstructureNotifyMask, &event))
+		ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode.\n");
+}
+
 void CreateXWindow (void)
 {
-	Atom wmProtocols[2];
-	Window parent = RootWindow(GLWin.dpy, GLWin.vi->screen);
-	GLWin.x = 0;
-	GLWin.y = 0;
+	Atom wmProtocols[3];
+	Window parent;
 
 #if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
 	wxMutexGuiEnter();
 #endif
-	if (GLWin.fs)
-	{
 #if defined(HAVE_XRANDR) && HAVE_XRANDR
-		if (GLWin.fullSize >= 0)
-			XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
-					GLWin.fullSize, GLWin.screenRotation, CurrentTime);
+	if (GLWin.fs
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+			&& !g_Config.RenderToMainframe
 #endif
-		GLWin.attr.override_redirect = True;
-		GLWin.width = GLWin.fullWidth;
-		GLWin.height = GLWin.fullHeight;
+	   )
+		XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
+				GLWin.fullSize, GLWin.screenRotation, CurrentTime);
+#endif
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+	if (g_Config.RenderToMainframe)
+	{
+		GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height);
+		GLWin.panel->GetPosition(&GLWin.x, &GLWin.y);
+		parent = GDK_WINDOW_XID(GTK_WIDGET(GLWin.panel->GetHandle())->window);
+		GLWin.panel->SetFocus();
 	}
 	else
-	{
-		GLWin.attr.override_redirect = False;
-#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
-		if (g_Config.RenderToMainframe)
-		{
-			GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height);
-			GLWin.panel->GetPosition(&GLWin.x, &GLWin.y);
-			parent = GDK_WINDOW_XID(GTK_WIDGET(GLWin.panel->GetHandle())->window);
-		}
-		else
 #endif
-		{
-			GLWin.width = GLWin.winWidth;
-			GLWin.height = GLWin.winHeight;
-		}
+	{
+		GLWin.x = 0;
+		GLWin.y = 0;
+		GLWin.width = GLWin.winWidth;
+		GLWin.height = GLWin.winHeight;
+		parent = RootWindow(GLWin.dpy, GLWin.vi->screen);
 	}
 
 	// Control window size and picture scaling
@@ -164,28 +182,18 @@ void CreateXWindow (void)
 	// create the window
 	GLWin.win = XCreateWindow(GLWin.dpy, parent,
 			GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0, GLWin.vi->depth, InputOutput, GLWin.vi->visual,
-			CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &GLWin.attr);
+			CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr);
 	wmProtocols[0] = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True);
-	wmProtocols[1] = XInternAtom(GLWin.dpy, "WM_TAKE_FOCUS", True);
-	XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 2);
+	wmProtocols[1] = XInternAtom(GLWin.dpy, "_NET_WM_STATE", False);
+	wmProtocols[2] = XInternAtom(GLWin.dpy, "_NET_WM_STATE_FULLSCREEN", False);
+	XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 3);
 	XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL);
 	XMapRaised(GLWin.dpy, GLWin.win);
-	if (GLWin.fs)
-	{
-		XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-		XGrabPointer(GLWin.dpy, GLWin.win, True, NULL,
-				GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime);
-	}
-#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
-	if (GLWin.fs || g_Config.RenderToMainframe)
-#else
-	if (GLWin.fs)
-#endif
-		XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, CurrentTime);
 	XSync(GLWin.dpy, True);
 #if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
 	wxMutexGuiLeave();
 #endif
+	GLWin.xEventThread = new Common::Thread(XEventThread, NULL);
 }
 
 void DestroyXWindow(void)
@@ -200,25 +208,189 @@ void DestroyXWindow(void)
 	/* switch back to original desktop resolution if we were in fullscreen */
 	if( GLWin.fs )
 	{
-		XUngrabKeyboard (GLWin.dpy, CurrentTime);
-		XUngrabPointer (GLWin.dpy, CurrentTime);
 #if defined(HAVE_XRANDR) && HAVE_XRANDR
-		if (GLWin.fullSize >= 0)
-			XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
-					GLWin.deskSize, GLWin.screenRotation, CurrentTime);
+		XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
+				GLWin.deskSize, GLWin.screenRotation, CurrentTime);
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+		if (!g_Config.RenderToMainframe)
+#endif
+			X11_EWMH_Fullscreen(_NET_WM_STATE_REMOVE); 
 #endif
 	}
 	XUndefineCursor(GLWin.dpy, GLWin.win);
 	XUnmapWindow(GLWin.dpy, GLWin.win);
-	XSync(GLWin.dpy, True);
+	GLWin.win = 0;
 }
 
 void ToggleFullscreenMode (void)
 {
-	DestroyXWindow();
 	GLWin.fs = !GLWin.fs;
-	CreateXWindow();
-	OpenGL_MakeCurrent();
+#if defined(HAVE_XRANDR) && HAVE_XRANDR
+	if (GLWin.fs)
+		XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
+				GLWin.fullSize, GLWin.screenRotation, CurrentTime);
+	else
+		XRRSetScreenConfig(GLWin.dpy, GLWin.screenConfig, RootWindow(GLWin.dpy, GLWin.screen),
+				GLWin.deskSize, GLWin.screenRotation, CurrentTime);
+#endif
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+	if (!g_Config.RenderToMainframe)
+#endif
+	{
+		X11_EWMH_Fullscreen(_NET_WM_STATE_TOGGLE); 
+		XRaiseWindow(GLWin.dpy, GLWin.win);
+		XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, CurrentTime);
+	}
+	XSync(GLWin.dpy, False);
+}
+
+THREAD_RETURN XEventThread(void *pArg)
+{
+	bool bPaused = False;
+	while (GLWin.win)
+	{
+		XEvent event;
+		KeySym key;
+		int num_events;
+		for (num_events = XPending(GLWin.dpy);num_events > 0;num_events--) {
+			XNextEvent(GLWin.dpy, &event);
+			switch(event.type) {
+				case KeyPress:
+					key = XLookupKeysym((XKeyEvent*)&event, 0);
+					switch (key)
+					{
+						case XK_F1: case XK_F2: case XK_F3: case XK_F4: case XK_F5: case XK_F6:
+						case XK_F7: case XK_F8: case XK_F9: case XK_F11: case XK_F12:
+							g_VideoInitialize.pKeyPress(key - 0xff4e,
+									event.xkey.state & ShiftMask,
+									event.xkey.state & ControlMask);
+							break;
+						case XK_Escape:
+							if (GLWin.fs && !bPaused)
+							{
+								printf("toggling fullscreen\n");
+								ToggleFullscreenMode();
+							}
+							g_VideoInitialize.pKeyPress(0x1c, False, False);
+							break;
+						case XK_Return:
+							if (event.xkey.state & Mod1Mask)
+								ToggleFullscreenMode();
+							break;
+						case XK_3:
+							OSDChoice = 1;
+							// Toggle native resolution
+							if (!(g_Config.bNativeResolution || g_Config.b2xResolution))
+								g_Config.bNativeResolution = true;
+							else if (g_Config.bNativeResolution && Renderer::AllowCustom())
+							{ g_Config.bNativeResolution = false; if (Renderer::Allow2x()) {g_Config.b2xResolution = true;} }
+							else if (Renderer::AllowCustom())
+								g_Config.b2xResolution = false;
+							break;
+						case XK_4:
+							OSDChoice = 2;
+							// Toggle aspect ratio
+							g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
+							break;
+						case XK_5:
+							OSDChoice = 3;
+							// Toggle EFB copy
+							if (g_Config.bEFBCopyDisable || g_Config.bCopyEFBToTexture)
+							{
+								g_Config.bEFBCopyDisable = !g_Config.bEFBCopyDisable;
+								g_Config.bCopyEFBToTexture = false;
+							}
+							else
+							{
+								g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture;
+							}
+							break;
+						case XK_6:
+							OSDChoice = 4;
+							g_Config.bDisableFog = !g_Config.bDisableFog;
+							break;
+						case XK_7:
+							OSDChoice = 5;
+							g_Config.bDisableLighting = !g_Config.bDisableLighting;
+							break;
+						default:
+							break;
+					}
+					break;
+				case FocusIn:
+					if (g_Config.bHideCursor && !bPaused
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+							&& !g_Config.RenderToMainframe
+#endif
+					   )
+						XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
+					break;
+				case FocusOut:
+					if (g_Config.bHideCursor && !bPaused
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+							&& !g_Config.RenderToMainframe
+#endif
+					   )
+						XUndefineCursor(GLWin.dpy, GLWin.win);
+					break;
+				case ConfigureNotify:
+					Window winDummy;
+					unsigned int borderDummy;
+					XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
+							&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
+					s_backbuffer_width = GLWin.width;
+					s_backbuffer_height = GLWin.height;
+					// Save windowed mode size for return from fullscreen
+					if (!GLWin.fs)
+					{
+						GLWin.winWidth = GLWin.width;
+						GLWin.winHeight = GLWin.height;
+					}
+					break;
+				case ClientMessage:
+					if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))
+						g_VideoInitialize.pKeyPress(0x1b, False, False);
+					if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False))
+						ToggleFullscreenMode();
+					if (g_Config.bHideCursor && 
+							(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "PAUSE", False))
+					{
+						bPaused = True;
+						XUndefineCursor(GLWin.dpy, GLWin.win);
+					}
+					if (g_Config.bHideCursor && 
+							(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "RESUME", False))
+					{
+						bPaused = False;
+						XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
+					}
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+					if (g_Config.RenderToMainframe &&
+							(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "RESIZE", False))
+					{
+						GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height);
+						GLWin.panel->GetPosition(&GLWin.x, &GLWin.y);
+						XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y, GLWin.width, GLWin.height);
+					}
+					if (g_Config.RenderToMainframe &&
+							(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "FOCUSIN", False))
+					{
+						GLWin.panel->SetFocus();
+						if (g_Config.bHideCursor)
+							XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
+					}
+					if (g_Config.RenderToMainframe && g_Config.bHideCursor &&
+							(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "FOCUSOUT", False))
+						XUndefineCursor(GLWin.dpy, GLWin.win);
+#endif
+					break;
+				default:
+					break;
+			}
+		}
+		Common::SleepCurrentThread(20);
+	}
+	return 0;
 }
 #endif
 
@@ -396,7 +568,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
 
 	GLWin.dpy = XOpenDisplay(0);
 #if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
-	GLWin.panel = (wxPanel *)g_VideoInitialize.pWindowHandle;
+	GLWin.panel = (wxPanel *)g_VideoInitialize.pPanel;
 #endif
 	g_VideoInitialize.pWindowHandle = (Display *)GLWin.dpy;
 	GLWin.screen = DefaultScreen(GLWin.dpy);
@@ -426,9 +598,11 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
 		exit(0); // TODO: Don't bring down entire Emu
 	}
 	// Create a color map and set the event masks
-	GLWin.attr.colormap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, GLWin.vi->screen), GLWin.vi->visual, AllocNone);
+	GLWin.attr.colormap = XCreateColormap(GLWin.dpy,
+			RootWindow(GLWin.dpy, GLWin.vi->screen), GLWin.vi->visual, AllocNone);
 	GLWin.attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
 		StructureNotifyMask | ResizeRedirectMask;
+	GLWin.attr.background_pixel = BlackPixel(GLWin.dpy, GLWin.screen);
 	GLWin.attr.border_pixel = 0;
 	XkbSetDetectableAutoRepeat(GLWin.dpy, True, NULL);
 
@@ -483,6 +657,11 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
 	GLWin.fullHeight = DisplayHeight(GLWin.dpy, GLWin.screen);
 #endif
 
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+	if (g_Config.RenderToMainframe)
+		g_VideoInitialize.pKeyPress(0, False, False);
+#endif
+
 	CreateXWindow();
 	g_VideoInitialize.pXWindow = (Window *) &GLWin.win;
 
@@ -525,6 +704,19 @@ bool OpenGL_MakeCurrent()
 			ERROR_LOG(VIDEO, "no Direct Rendering possible!");
 		}
 
+	if (GLWin.fs)
+	{
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+		if (g_Config.RenderToMainframe)
+		{
+			GLWin.fs = False;
+			g_VideoInitialize.pKeyPress(0x1d, False, False);
+		}
+		else
+#endif
+			X11_EWMH_Fullscreen(_NET_WM_STATE_ADD);
+	}
+
 	// Hide the cursor now
 	if (g_Config.bHideCursor)
 		XDefineCursor (GLWin.dpy, GLWin.win, GLWin.blankCursor);
@@ -581,134 +773,6 @@ void OpenGL_Update()
 	s_backbuffer_height = height;
 
 #elif defined(HAVE_X11) && HAVE_X11
-	// We just check all of our events here
-	XEvent event;
-	KeySym key;
-	int num_events;
-	for (num_events = XPending(GLWin.dpy);num_events > 0;num_events--) {
-		XNextEvent(GLWin.dpy, &event);
-		switch(event.type) {
-			case KeyPress:
-				key = XLookupKeysym((XKeyEvent*)&event, 0);
-				switch (key)
-				{
-					case XK_F4:
-						if(event.xkey.state & Mod1Mask)
-						{
-							g_VideoInitialize.pKeyPress(0x1b, False, False);
-							break;
-						}
-					case XK_F1: case XK_F2: case XK_F3: case XK_F5:
-					case XK_F6: case XK_F7: case XK_F8: case XK_F9:
-						g_VideoInitialize.pKeyPress(key - 0xff4e,
-								event.xkey.state & ShiftMask,
-								event.xkey.state & ControlMask);
-						break;
-					case XK_Escape:
-						if (GLWin.fs)
-						{
-							ToggleFullscreenMode();
-							#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
-							if (!g_Config.RenderToMainframe)
-							#endif
-							{
-								XEvent mapevent;
-								do {
-									XMaskEvent(GLWin.dpy, StructureNotifyMask, &mapevent);
-								} while ((mapevent.type != MapNotify) || (mapevent.xmap.event != GLWin.win));
-							}
-						}
-						g_VideoInitialize.pKeyPress(0x1c, False, False);
-						break;
-					case XK_Return:
-						if (event.xkey.state & Mod1Mask)
-							ToggleFullscreenMode();
-						break;
-					case XK_3:
-						OSDChoice = 1;
-						// Toggle native resolution
-						if (!(g_Config.bNativeResolution || g_Config.b2xResolution))
-							g_Config.bNativeResolution = true;
-						else if (g_Config.bNativeResolution && Renderer::AllowCustom())
-						{ g_Config.bNativeResolution = false; if (Renderer::Allow2x()) {g_Config.b2xResolution = true;} }
-						else if (Renderer::AllowCustom())
-							g_Config.b2xResolution = false;
-						break;
-					case XK_4:
-						OSDChoice = 2;
-						// Toggle aspect ratio
-						g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
-						break;
-					case XK_5:
-						OSDChoice = 3;
-						// Toggle EFB copy
-						if (g_Config.bEFBCopyDisable || g_Config.bCopyEFBToTexture)
-						{
-							g_Config.bEFBCopyDisable = !g_Config.bEFBCopyDisable;
-							g_Config.bCopyEFBToTexture = false;
-						}
-						else
-						{
-							g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture;
-						}
-						break;
-					case XK_6:
-						OSDChoice = 4;
-						g_Config.bDisableFog = !g_Config.bDisableFog;
-						break;
-					case XK_7:
-						OSDChoice = 5;
-						g_Config.bDisableLighting = !g_Config.bDisableLighting;
-						break;
-
-					default:
-						break;
-				}
-				break;
-			case FocusIn:
-				if (g_Config.bHideCursor)
-					XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor);
-				break;
-			case FocusOut:
-				if (g_Config.bHideCursor && !GLWin.fs)
-					XUndefineCursor(GLWin.dpy, GLWin.win);
-				break;
-			case ConfigureNotify:
-				Window winDummy;
-				unsigned int borderDummy;
-				XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
-						&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
-				s_backbuffer_width = GLWin.width;
-				s_backbuffer_height = GLWin.height;
-				// Save windowed mode size for return from fullscreen
-				if (!GLWin.fs)
-				{
-					GLWin.winWidth = GLWin.width;
-					GLWin.winHeight = GLWin.height;
-				}
-				break;
-			case ClientMessage:
-				if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))
-					g_VideoInitialize.pKeyPress(0x1b, False, False);
-				if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False))
-					ToggleFullscreenMode();
-#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
-				if (g_Config.RenderToMainframe && !GLWin.fs &&
-						(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "MAIN_RESIZED", False))
-				{
-					GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height);
-					GLWin.panel->GetPosition(&GLWin.x, &GLWin.y);
-					XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y, GLWin.width, GLWin.height);
-				}
-				if (g_Config.RenderToMainframe && !GLWin.fs &&
-						(ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WINDOW_REFOCUS", False))
-					XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, CurrentTime);
-#endif
-			break;
-			default:
-				break;
-		}
-	}
 #endif
 }
 
@@ -748,6 +812,9 @@ void OpenGL_Shutdown()
 	}
 #elif defined(HAVE_X11) && HAVE_X11
 	DestroyXWindow();
+	if (GLWin.xEventThread)
+		GLWin.xEventThread->WaitForDeath();
+	GLWin.xEventThread = NULL;
 #if defined(HAVE_XRANDR) && HAVE_XRANDR
 	if (GLWin.fullSize >= 0)
 		XRRFreeScreenConfigInfo(GLWin.screenConfig);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
index ddd6ec3636..921729ee60 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
@@ -31,14 +31,14 @@
 #include <GLew/gl.h>
 #include <GLew/glext.h>
 
-#else // linux basic definitions
+#else // linux and apple basic definitions
 
 #if defined(USE_WX) && USE_WX
 #include <GL/glew.h>
 #include "wx/wx.h"
 #include "wx/glcanvas.h"
+
 #elif defined(HAVE_X11) && HAVE_X11
-#define I_NEED_OS2_H // HAXXOR
 #include <GL/glxew.h>
 #include <X11/XKBlib.h>
 #if defined(HAVE_GTK2) && HAVE_GTK2 // Needed for render to main
@@ -46,9 +46,23 @@
 #include <gdk/gdkx.h>
 #include <wx/wx.h>
 #endif
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include "Thread.h"
+#if defined(HAVE_XRANDR) && HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif // XRANDR
+// EWMH state actions, see
+// http://freedesktop.org/wiki/Specifications/wm-spec?action=show&redirect=Standards%2Fwm-spec
+#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
+#define _NET_WM_STATE_ADD           1    /* add/set property */
+#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
+
 #elif defined(USE_SDL) && USE_SDL
 #include <GL/glew.h>
 #include <SDL.h>
+
 #elif defined(HAVE_COCOA) && HAVE_COCOA
 #include <GL/glew.h>
 #include "cocoaGL.h"
@@ -70,15 +84,6 @@
 #endif
 
 #ifndef _WIN32
-#if defined(HAVE_X11) && HAVE_X11
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-
-#if defined(HAVE_XRANDR) && HAVE_XRANDR
-#include <X11/extensions/Xrandr.h>
-#endif // XRANDR
-#endif // X11
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -102,6 +107,7 @@ typedef struct {
 	Bool doubleBuffered;
 	int fullWidth, fullHeight;
 	int winWidth, winHeight;
+	Common::Thread *xEventThread;
 #if defined(HAVE_XRANDR) && HAVE_XRANDR
 	XRRScreenConfiguration *screenConfig;
 	Rotation screenRotation;
diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp
index f6b26a2f03..1ab892cda3 100644
--- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp
+++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp
@@ -397,12 +397,14 @@ bool IsFocus()
 		return false;
 #elif defined HAVE_X11 && HAVE_X11
 	Window GLWin = *(Window *)g_WiimoteInitialize.pXWindow;
+	bool bFocus = False;
+#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK)
+	bFocus = (wxPanel *)g_WiimoteInitialize.pPanel == wxWindow::FindFocus();
+#endif
 	Window FocusWin;
 	int Revert;
 	XGetInputFocus(WMdisplay, &FocusWin, &Revert);
-	XWindowAttributes WinAttribs;
-	XGetWindowAttributes (WMdisplay, GLWin, &WinAttribs);
-	return (GLWin != 0 && (GLWin == FocusWin || WinAttribs.override_redirect));
+	return (GLWin == FocusWin || bFocus);
 #else
 	return true;
 #endif