From 5beb6dfd4718c5580d4b90edf38ef7bd6882e0f4 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Mon, 8 Mar 2010 23:29:16 +0000 Subject: [PATCH] Implement render to main in linux. In order to compile this in you will have to have libgtk2.0-dev (or your distributions equivalent) installed. If not dolphin-emu will still build, but without render to main operational. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5176 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DolphinWX/Src/Frame.cpp | 56 +++++++----- Source/Core/DolphinWX/Src/Frame.h | 2 + Source/Core/DolphinWX/Src/FrameTools.cpp | 5 +- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 87 ++++++++++++++----- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h | 8 ++ .../Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp | 6 ++ Source/Plugins/Plugin_VideoOGL/Src/SConscript | 4 + 7 files changed, 120 insertions(+), 48 deletions(-) diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index f038f0926b..d970fe86b8 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -523,10 +523,34 @@ void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event)) Close(true); } +#if defined HAVE_X11 && HAVE_X11 +void X11_SendEvent(const char *message) +{ + XEvent event; + Display *dpy = (Display *)Core::GetWindowHandle(); + Window win = *(Window *)Core::GetXWindow(); + + // Init X event structure for client message + event.xclient.type = ClientMessage; + event.xclient.format = 32; + event.xclient.data.l[0] = XInternAtom(dpy, message, False); + + // Send the event + if (!XSendEvent(dpy, win, False, False, &event)) + { + ERROR_LOG(VIDEO, "Failed to send message %s to the emulator window.\n", message); + } +} +#endif + // -------- // Events void CFrame::OnActive(wxActivateEvent& event) { +#if defined(HAVE_X11) && HAVE_X11 && defined(wxGTK) + if (event.GetActive() && Core::GetState() == Core::CORE_RUN) + X11_SendEvent("WINDOW_REFOCUS"); +#endif event.Skip(); } @@ -582,6 +606,7 @@ void CFrame::OnMove(wxMoveEvent& event) SConfig::GetInstance().m_LocalCoreStartupParameter.iPosX = GetPosition().x; SConfig::GetInstance().m_LocalCoreStartupParameter.iPosY = GetPosition().y; } + void CFrame::OnResize(wxSizeEvent& event) { event.Skip(); @@ -589,6 +614,11 @@ void CFrame::OnResize(wxSizeEvent& event) SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth = GetSize().GetWidth(); SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight = GetSize().GetHeight(); +#if defined(HAVE_X11) && HAVE_X11 + if (Core::GetState() == Core::CORE_RUN) + X11_SendEvent("MAIN_RESIZED"); +#endif + DoMoveIcons(); // In FrameWiimote.cpp } void CFrame::OnResizeAll(wxSizeEvent& event) @@ -653,7 +683,7 @@ void CFrame::OnHostMessage(wxCommandEvent& event) main_frame->DoStop(); break; case WM_USER_PAUSE: - main_frame->OnPlay(event); + main_frame->DoPause(); break; #endif } @@ -910,31 +940,11 @@ wxAuiNotebook* CFrame::CreateEmptyNotebook() return NB; } -#if defined HAVE_X11 && HAVE_X11 -void X11_ShowFullScreen(bool bF) -{ - XEvent event; - Display *dpy = (Display *)Core::GetWindowHandle(); - Window win = *(Window *)Core::GetXWindow(); - - // Init X event structure for TOGGLE_FULLSCREEN client message - event.xclient.type = ClientMessage; - event.xclient.format = 32; - event.xclient.data.l[0] = XInternAtom(dpy, "TOGGLE_FULLSCREEN", False);; - - // Send the event - if (!XSendEvent(dpy, win, False, False, &event)) - { - ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode.\n"); - } -} -#endif - void CFrame::DoFullscreen(bool bF) { #if defined HAVE_X11 && HAVE_X11 if ((Core::GetState() == Core::CORE_RUN)) - X11_ShowFullScreen(bF); + 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 @@ -1060,4 +1070,4 @@ void CFrame::ListTopWindows() j++; } NOTICE_LOG(CONSOLE, "\n"); -} \ No newline at end of file +} diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h index 6d228a8618..21757a7072 100644 --- a/Source/Core/DolphinWX/Src/Frame.h +++ b/Source/Core/DolphinWX/Src/Frame.h @@ -64,6 +64,8 @@ class CFrame : public wxFrame { #ifdef _WIN32 return(m_Panel->GetHandle()); + #elif defined(HAVE_X11) && HAVE_X11 + return m_Panel; #else return this; #endif diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index f4eaae698b..50d710ed49 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -691,7 +691,10 @@ void CFrame::OnScreenshot(wxCommandEvent& WXUNUSED (event)) // Pause the emulation void CFrame::DoPause() { - Core::SetState(Core::CORE_PAUSE); + if (Core::GetState() == Core::CORE_RUN) + Core::SetState(Core::CORE_PAUSE); + else + Core::SetState(Core::CORE_RUN); UpdateGUI(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 5bc174f851..6df7ec195a 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -120,9 +120,14 @@ void UpdateFPSDisplay(const char *text) #if defined(HAVE_X11) && HAVE_X11 void CreateXWindow (void) { - Atom wmProtocols[3]; - int width, height; + Atom wmProtocols[2]; + Window parent = RootWindow(GLWin.dpy, GLWin.vi->screen); + GLWin.x = 0; + GLWin.y = 0; +#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) + wxMutexGuiEnter(); +#endif if (GLWin.fs) { #if defined(HAVE_XRANDR) && HAVE_XRANDR @@ -131,30 +136,40 @@ void CreateXWindow (void) GLWin.fullSize, GLWin.screenRotation, CurrentTime); #endif GLWin.attr.override_redirect = True; - width = GLWin.fullWidth; - height = GLWin.fullHeight; + GLWin.width = GLWin.fullWidth; + GLWin.height = GLWin.fullHeight; } else { GLWin.attr.override_redirect = False; - width = GLWin.winWidth; - height = GLWin.winHeight; +#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; + } } // Control window size and picture scaling - s_backbuffer_width = width; - s_backbuffer_height = height; + s_backbuffer_width = GLWin.width; + s_backbuffer_height = GLWin.height; // create the window GLWin.attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | ResizeRedirectMask; - GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, GLWin.vi->screen), - 0, 0, width, height, 0, GLWin.vi->depth, InputOutput, GLWin.vi->visual, + 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); wmProtocols[0] = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); wmProtocols[1] = XInternAtom(GLWin.dpy, "WM_TAKE_FOCUS", True); - wmProtocols[2] = XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False); - XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 3); + XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 2); XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL); XMapRaised(GLWin.dpy, GLWin.win); if (GLWin.fs) @@ -162,9 +177,17 @@ void CreateXWindow (void) XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(GLWin.dpy, GLWin.win, True, NULL, GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime); - XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, 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 } void DestroyXWindow(void) @@ -352,7 +375,6 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight // -------------------------------------- #elif defined(HAVE_X11) && HAVE_X11 - Colormap cmap; int glxMajorVersion, glxMinorVersion; int vidModeMajorVersion, vidModeMinorVersion; @@ -375,7 +397,10 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight GLWin.dpy = XOpenDisplay(0); - g_VideoInitialize.pWindowHandle = (HWND)GLWin.dpy; +#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) + GLWin.panel = (wxPanel *)g_VideoInitialize.pWindowHandle; +#endif + g_VideoInitialize.pWindowHandle = (Display *)GLWin.dpy; GLWin.screen = DefaultScreen(GLWin.dpy); // Fullscreen option. @@ -403,8 +428,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight exit(0); // TODO: Don't bring down entire Emu } // Create a color map. - cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, GLWin.vi->screen), GLWin.vi->visual, AllocNone); - GLWin.attr.colormap = cmap; + GLWin.attr.colormap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, GLWin.vi->screen), GLWin.vi->visual, AllocNone); GLWin.attr.border_pixel = 0; XkbSetDetectableAutoRepeat(GLWin.dpy, True, NULL); @@ -584,10 +608,15 @@ void OpenGL_Update() if (GLWin.fs) { ToggleFullscreenMode(); - XEvent mapevent; - do { - XMaskEvent(GLWin.dpy, StructureNotifyMask, &mapevent); - } while ( (mapevent.type != MapNotify) || (mapevent.xmap.event != GLWin.win) ); + #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; @@ -635,6 +664,7 @@ void OpenGL_Update() default: break; } + break; case FocusIn: if (g_Config.bHideCursor) XDefineCursor(GLWin.dpy, GLWin.win, GLWin.blankCursor); @@ -662,13 +692,22 @@ void OpenGL_Update() g_VideoInitialize.pKeyPress(0x1b, False, False); if ((ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "TOGGLE_FULLSCREEN", False)) ToggleFullscreenMode(); - return; - break; +#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) + if (g_Config.RenderToMainframe && + (ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "MAIN_RESIZED", False)) + { + GLWin.panel->GetSize((int *)&GLWin.width, (int *)&GLWin.height); + XResizeWindow(GLWin.dpy, GLWin.win, GLWin.width, GLWin.height); + } +#endif + if (g_Config.RenderToMainframe && + (ulong) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WINDOW_REFOCUS", False)) + XSetInputFocus(GLWin.dpy, GLWin.win, RevertToPointerRoot, CurrentTime); + break; default: break; } } - return; #endif } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h index 4bff0c4efa..ddd6ec3636 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h @@ -41,6 +41,11 @@ #define I_NEED_OS2_H // HAXXOR #include #include +#if defined(HAVE_GTK2) && HAVE_GTK2 // Needed for render to main +#include +#include +#include +#endif #elif defined(USE_SDL) && USE_SDL #include #include @@ -85,6 +90,9 @@ typedef struct { NSOpenGLContext *cocoaCtx; #elif defined(HAVE_X11) && HAVE_X11 Window win; +#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) + wxPanel *panel; +#endif Display *dpy; XVisualInfo *vi; GLXContext ctx; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp index 13550b1a7d..d99b66f4fd 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp @@ -833,8 +833,10 @@ void GFXConfigDialogOGL::UpdateGUI() m_AutoScale->Enable(!g_Config.bUseXFB); // These options are for the separate rendering window +#if !defined(HAVE_GTK2) || !HAVE_GTK2 || !defined(wxGTK) m_Fullscreen->Enable(!g_Config.RenderToMainframe); if (g_Config.RenderToMainframe) m_Fullscreen->SetValue(false); +#endif // Resolution settings //disable native/2x choice when real xfb is on. native simply looks best, as ector noted above. @@ -842,7 +844,11 @@ void GFXConfigDialogOGL::UpdateGUI() m_NativeResolution->Enable(!g_Config.bUseXFB); m_2xResolution->Enable(!g_Config.bUseXFB && (!g_Config.bRunning || Renderer::Allow2x())); m_WindowResolutionCB->Enable(!g_Config.bRunning); +#if defined(HAVE_GTK2) && HAVE_GTK2 && defined(wxGTK) + m_WindowFSResolutionCB->Enable(!g_Config.bRunning); +#else m_WindowFSResolutionCB->Enable(!g_Config.bRunning && !g_Config.RenderToMainframe); +#endif // Disable the Copy to options when EFBCopy is disabled m_Radio_CopyEFBToRAM->Enable(!(g_Config.bEFBCopyDisable)); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SConscript b/Source/Plugins/Plugin_VideoOGL/Src/SConscript index d670d8b1f8..9a9349c26b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/SConscript +++ b/Source/Plugins/Plugin_VideoOGL/Src/SConscript @@ -105,6 +105,10 @@ gfxenv['HAVE_XRANDR'] = gfxenv['HAVE_X11'] and conf.CheckPKG('xrandr') conf.Define('HAVE_XRANDR', gfxenv['HAVE_XRANDR']) +# check for libgtk2.0 +gfxenv['HAVE_GTK2'] = gfxenv['HAVE_WX'] and conf.CheckPKG('gtk+-2.0') +conf.Define('HAVE_GTK2', gfxenv['HAVE_GTK2']) + conf.Finish() # Sanity check