From b087e0f9525e3f843efee9ec3a24c6f6dcc2a979 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 20 Jun 2011 17:54:27 +0000 Subject: [PATCH] Merged following revisions from svn/trunk which address problems with toggling fullscreen on/off under modern X11 window managers ------------------------------------------------------------------------ r12573 | robert | 2011-06-20 12:25:52 +0100 (Mon, 20 Jun 2011) | 2 lines Added catch for window manager doesn't set the window size to full screen. ------------------------------------------------------------------------ r12572 | robert | 2011-06-20 10:28:39 +0100 (Mon, 20 Jun 2011) | 4 lines Added check against Traits::overrideRedirct to prevent the fullscreen workaround being run when overrideRedirect is on as overrideRedirect switches off the window managers ability to manage the fullscreen so the problem doesn't need working around. ------------------------------------------------------------------------ r12571 | robert | 2011-06-20 10:22:57 +0100 (Mon, 20 Jun 2011) | 2 lines Introduced a workaround for fullscreen toggle issues under modern X11 window managers. --- src/osgViewer/GraphicsWindowX11.cpp | 80 +++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index c95b2f399..1f18e5d9d 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -396,8 +396,7 @@ bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, in bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration; Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True); - Atom netWMStateFullscreenAtom = XInternAtom(display, - "_NET_WM_STATE_FULLSCREEN", True); + Atom netWMStateFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True); if (netWMStateAtom != None && netWMStateFullscreenAtom != None) { XEvent xev; @@ -439,28 +438,34 @@ bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag) if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None ) { - wmHints.flags = 0; - wmHints.functions = MWM_FUNC_ALL; - wmHints.decorations = MWM_DECOR_ALL; - wmHints.inputMode = 0; - wmHints.status = 0; - - if (!flag) + if (flag) { - wmHints.flags = MWM_HINTS_DECORATIONS; - wmHints.decorations = 0; + wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; + wmHints.functions = MWM_FUNC_ALL; + wmHints.decorations = MWM_DECOR_ALL; + wmHints.inputMode = 0; + wmHints.status = 0; + + // if traits says not resize we want to set the functions to exlude MWM_FUNC_RESIZE, + // but this bitmask needs to be set if the MWM_FUNC_ALL bit is already set in order to toggle it off. + if (_traits.valid() && !_traits->supportsResize) wmHints.functions = wmHints.functions | MWM_FUNC_RESIZE; + } else { - wmHints.flags |= MWM_HINTS_FUNCTIONS; - if (_traits.valid() && !_traits->supportsResize) wmHints.functions |= MWM_FUNC_RESIZE; + wmHints.flags = MWM_HINTS_DECORATIONS; + wmHints.functions = 0; + wmHints.decorations = 0; + wmHints.inputMode = 0; + wmHints.status = 0; } + XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 ); result = true; } else { - OSG_NOTICE<<"Error: GraphicsWindowX11::setBorder(" << flag << ") - couldn't change decorations." << std::endl; + OSG_NOTICE<<"Error: GraphicsWindowX11::setWindowDecorationImplementation(" << flag << ") - couldn't change decorations." << std::endl; result = false; } @@ -479,13 +484,13 @@ bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width Display* display = getDisplayToUse(); + checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration); + XMoveResizeWindow(display, _window, x, y, width, height); XFlush(display); XSync(display, 0); - - checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration); - + // add usleep here to give window manager a chance to handle the request, if // we don't add this sleep then any X11 calls right afterwards can produce // X11 errors. @@ -854,10 +859,45 @@ bool GraphicsWindowX11::createWindow() OSG_INFO<<"Setting override redirect"<x; + int y = _traits->y; + int width = _traits->width; + int height = _traits->height; + + { + // follows is hack to get around problems with toggling off full screen with modern X11 window + // managers that try to be too clever when toggling off full screen and ignore the window size + // calls made by the OSG when the initial window size is full screen. + unsigned int screenWidth; + unsigned int screenHeight; + wsi->getScreenResolution(*_traits, screenWidth, screenHeight); + + bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !_traits->windowDecoration; + + if (isFullScreen) + { + // artifically reduce the initial window size so that the windowing + // system has a size to go back to when toggling off full screen, + // we don't have to worry about the window being initially smaller as the + // setWindowDecoration(..) implementation with enable full screen for us + x = width/4; + y = height/4; + width /= 2; + height /= 2; + } + } + _window = XCreateWindow( _display, _parent, - _traits->x, - _traits->y, - _traits->width, _traits->height, 0, + x, + y, + width, height, 0, _visualInfo->depth, InputOutput, _visualInfo->visual, mask, &swatt );