From 13437c1f6b6e5caa0012d943a3ca38709ffe0bc0 Mon Sep 17 00:00:00 2001
From: Glenn Rice <glennricster@gmail.com>
Date: Sun, 7 Feb 2010 02:41:02 +0000
Subject: [PATCH] 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
---
 Source/Core/Core/Src/Core.cpp                 |  7 +++++
 Source/Core/DolphinWX/Src/Frame.cpp           |  4 +++
 Source/Core/DolphinWX/Src/Main.cpp            | 14 ++++++++++
 Source/Plugins/Plugin_GCPad/Src/GCPad.cpp     |  4 +--
 Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 28 +++++++++++--------
 Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp |  4 +--
 6 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index 1c9ebcd3b2..853a90a14b 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -739,6 +739,13 @@ void Callback_KeyPress(int key, bool shift, bool control)
 		else
 			State_UndoLoadState();	
 	}
+#if defined(HAVE_X11) && HAVE_X11
+	// 0x1b == VK_ESCAPE
+	if (key == 0x1b) 
+	{
+		Host_Message(WM_USER_STOP);
+	}
+#endif
 }
  
 // Callback_WiimoteLog
diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp
index 2c2a56eaaf..911ef740ae 100644
--- a/Source/Core/DolphinWX/Src/Frame.cpp
+++ b/Source/Core/DolphinWX/Src/Frame.cpp
@@ -640,7 +640,11 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
 			m_pStatusBar->SetStatusText(event.GetString(), event.GetInt());
 		}
 		break;
+#if defined(HAVE_X11) && HAVE_X11
+	case WM_USER_STOP:
+		main_frame->DoStop();
 	}
+#endif
 }
 
 void CFrame::OnCustomHostMessage(int Id)
diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp
index 37ab2b1d0a..b92f3a6d25 100644
--- a/Source/Core/DolphinWX/Src/Main.cpp
+++ b/Source/Core/DolphinWX/Src/Main.cpp
@@ -520,7 +520,21 @@ CFrame* DolphinApp::GetCFrame()
 
 void Host_Message(int Id)
 {
+#if defined(HAVE_X11) && HAVE_X11
+	switch(Id)
+	{
+		case WM_USER_STOP:
+			{
+				wxCommandEvent event(wxEVT_HOST_COMMAND, WM_USER_STOP);
+				main_frame->GetEventHandler()->AddPendingEvent(event);
+				break;
+			}
+		default:
+			main_frame->OnCustomHostMessage(Id);
+	}
+#else
 	main_frame->OnCustomHostMessage(Id);
+#endif
 }
 
 // OK, this thread boundary is DANGEROUS on linux
diff --git a/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp b/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
index e2eef71df9..177d1129eb 100644
--- a/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
+++ b/Source/Plugins/Plugin_GCPad/Src/GCPad.cpp
@@ -650,7 +650,7 @@ void ReadLinuxKeyboard()
 			
 			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_Control_L || key == XK_Control_R || key == XK_Escape)
 			{
 				XPutBackEvent(WMdisplay, &E);
 				break;
@@ -669,7 +669,7 @@ void ReadLinuxKeyboard()
 			
 			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_Control_L || key == XK_Control_R || key == XK_Escape) {
 				XPutBackEvent(WMdisplay, &E);
 				break;
 			}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
index 9da44d628f..b467bf1e90 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp
@@ -506,7 +506,7 @@ void OpenGL_Update()
         switch(event.type) {
             case KeyRelease:
                 key = XLookupKeysym((XKeyEvent*)&event, 0);
-                if(key >= XK_F1 && key <= XK_F9) {
+                if((key >= XK_F1 && key <= XK_F9) || (key == XK_Escape)) {
                         g_VideoInitialize.pKeyPress(FKeyPressed, ShiftPressed, ControlPressed);
                         FKeyPressed = -1;
                 } else {
@@ -522,6 +522,8 @@ void OpenGL_Update()
                 key = XLookupKeysym((XKeyEvent*)&event, 0);
                 if(key >= XK_F1 && key <= XK_F9)
                     FKeyPressed = key - 0xff4e;
+                else if (key == XK_Escape)
+                    FKeyPressed = 0x1b;
                 else {
                     if(key == XK_Shift_L || key == XK_Shift_R)
                         ShiftPressed = true;
@@ -547,8 +549,10 @@ void OpenGL_Update()
                 rcWindow.right = GLWin.width;
                 rcWindow.bottom = GLWin.height;
                 break;
-            case ClientMessage: //TODO: We aren't reading this correctly, It could be anything, highest chance is that it's a close event though
-//								Shutdown(); // Calling from here since returning false does nothing
+            case ClientMessage:
+                if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False))
+                  g_VideoInitialize.pKeyPress(0x1b, False, False);
+                return;
                 break;
             default:
                 //TODO: Should we put the event back if we don't handle it?
@@ -596,6 +600,15 @@ void OpenGL_Shutdown()
 		hDC = NULL;                                       // Set DC To NULL
 	}
 #elif defined(HAVE_X11) && HAVE_X11
+#if defined(HAVE_XXF86VM) && HAVE_XXF86VM
+	/* switch back to original desktop resolution if we were in fs */
+	if ((GLWin.dpy != NULL) && GLWin.fs) {
+		XUngrabKeyboard (GLWin.dpy, CurrentTime);
+		XUngrabButton (GLWin.dpy, AnyButton, AnyModifier, GLWin.win);
+		XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode);
+		XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
+	}
+#endif
 	if (g_Config.bHideCursor) XUndefineCursor(GLWin.dpy, GLWin.win);
 	if (GLWin.ctx)
 	{
@@ -608,15 +621,6 @@ void OpenGL_Shutdown()
 		XCloseDisplay(GLWin.dpy);
 		GLWin.ctx = NULL;
 	}
-#if defined(HAVE_XXF86VM) && HAVE_XXF86VM
-	/* switch back to original desktop resolution if we were in fs */
-	if (GLWin.dpy != NULL) {
-		if (GLWin.fs) {
-			XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode);
-			XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
-		}
-	}
-#endif
 #endif
 }
 
diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp
index 7fb2cbafc3..8aa5b8e2e1 100644
--- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp
+++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp
@@ -682,7 +682,7 @@ void ReadLinuxKeyboard()
 			
 			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_Control_L || key == XK_Control_R || key == XK_Escape)
 			{
 				XPutBackEvent(WMdisplay, &E);
 				break;
@@ -701,7 +701,7 @@ void ReadLinuxKeyboard()
 			
 			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_Control_L || key == XK_Control_R || key == XK_Escape) {
 				XPutBackEvent(WMdisplay, &E);
 				break;
 			}