diff --git a/plugins/zzogl-pg/opengl/GLWin.h b/plugins/zzogl-pg/opengl/GLWin.h index bca595fe1b..783e48b171 100644 --- a/plugins/zzogl-pg/opengl/GLWin.h +++ b/plugins/zzogl-pg/opengl/GLWin.h @@ -50,8 +50,8 @@ class GLWindow bool CreateVisual(); void GetGLXVersion(); - void GetGLXVidModeVersion(); void GetWindowSize(); + void UpdateGrabKey(); #endif bool fullScreen, doubleBuffered; s32 x, y; @@ -60,6 +60,10 @@ class GLWindow public: void SwapGLBuffers(); bool ReleaseContext(); + +#ifdef GL_X11_WINDOW + void ToggleFullscreen(); +#endif bool CreateWindow(void *pDisplay); void CloseWindow(); @@ -68,6 +72,7 @@ class GLWindow void ResizeCheck(); }; + extern GLWindow GLWin; #endif // GLWIN_H_INCLUDED diff --git a/plugins/zzogl-pg/opengl/GLWinX11.cpp b/plugins/zzogl-pg/opengl/GLWinX11.cpp index 70b15c6ad6..5d7977d7e8 100644 --- a/plugins/zzogl-pg/opengl/GLWinX11.cpp +++ b/plugins/zzogl-pg/opengl/GLWinX11.cpp @@ -59,22 +59,15 @@ void GLWindow::CloseWindow() conf.x = x; conf.y = y; SaveConfig(); + if (!glDisplay) return; /* switch back to original desktop resolution if we were in fullscreen */ - if (glDisplay != NULL) - { - if (fullScreen) - { - XF86VidModeSwitchToMode(glDisplay, glScreen, &deskMode); - XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0); - } - } - - if (glDisplay != NULL) - { - XCloseDisplay(glDisplay); - glDisplay = NULL; - } + if (fullScreen) + ToggleFullscreen(); + + XSync(glDisplay, False); + XCloseDisplay(glDisplay); + glDisplay = NULL; } bool GLWindow::CreateVisual() @@ -123,11 +116,15 @@ bool GLWindow::CreateVisual() void GLWindow::GetWindowSize() { + if (!glDisplay or !glWindow) return; + unsigned int borderDummy; Window winDummy; + s32 xDummy; + s32 yDummy; - XGetGeometry(glDisplay, glWindow, &winDummy, &x, &y, &width, &height, &borderDummy, &depth); - ZZLog::Error_Log("Depth %d", depth); + XGetGeometry(glDisplay, glWindow, &winDummy, &xDummy, &yDummy, &width, &height, &borderDummy, &depth); + ZZLog::Error_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, x, y); } void GLWindow::GetGLXVersion() @@ -139,14 +136,59 @@ void GLWindow::GetGLXVersion() ZZLog::Error_Log("glX-Version %d.%d", glxMajorVersion, glxMinorVersion); } -void GLWindow::GetGLXVidModeVersion() +void GLWindow::UpdateGrabKey() { + if (fullScreen) { + XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime); + XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } else { + XUngrabPointer(glDisplay, CurrentTime); + XUngrabKeyboard(glDisplay, CurrentTime); + } +} + +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 +#define _NET_WM_STATE_TOGGLE 2 + +void GLWindow::ToggleFullscreen() { - int vidModeMajorVersion, vidModeMinorVersion; - - XF86VidModeQueryVersion(glDisplay, &vidModeMajorVersion, &vidModeMinorVersion); - - ZZLog::Error_Log("XF86VidModeExtension-Version %d.%d.", vidModeMajorVersion, vidModeMinorVersion); -} + if (!glDisplay or !glWindow) return; + + u32 mask = SubstructureRedirectMask | SubstructureNotifyMask; + // Setup a new event structure + XClientMessageEvent cme; + + cme.type = ClientMessage; + cme.send_event = True; + cme.display = glDisplay; + cme.window = glWindow; + cme.message_type = XInternAtom(glDisplay, "_NET_WM_STATE", False); + cme.format = 32; + cme.data.l[0] = _NET_WM_STATE_TOGGLE; + cme.data.l[1] = (u32)XInternAtom(glDisplay, "_NET_WM_STATE_FULLSCREEN", False); + cme.data.l[2] = 0; + cme.data.l[3] = 0; + + // send the event + if (!XSendEvent(glDisplay, RootWindow(glDisplay, vi->screen), False, mask, (XEvent*)(&cme))) + ZZLog::Error_Log("Failed to send event: toggle fullscreen"); + else + fullScreen = (!fullScreen); + + // Apply the change + XSync(glDisplay, False); + + // update info structure + GetWindowSize(); + + // Grab key if needed + UpdateGrabKey(); + + // Hide the cursor in the right bottom corner + if(fullScreen) + XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, width, height); + +} bool GLWindow::DisplayWindow(int _width, int _height) { @@ -167,95 +209,43 @@ bool GLWindow::DisplayWindow(int _width, int _height) attr.colormap = cmap; attr.border_pixel = 0; - attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; + attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | + StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask | + EnterWindowMask | LeaveWindowMask | FocusChangeMask ; GetGLXVersion(); - - if (fullScreen) - { - int dpyWidth, dpyHeight; - int modeNum = 0, bestMode = 0; - XF86VidModeModeInfo **modes = NULL; - - GetGLXVidModeVersion(); - - XF86VidModeGetAllModeLines(glDisplay, glScreen, &modeNum, &modes); - if (modeNum > 0 && modes != NULL) - { - /* save desktop-resolution before switching modes */ - deskMode = *modes[0]; + glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen), + 0, 0, _width, _height, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, + &attr); - /* look for mode with requested resolution */ + /* Allow to kill properly the window */ + Atom wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True); + XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1); - for (int i = 0; i < modeNum; i++) - { - if ((modes[i]->hdisplay == _width) && (modes[i]->vdisplay == _height)) - { - bestMode = i; - } - } + // Set icon name + XSetIconName(glDisplay, glWindow, "ZZogl-pg"); - XF86VidModeSwitchToMode(glDisplay, glScreen, modes[bestMode]); - - XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0); - dpyWidth = modes[bestMode]->hdisplay; - dpyHeight = modes[bestMode]->vdisplay; - ZZLog::Error_Log("Resolution %dx%d.", dpyWidth, dpyHeight); - XFree(modes); - - /* create a fullscreen window */ - attr.override_redirect = True; - glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen), - 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, - &attr); - XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 0, 0); - XMapRaised(glDisplay, glWindow); - XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime); - } - else - { - ZZLog::Error_Log("Failed to start fullscreen. If you received the \n" - "\"XFree86-VidModeExtension\" extension is missing, add\n" - "Load \"extmod\"\n" - "to your X configuration file (under the Module Section)"); - fullScreen = false; - } - } - - if (!fullScreen) - { - // create a window in window mode - glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen), - 0, 0, _width, _height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &attr); - - // only set window title and handle wm_delete_events if in windowed mode - Atom wmDelete; - wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True); - XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1); - - XSetStandardProperties(glDisplay, glWindow, "ZZOgl-PG", "ZZOgl-PG", None, NULL, 0, NULL); - XMapRaised(glDisplay, glWindow); - XMoveWindow(glDisplay, glWindow, x, y); - } + // Draw the window + XMapRaised(glDisplay, glWindow); + XSync(glDisplay, false); // connect the glx-context to the window glXMakeCurrent(glDisplay, glWindow, context); - GetWindowSize(); - if (glXIsDirect(glDisplay, context)) ZZLog::Error_Log("You have Direct Rendering!"); else ZZLog::Error_Log("No Direct Rendering possible!"); - // better for pad plugin key input (thc) - XSelectInput(glDisplay, glWindow, ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | - FocusChangeMask); + if (fullScreen) { + ToggleFullscreen(); + } else { + // Restore the window position + XMoveWindow(glDisplay, glWindow, x, y); + GetWindowSize(); + } return true; } @@ -267,16 +257,16 @@ void GLWindow::SwapGLBuffers() void GLWindow::SetTitle(char *strtitle) { - if (!conf.fullscreen()) + if (!fullScreen) { XTextProperty prop; - memset(&prop, 0, sizeof(prop)); - char* ptitle = strtitle; + memset(&prop, 0, sizeof(prop)); + char* ptitle = strtitle; if (XStringListToTextProperty(&ptitle, 1, &prop)) XSetWMName(glDisplay, glWindow, &prop); - XFree(prop.value); + XFree(prop.value); } } @@ -293,14 +283,17 @@ void GLWindow::ResizeCheck() height = event.xconfigure.height; } - if ((event.xconfigure.x != x) || (event.xconfigure.y != y)) - { - // Fixme; x&y occassionally gives values near the top left corner rather then the real values, - // causing the window to change positions when adjusting ZZOgl's settings. - x = event.xconfigure.x; - y = event.xconfigure.y; - } + if (!fullScreen) { + if ((event.xconfigure.x != x) || (event.xconfigure.y != y)) + { + // Fixme; x&y occassionally gives values near the top left corner rather then the real values, + // causing the window to change positions when adjusting ZZOgl's settings. + x = event.xconfigure.x; + y = event.xconfigure.y; + } + } } + } #endif diff --git a/plugins/zzogl-pg/opengl/Linux/Linux.cpp b/plugins/zzogl-pg/opengl/Linux/Linux.cpp index 78169e9033..aaf3f440a3 100644 --- a/plugins/zzogl-pg/opengl/Linux/Linux.cpp +++ b/plugins/zzogl-pg/opengl/Linux/Linux.cpp @@ -53,10 +53,7 @@ void CALLBACK GSkeyEvent(keyEvent *ev) break; case XK_Escape: - if (conf.fullscreen()) - { - GSclose(); - } + GSclose(); break; case XK_Shift_L: @@ -69,6 +66,10 @@ void CALLBACK GSkeyEvent(keyEvent *ev) case XK_Alt_R: bAlt = true; break; + + case XK_Return: + if (bAlt) + GLWin.ToggleFullscreen(); } break;