diff --git a/RenderSystems/GLSupport/CMakeLists.txt b/RenderSystems/GLSupport/CMakeLists.txt index 6af0375bb46..0e950b8330f 100644 --- a/RenderSystems/GLSupport/CMakeLists.txt +++ b/RenderSystems/GLSupport/CMakeLists.txt @@ -67,7 +67,7 @@ elseif (APPLE) elseif (UNIX) if(OGRE_GLSUPPORT_USE_EGL) file(GLOB PLATFORM_HEADERS "include/EGL/X11/*.h" "include/EGL/*.h") - file(GLOB PLATFORM_SOURCES "src/EGL/X11/*.cpp" "src/EGL/*.cpp") + file(GLOB PLATFORM_SOURCES "src/EGL/X11/*.cpp" "src/EGL/*.cpp" "src/X11/*.cpp") set(NATIVE_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/EGL @@ -75,7 +75,7 @@ elseif (UNIX) set(PLATFORM_LIBS ${X11_LIBRARIES} ${X11_Xrandr_LIB} ${EGL_LIBRARIES}) else() file(GLOB PLATFORM_HEADERS "include/GLX/*.h") - file(GLOB PLATFORM_SOURCES "src/GLX/*.cpp") + file(GLOB PLATFORM_SOURCES "src/GLX/*.cpp" "src/X11/*.cpp") set(NATIVE_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/GLX @@ -83,6 +83,7 @@ elseif (UNIX) set(PLATFORM_LIBS ${X11_LIBRARIES} ${X11_Xrandr_LIB} ${OPENGL_gl_LIBRARY}) endif() + list(APPEND NATIVE_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/src/X11/") endif () file(GLOB GLSUPPORT_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") diff --git a/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLSupport.cpp b/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLSupport.cpp index c8fe6e24e2f..d0c7111f8fc 100644 --- a/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLSupport.cpp +++ b/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLSupport.cpp @@ -34,11 +34,10 @@ THE SOFTWARE. #include "OgreX11EGLSupport.h" #include "OgreX11EGLWindow.h" +#include "OgreX11.h" #include "OgreGLUtil.h" -#include - namespace Ogre { GLNativeSupport* getGLSupport(int profile) { @@ -53,7 +52,6 @@ namespace Ogre { // A connection that is NOT shared to enable independent event processing: mNativeDisplay = getNativeDisplay(); - int dummy; if(mNativeDisplay == EGL_DEFAULT_DISPLAY) { @@ -61,50 +59,11 @@ namespace Ogre { mCurrentMode.width = 0; mCurrentMode.height = 0; mCurrentMode.refreshRate = 0; - mOriginalMode = mCurrentMode; mVideoModes.push_back(mCurrentMode); } - else if (XQueryExtension(mNativeDisplay, "RANDR", &dummy, &dummy, &dummy)) + else { - XRRScreenConfiguration *screenConfig; - - screenConfig = XRRGetScreenInfo(mNativeDisplay, DefaultRootWindow(mNativeDisplay)); - - if (screenConfig) - { - XRRScreenSize *screenSizes; - int nSizes = 0; - Rotation currentRotation; - int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); - - screenSizes = XRRConfigSizes(screenConfig, &nSizes); - - mCurrentMode.width = screenSizes[currentSizeID].width; - mCurrentMode.height = screenSizes[currentSizeID].height; - mCurrentMode.refreshRate = XRRConfigCurrentRate(screenConfig); - - mOriginalMode = mCurrentMode; - - for (int sizeID = 0; sizeID < nSizes; sizeID++) - { - short *rates; - int nRates = 0; - - rates = XRRConfigRates(screenConfig, sizeID, &nRates); - - for (int rate = 0; rate < nRates; rate++) - { - VideoMode mode; - - mode.width = screenSizes[sizeID].width; - mode.height = screenSizes[sizeID].height; - mode.refreshRate = rates[rate]; - - mVideoModes.push_back(mode); - } - } - XRRFreeScreenConfigInfo(screenConfig); - } + getXVideoModes(mNativeDisplay, mCurrentMode, mVideoModes); } if(mVideoModes.empty()) // none of the above worked @@ -112,12 +71,11 @@ namespace Ogre { mCurrentMode.width = DisplayWidth(mNativeDisplay, DefaultScreen(mNativeDisplay)); mCurrentMode.height = DisplayHeight(mNativeDisplay, DefaultScreen(mNativeDisplay)); mCurrentMode.refreshRate = 0; - - mOriginalMode = mCurrentMode; - mVideoModes.push_back(mCurrentMode); } + mOriginalMode = mCurrentMode; + EGLConfig *glConfigs; int config, nConfigs = 0; @@ -156,17 +114,13 @@ namespace Ogre { { if (!mNativeDisplay) { - mNativeDisplay = (NativeDisplayType)XOpenDisplay(NULL); + mNativeDisplay = getXDisplay(NULL, mAtomDeleteWindow, mAtomFullScreen, mAtomState); if (mNativeDisplay == EGL_DEFAULT_DISPLAY) { LogManager::getSingleton().logWarning("Couldn't open X display"); return mNativeDisplay; } - - mAtomDeleteWindow = XInternAtom((Display*)mNativeDisplay, "WM_DELETE_WINDOW", True); - mAtomFullScreen = XInternAtom((Display*)mNativeDisplay, "_NET_WM_STATE_FULLSCREEN", True); - mAtomState = XInternAtom((Display*)mNativeDisplay, "_NET_WM_STATE", True); } return mNativeDisplay; diff --git a/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLWindow.cpp b/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLWindow.cpp index 348acfdd162..5e16be7e7d6 100644 --- a/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLWindow.cpp +++ b/RenderSystems/GLSupport/src/EGL/X11/OgreX11EGLWindow.cpp @@ -34,23 +34,7 @@ THE SOFTWARE. #include "OgreX11EGLSupport.h" #include "OgreX11EGLWindow.h" - -#include -#include -#include - -extern "C" -{ - static int safeXErrorHandler(Display *display, XErrorEvent *event) - { - // Ignore all XErrorEvents - return 0; - } - - - int (*oldXErrorHandler)(Display *, XErrorEvent*); -} - +#include "OgreX11.h" namespace Ogre { X11EGLWindow::X11EGLWindow(X11EGLSupport *glsupport) @@ -63,19 +47,14 @@ namespace Ogre { X11EGLWindow::~X11EGLWindow() { - mNativeDisplay = mGLSupport->getNativeDisplay(); - // Ignore fatal XErrorEvents from stale handles. - oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); if (mWindow && mIsTopLevel) { - XDestroyWindow((Display*)mNativeDisplay, (Window)mWindow); + destroyXWindow(mNativeDisplay, mWindow); } - XSetErrorHandler(oldXErrorHandler); mWindow = 0; - } void X11EGLWindow::getCustomAttribute( const String& name, void* pData ) @@ -138,23 +117,7 @@ namespace Ogre { } } - // Ignore fatal XErrorEvents during parameter validation: - oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); - - // Validate parentWindowHandle - if (mParentWindow != DefaultRootWindow((Display*)mNativeDisplay)) - { - XWindowAttributes windowAttrib; - - if (!XGetWindowAttributes((Display*)mNativeDisplay, mParentWindow, &windowAttrib) || - windowAttrib.root != DefaultRootWindow((Display*)mNativeDisplay)) - { - OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, - "Invalid parentWindowHandle (wrong server or screen)"); - } - } - - XSetErrorHandler(oldXErrorHandler); + validateParentWindow(mNativeDisplay, mParentWindow); mIsTopLevel = (!mIsExternal && mParentWindow == DefaultRootWindow((Display*)mNativeDisplay)); @@ -163,86 +126,15 @@ namespace Ogre { void X11EGLWindow::createNativeWindow( int &left, int &top, uint &width, uint &height, String &title ) { mEglDisplay = mGLSupport->getGLDisplay();//todo - XSetWindowAttributes attr; - ulong mask; XVisualInfo *visualInfo = mGLSupport->getVisualFromFBConfig(mEglConfig); - attr.background_pixel = 0; - attr.border_pixel = 0; - attr.colormap = XCreateColormap((Display*)mNativeDisplay, - DefaultRootWindow((Display*)mNativeDisplay), - visualInfo->visual, - AllocNone); - attr.event_mask = StructureNotifyMask | VisibilityChangeMask | FocusChangeMask; - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - if(mIsFullScreen && mGLSupport->mAtomFullScreen == None) - { - LogManager::getSingleton().logMessage("X11EGLWindow::switchFullScreen: Your WM has no fullscreen support"); - - // A second best approach for outdated window managers - attr.backing_store = NotUseful; - attr.save_under = False; - attr.override_redirect = True; - mask |= CWSaveUnder | CWBackingStore | CWOverrideRedirect; - left = top = 0; - } - // Create window on server - mWindow = (NativeWindowType)XCreateWindow((Display*)mNativeDisplay, - mParentWindow, - left, top, width, height, - 0, visualInfo->depth, - InputOutput, - visualInfo->visual, mask, &attr); - XFree(visualInfo); - - if(!mWindow) - { - OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, - "Unable to create an X NativeWindowType", - "EGLWindow::create"); - } + mWindow = createXWindow(mNativeDisplay, mParentWindow, visualInfo, left, top, width, height, + mGLSupport->mAtomFullScreen, mIsFullScreen); if (mIsTopLevel) { - XWMHints *wmHints; - XSizeHints *sizeHints; - - // Is this really necessary ? Which broken WM might need it? - if ((wmHints = XAllocWMHints()) != NULL) - { - wmHints->initial_state = NormalState; - wmHints->input = True; - wmHints->flags = StateHint | InputHint; - } - - // Is this really necessary ? Which broken WM might need it? - if ((sizeHints = XAllocSizeHints()) != NULL) - { - sizeHints->flags = USPosition; - } - - XTextProperty titleprop; - char *lst = const_cast(title.c_str()); - XStringListToTextProperty((char **)&lst, 1, &titleprop); - XSetWMProperties((Display*)mNativeDisplay, (Window)mWindow, &titleprop, - NULL, NULL, 0, sizeHints, wmHints, NULL); - - XFree(titleprop.value); - XFree(wmHints); - XFree(sizeHints); - - XSetWMProtocols((Display*)mNativeDisplay, (Window)mWindow, &mGLSupport->mAtomDeleteWindow, 1); - - XWindowAttributes windowAttrib; - - XGetWindowAttributes((Display*)mNativeDisplay, (Window)mWindow, &windowAttrib); - - left = windowAttrib.x; - top = windowAttrib.y; - width = windowAttrib.width; - height = windowAttrib.height; + finaliseTopLevel(mNativeDisplay, mWindow, left, top, width, height, title, mGLSupport->mAtomDeleteWindow); } mEglSurface = createSurfaceFromWindow(mGLSupport->getGLDisplay(), mWindow); @@ -311,28 +203,9 @@ namespace Ogre { if (mClosed || !mWindow) return; - XWindowAttributes windowAttrib; - - Window parent, root, *children; - uint nChildren; - - XQueryTree((Display*)mNativeDisplay, (Window)mWindow, &root, &parent, &children, &nChildren); - - if (children) - XFree(children); - - XGetWindowAttributes((Display*)mNativeDisplay, parent, &windowAttrib); - - if (mIsTopLevel && !mIsFullScreen) - { - // offset from window decorations - mLeft = windowAttrib.x; - mTop = windowAttrib.y; - // w/ h of the actual renderwindow - XGetWindowAttributes((Display*)mNativeDisplay, (Window)mWindow, &windowAttrib); - } - - resize(windowAttrib.width, windowAttrib.height); + uint width, height; + queryRect(mNativeDisplay, mWindow, mLeft, mTop, width, height, mIsTopLevel && !mIsFullScreen); + resize(width, height); } void X11EGLWindow::switchFullScreen(bool fullscreen) { diff --git a/RenderSystems/GLSupport/src/GLX/OgreGLXGLSupport.cpp b/RenderSystems/GLSupport/src/GLX/OgreGLXGLSupport.cpp index 73ea617f3a5..578a94abbd0 100644 --- a/RenderSystems/GLSupport/src/GLX/OgreGLXGLSupport.cpp +++ b/RenderSystems/GLSupport/src/GLX/OgreGLXGLSupport.cpp @@ -38,11 +38,8 @@ #include "OgreGLUtil.h" -#ifndef Status -#define Status int -#endif +#include "OgreX11.h" -#include #include static bool ctxErrorOccurred = false; @@ -73,50 +70,7 @@ namespace Ogre // A connection that is NOT shared to enable independent event processing: mXDisplay = getXDisplay(); - int dummy; - - if (XQueryExtension(mXDisplay, "RANDR", &dummy, &dummy, &dummy)) - { - XRRScreenConfiguration *screenConfig; - - screenConfig = XRRGetScreenInfo(mXDisplay, DefaultRootWindow(mXDisplay)); - - if (screenConfig) - { - XRRScreenSize *screenSizes; - int nSizes = 0; - Rotation currentRotation; - int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); - - screenSizes = XRRConfigSizes(screenConfig, &nSizes); - - mCurrentMode.width = screenSizes[currentSizeID].width; - mCurrentMode.height = screenSizes[currentSizeID].height; - mCurrentMode.refreshRate = XRRConfigCurrentRate(screenConfig); - - mOriginalMode = mCurrentMode; - - for(int sizeID = 0; sizeID < nSizes; sizeID++) - { - short *rates; - int nRates = 0; - - rates = XRRConfigRates(screenConfig, sizeID, &nRates); - - for (int rate = 0; rate < nRates; rate++) - { - VideoMode mode; - - mode.width = screenSizes[sizeID].width; - mode.height = screenSizes[sizeID].height; - mode.refreshRate = rates[rate]; - - mVideoModes.push_back(mode); - } - } - XRRFreeScreenConfigInfo(screenConfig); - } - } + getXVideoModes(mXDisplay, mCurrentMode, mVideoModes); if(mVideoModes.empty()) { @@ -124,11 +78,11 @@ namespace Ogre mCurrentMode.height = DisplayHeight(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.refreshRate = 0; - mOriginalMode = mCurrentMode; - mVideoModes.push_back(mCurrentMode); } + mOriginalMode = mCurrentMode; + GLXFBConfig *fbConfigs; int config, nConfigs = 0; diff --git a/RenderSystems/GLSupport/src/GLX/OgreGLXWindow.cpp b/RenderSystems/GLSupport/src/GLX/OgreGLXWindow.cpp index c537a1ad963..df60ca5fac4 100644 --- a/RenderSystems/GLSupport/src/GLX/OgreGLXWindow.cpp +++ b/RenderSystems/GLSupport/src/GLX/OgreGLXWindow.cpp @@ -37,25 +37,10 @@ #include "OgreGLXContext.h" #include "OgreGLXGLSupport.h" +#include "OgreX11.h" -#include -#include #include -#include -#include - -#include "OgreGLRenderSystemCommon.h" - -namespace { - int safeXErrorHandler (Display *display, XErrorEvent *event) - { - // Ignore all XErrorEvents - return 0; - } - int (*oldXErrorHandler)(Display *, XErrorEvent*); -} - namespace Ogre { //-------------------------------------------------------------------------------------------------// @@ -72,12 +57,9 @@ namespace Ogre destroy(); - // Ignore fatal XErrorEvents from stale handles. - oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); - if (mWindow && mIsTopLevel) { - XDestroyWindow(xDisplay, mWindow); + destroyXWindow(xDisplay, mWindow); } if (mContext) @@ -85,8 +67,6 @@ namespace Ogre delete mContext; } - XSetErrorHandler(oldXErrorHandler); - mContext = 0; mWindow = 0; } @@ -207,20 +187,7 @@ namespace Ogre border = opt->second; } - // Ignore fatal XErrorEvents during parameter validation: - oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); - // Validate parentWindowHandle - - if (parentWindow != DefaultRootWindow(xDisplay)) - { - XWindowAttributes windowAttrib; - - if (! XGetWindowAttributes(xDisplay, parentWindow, &windowAttrib) || - windowAttrib.root != DefaultRootWindow(xDisplay)) - { - OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Invalid parentWindowHandle (wrong server or screen)"); - } - } + validateParentWindow(xDisplay, parentWindow); // Derive fbConfig ::GLXFBConfig fbConfig = 0; @@ -237,8 +204,6 @@ namespace Ogre mIsExternal = (glxDrawable != 0); - XSetErrorHandler(oldXErrorHandler); - if (! fbConfig) { int minComponentSize = minBufferSize; @@ -324,83 +289,14 @@ namespace Ogre if (! mIsExternal) { - XSetWindowAttributes attr; - ulong mask; XVisualInfo *visualInfo = mGLSupport->getVisualFromFBConfig (fbConfig); - attr.background_pixel = 0; - attr.border_pixel = 0; - attr.colormap = XCreateColormap(xDisplay, DefaultRootWindow(xDisplay), visualInfo->visual, AllocNone); - attr.event_mask = StructureNotifyMask | VisibilityChangeMask | FocusChangeMask; - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - if(mIsFullScreen && mGLSupport->mAtomFullScreen == None) - { - LogManager::getSingleton().logMessage("GLXWindow::switchFullScreen: Your WM has no fullscreen support"); - - // A second best approach for outdated window managers - attr.backing_store = NotUseful; - attr.save_under = False; - attr.override_redirect = True; - mask |= CWSaveUnder | CWBackingStore | CWOverrideRedirect; - left = top = 0; - } - // Create window on server - mWindow = XCreateWindow(xDisplay, parentWindow, left, top, width, height, 0, visualInfo->depth, InputOutput, visualInfo->visual, mask, &attr); - - XFree(visualInfo); - - if(!mWindow) - { - OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to create an X Window", "GLXWindow::create"); - } + mWindow = createXWindow(xDisplay, parentWindow, visualInfo, left, top, width, height, mGLSupport->mAtomFullScreen, mIsFullScreen); if (mIsTopLevel) { - XWMHints *wmHints; - XSizeHints *sizeHints; - - if ((wmHints = XAllocWMHints()) != NULL) - { - wmHints->initial_state = NormalState; - wmHints->input = True; - wmHints->flags = StateHint | InputHint; - } - - // Is this really necessary ? Which broken WM might need it? - if ((sizeHints = XAllocSizeHints()) != NULL) - { - // Is this really necessary ? Which broken WM might need it? - sizeHints->flags = USPosition; - - if(!fullScreen && border == "fixed") - { - sizeHints->min_width = sizeHints->max_width = width; - sizeHints->min_height = sizeHints->max_height = height; - sizeHints->flags |= PMaxSize | PMinSize; - } - } - - XTextProperty titleprop; - char *lst = &title[0]; - XStringListToTextProperty(&lst, 1, &titleprop); - XSetWMProperties(xDisplay, mWindow, &titleprop, NULL, NULL, 0, sizeHints, wmHints, NULL); - - XFree(titleprop.value); - XFree(wmHints); - XFree(sizeHints); - - XSetWMProtocols(xDisplay, mWindow, &mGLSupport->mAtomDeleteWindow, 1); - - XWindowAttributes windowAttrib; - - XGetWindowAttributes(xDisplay, mWindow, &windowAttrib); - - left = windowAttrib.x; - top = windowAttrib.y; - width = windowAttrib.width; - height = windowAttrib.height; + finaliseTopLevel(xDisplay, mWindow, left, top, width, height, title, mGLSupport->mAtomDeleteWindow); } glxDrawable = mWindow; @@ -590,28 +486,9 @@ namespace Ogre return; Display* xDisplay = mGLSupport->getXDisplay(); - XWindowAttributes windowAttrib; - - Window parent, root, *children; - uint nChildren; - - XQueryTree(xDisplay, mWindow, &root, &parent, &children, &nChildren); - - if (children) - XFree(children); - - XGetWindowAttributes(xDisplay, parent, &windowAttrib); - - if (mIsTopLevel && !mIsFullScreen) - { - // offset from window decorations - mLeft = windowAttrib.x; - mTop = windowAttrib.y; - // w/ h of the actual renderwindow - XGetWindowAttributes(xDisplay, mWindow, &windowAttrib); - } - - resize(windowAttrib.width, windowAttrib.height); + uint width, height; + queryRect(xDisplay, mWindow, mLeft, mTop, width, height, mIsTopLevel && !mIsFullScreen); + resize(width, height); } //-------------------------------------------------------------------------------------------------// diff --git a/RenderSystems/GLSupport/src/X11/OgreX11.cpp b/RenderSystems/GLSupport/src/X11/OgreX11.cpp new file mode 100644 index 00000000000..38b8bc6b2be --- /dev/null +++ b/RenderSystems/GLSupport/src/X11/OgreX11.cpp @@ -0,0 +1,206 @@ +#include +#include + +#include + +namespace { + int safeXErrorHandler (Display *display, XErrorEvent *event) + { + // Ignore all XErrorEvents + return 0; + } + int (*oldXErrorHandler)(Display *, XErrorEvent*); +} + +namespace Ogre +{ +Display* getXDisplay(Display* glDisplay, Atom& deleteWindow, Atom& fullScreen, Atom& state) +{ + char* displayString = glDisplay ? DisplayString(glDisplay) : NULL; + + auto xDisplay = XOpenDisplay(displayString); + + if (!xDisplay) + return xDisplay; + + deleteWindow = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True); + fullScreen = XInternAtom(xDisplay, "_NET_WM_STATE_FULLSCREEN", True); + state = XInternAtom(xDisplay, "_NET_WM_STATE", True); + return xDisplay; +} + +void validateParentWindow(Display* display, Window parentWindow) +{ + // Ignore fatal XErrorEvents during parameter validation: + oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); + + // Validate parentWindowHandle + if (parentWindow != DefaultRootWindow(display)) + { + XWindowAttributes windowAttrib; + + if (!XGetWindowAttributes(display, parentWindow, &windowAttrib) || + windowAttrib.root != DefaultRootWindow(display)) + { + OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Invalid parentWindowHandle (wrong server or screen)"); + } + } + + XSetErrorHandler(oldXErrorHandler); +} + +Window createXWindow(Display* display, Window parent, XVisualInfo* visualInfo, int& left, int& top, uint& width, + uint& height, Atom wmFullScreen, bool fullScreen) +{ + XSetWindowAttributes attr; + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(display, DefaultRootWindow(display), visualInfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | VisibilityChangeMask | FocusChangeMask; + + ulong mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + if (fullScreen && wmFullScreen == None) + { + LogManager::getSingleton().logWarning("createXWindow: Your WM has no fullscreen support"); + + // A second best approach for outdated window managers + attr.backing_store = NotUseful; + attr.save_under = False; + attr.override_redirect = True; + mask |= CWSaveUnder | CWBackingStore | CWOverrideRedirect; + left = top = 0; + } + + auto window = XCreateWindow(display, parent, left, top, width, height, 0, visualInfo->depth, InputOutput, + visualInfo->visual, mask, &attr); + XFree(visualInfo); + + if (!window) + { + OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to create an X Window"); + } + + return window; +} + +void destroyXWindow(Display* display, Window window) +{ + // Ignore fatal XErrorEvents from stale handles. + oldXErrorHandler = XSetErrorHandler(safeXErrorHandler); + XDestroyWindow(display, window); + XSetErrorHandler(oldXErrorHandler); +} + +void queryRect(Display* display, Window window, int& left, int& top, uint& width, uint& height, bool queryOffset) +{ + XWindowAttributes windowAttrib; + + Window parent, root, *children; + uint nChildren; + + XQueryTree(display, window, &root, &parent, &children, &nChildren); + + if (children) + XFree(children); + + XGetWindowAttributes(display, parent, &windowAttrib); + + if (queryOffset) + { + // offset from window decorations + left = windowAttrib.x; + top = windowAttrib.y; + // w/ h of the actual renderwindow + XGetWindowAttributes(display, window, &windowAttrib); + } + + width = windowAttrib.width; + height = windowAttrib.height; +} + +void finaliseTopLevel(Display* display, Window window, int& left, int& top, uint& width, uint& height, String& title, Atom wmDelete) +{ + XWMHints* wmHints; + XSizeHints* sizeHints; + + // Is this really necessary ? Which broken WM might need it? + if ((wmHints = XAllocWMHints()) != NULL) + { + wmHints->initial_state = NormalState; + wmHints->input = True; + wmHints->flags = StateHint | InputHint; + } + + // Is this really necessary ? Which broken WM might need it? + if ((sizeHints = XAllocSizeHints()) != NULL) + { + sizeHints->flags = USPosition; + } + + XTextProperty titleprop; + char* lst = const_cast(title.c_str()); + XStringListToTextProperty(&lst, 1, &titleprop); + XSetWMProperties(display, window, &titleprop, NULL, NULL, 0, sizeHints, wmHints, NULL); + + XFree(titleprop.value); + XFree(wmHints); + XFree(sizeHints); + + XSetWMProtocols(display, window, &wmDelete, 1); + + XWindowAttributes windowAttrib; + + XGetWindowAttributes(display, window, &windowAttrib); + + left = windowAttrib.x; + top = windowAttrib.y; + width = windowAttrib.width; + height = windowAttrib.height; +} + +bool getXVideoModes(Display* display, GLRenderSystemCommon::VideoMode& currentMode, + GLRenderSystemCommon::VideoModes& videoModes) +{ + int dummy; + if (!XQueryExtension(display, "RANDR", &dummy, &dummy, &dummy)) + return false; + + auto screenConfig = XRRGetScreenInfo(display, DefaultRootWindow(display)); + if (!screenConfig) + return false; + + XRRScreenSize* screenSizes; + int nSizes = 0; + Rotation currentRotation; + int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); + + screenSizes = XRRConfigSizes(screenConfig, &nSizes); + + currentMode.width = screenSizes[currentSizeID].width; + currentMode.height = screenSizes[currentSizeID].height; + currentMode.refreshRate = XRRConfigCurrentRate(screenConfig); + + for (int sizeID = 0; sizeID < nSizes; sizeID++) + { + short* rates; + int nRates = 0; + + rates = XRRConfigRates(screenConfig, sizeID, &nRates); + + for (int rate = 0; rate < nRates; rate++) + { + GLRenderSystemCommon::VideoMode mode; + + mode.width = screenSizes[sizeID].width; + mode.height = screenSizes[sizeID].height; + mode.refreshRate = rates[rate]; + + videoModes.push_back(mode); + } + } + XRRFreeScreenConfigInfo(screenConfig); + + return true; +} +} // namespace Ogre \ No newline at end of file diff --git a/RenderSystems/GLSupport/src/X11/OgreX11.h b/RenderSystems/GLSupport/src/X11/OgreX11.h new file mode 100644 index 00000000000..39d116ae5a0 --- /dev/null +++ b/RenderSystems/GLSupport/src/X11/OgreX11.h @@ -0,0 +1,39 @@ +// This file is part of the OGRE project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at https://www.ogre3d.org/licensing. +// SPDX-License-Identifier: MIT + +#ifndef OGRE_X11_H__ +#define OGRE_X11_H__ + +#include +#include + +#ifndef Status +#define Status int +#endif + +#include +#include + +namespace Ogre +{ +Display* getXDisplay(Display* glDisplay, Atom& deleteWindow, Atom& fullScreen, Atom& state); + +void validateParentWindow(Display* display, Window parentWindow); + +Window createXWindow(Display* display, Window parent, XVisualInfo* visualInfo, int& left, int& top, uint& width, + uint& height, Atom wmFullScreen, bool fullScreen); + +void destroyXWindow(Display* display, Window window); + +void queryRect(Display* display, Window window, int& left, int& top, uint& width, uint& height, bool queryOffset); + +void finaliseTopLevel(Display* display, Window window, int& left, int& top, uint& width, uint& height, String& title, + Atom wmDelete); + +bool getXVideoModes(Display* display, GLRenderSystemCommon::VideoMode& currentMode, + GLRenderSystemCommon::VideoModes& videoModes); +} // namespace Ogre + +#endif \ No newline at end of file