mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
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
This commit is contained in:
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
{
|
||||
|
Reference in New Issue
Block a user