ovr_sdk
diff LibOVR/Src/Displays/OVR_Linux_SDKWindow.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Displays/OVR_Linux_SDKWindow.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,649 @@ 1.4 +/******************************************************************************* 1.5 + 1.6 +Filename : OVR_Linux_SDKWindow.cpp 1.7 +Content : SDK generated Linux window. 1.8 +Created : October 1, 2014 1.9 +Authors : James Hughes 1.10 + 1.11 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.12 + 1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.15 +which is provided at the time of installation or download, or which 1.16 +otherwise accompanies this software in either electronic or hard copy form. 1.17 + 1.18 +You may obtain a copy of the License at 1.19 + 1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.21 + 1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.23 +distributed under the License is distributed on an "AS IS" BASIS, 1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.25 +See the License for the specific language governing permissions and 1.26 +limitations under the License. 1.27 + 1.28 +*******************************************************************************/ 1.29 + 1.30 +#include "OVR_Linux_SDKWindow.h" 1.31 +#include "../Kernel/OVR_Log.h" 1.32 +#include "../Kernel/OVR_Log.h" 1.33 +#include "../../../3rdParty/EDID/edid.h" 1.34 + 1.35 +namespace OVR { 1.36 + 1.37 +// Forward declarations 1.38 +static Window constructWindow(struct _XDisplay* display, int xscreen, 1.39 + XVisualInfo* xvisual, 1.40 + const LinuxDeviceScreen& screen); 1.41 + 1.42 +static XRRModeInfo* findModeByXID(XRRScreenResources* screen, RRMode xid) 1.43 +{ 1.44 + for (int m = 0; m < screen->nmode; ++m) 1.45 + { 1.46 + XRRModeInfo* mode = &screen->modes[m]; 1.47 + if (xid == mode->id) 1.48 + { 1.49 + return mode; 1.50 + } 1.51 + } 1.52 + return NULL; 1.53 +} 1.54 + 1.55 +/// Retrieves a list of available device screens on which we can build 1.56 +/// SDK windows. Returns number of devices found. 1.57 +/// screens Array which this function will populate. 1.58 +/// maxNumScreens Maximum number of screens to store in screens. 1.59 +static int getDeviceScreens(LinuxDeviceScreen* screens, int maxNumDevices) 1.60 +{ 1.61 + struct _XDisplay* disp = XOpenDisplay(NULL); 1.62 + if (!disp) 1.63 + { 1.64 + OVR::LogError("[SDKWindow] Unable to open X Display."); 1.65 + return 0; 1.66 + } 1.67 + 1.68 + int numDevices = 0; 1.69 + int numScreens = XScreenCount(disp); 1.70 + for (int i = 0; i < numScreens; ++i) 1.71 + { 1.72 + // Screen root is used to detect what video output the crtc is using. 1.73 + Window sr = XRootWindow(disp, i); 1.74 + XRRScreenResources* screen = XRRGetScreenResources(disp, sr); 1.75 + 1.76 + for (int ii = 0; ii < screen->ncrtc; ++ii) 1.77 + { 1.78 + XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(disp, screen, screen->crtcs[ii]); 1.79 + 1.80 + if (0 == crtcInfo->noutput) 1.81 + { 1.82 + XRRFreeCrtcInfo(crtcInfo); 1.83 + continue; 1.84 + } 1.85 + 1.86 + bool foundOutput = false; 1.87 + RROutput output = crtcInfo->outputs[0]; 1.88 + for (int k = 0; k < crtcInfo->noutput; ++k) 1.89 + { 1.90 + XRROutputInfo* outputInfo = 1.91 + XRRGetOutputInfo(disp, screen, crtcInfo->outputs[k]); 1.92 + for (int kk = 0 ; kk < outputInfo->nmode; ++kk) 1.93 + { 1.94 + if (outputInfo->modes[kk] == crtcInfo->mode) 1.95 + { 1.96 + output = crtcInfo->outputs[k]; 1.97 + foundOutput = true; 1.98 + break; 1.99 + } 1.100 + } 1.101 + XRRFreeOutputInfo(outputInfo); 1.102 + if (foundOutput) { break; } 1.103 + } 1.104 + 1.105 + if (!foundOutput) 1.106 + { 1.107 + XRRFreeCrtcInfo(crtcInfo); 1.108 + continue; 1.109 + } 1.110 + 1.111 + XRROutputInfo* outputInfo = XRRGetOutputInfo(disp, screen, output); 1.112 + if (RR_Connected != outputInfo->connection) 1.113 + { 1.114 + XRRFreeOutputInfo(outputInfo); 1.115 + XRRFreeCrtcInfo(crtcInfo); 1.116 + continue; 1.117 + } 1.118 + 1.119 + // Read EDID associated with crtc. 1.120 + MonitorInfo* mi = read_edid_data(disp, output); 1.121 + if (mi == NULL) 1.122 + { 1.123 + XRRFreeOutputInfo(outputInfo); 1.124 + XRRFreeCrtcInfo(crtcInfo); 1.125 + continue; 1.126 + } 1.127 + 1.128 + if (strcmp(mi->manufacturer_code, "OVR") == 0) 1.129 + { 1.130 + XRRModeInfo* modeInfo = findModeByXID(screen, crtcInfo->mode); 1.131 + 1.132 + DistortionRotation desiredRot = DistRotateNone; 1.133 + if (mi->product_code == 3) 1.134 + { 1.135 + // This is a DK2, we may have to rotate our output. 1.136 + // If we don't have to, we should alert the user that 1.137 + // rotating the display using the DM or graphics 1.138 + // card settings is highly non-optimal. 1.139 + desiredRot = DistRotateCCW90; 1.140 + if (crtcInfo->rotation != RR_Rotate_0) 1.141 + { 1.142 + OVR::LogError("Please do not rotate your rift's screen."); 1.143 + 1.144 + if (crtcInfo->rotation == RR_Rotate_90) 1.145 + { 1.146 + // The user has manually rotated the screen. 1.147 + // So apply no rotation on our end. 1.148 + desiredRot = DistRotateNone; 1.149 + } 1.150 + } 1.151 + } 1.152 + else 1.153 + { 1.154 + if (crtcInfo->rotation != RR_Rotate_0) 1.155 + { 1.156 + OVR::LogError("Please do not rotate your rift's screen."); 1.157 + } 1.158 + } 1.159 + 1.160 + int width = modeInfo->width; 1.161 + int height = modeInfo->height; 1.162 + 1.163 + // Swap width / height if display is rotated (shouldn't be on linux). 1.164 + if ( crtcInfo->rotation == RR_Rotate_90 1.165 + || crtcInfo->rotation == RR_Rotate_270) 1.166 + { 1.167 + width = modeInfo->height; 1.168 + height = modeInfo->width; 1.169 + } 1.170 + 1.171 + // Push detected monitor. 1.172 + screens[numDevices].set(i, screen->crtcs[ii], desiredRot, 1.173 + mi->product_code, width, height, 1.174 + crtcInfo->x, crtcInfo->y); 1.175 + ++numDevices; 1.176 + } 1.177 + 1.178 + delete mi; 1.179 + 1.180 + if (numDevices == maxNumDevices) 1.181 + { 1.182 + XRRFreeOutputInfo(outputInfo); 1.183 + XRRFreeCrtcInfo(crtcInfo); 1.184 + XRRFreeScreenResources(screen); 1.185 + OVR::LogError("[SDKWindow] Maxed out number of devices.."); 1.186 + XCloseDisplay(disp); 1.187 + return numDevices; 1.188 + } 1.189 + 1.190 + XRRFreeOutputInfo(outputInfo); 1.191 + XRRFreeCrtcInfo(crtcInfo); 1.192 + } 1.193 + 1.194 + XRRFreeScreenResources(screen); 1.195 + } 1.196 + XCloseDisplay(disp); 1.197 + return numDevices; 1.198 +} 1.199 + 1.200 + 1.201 +LinuxDeviceScreen SDKWindow::findDevScreenForHMD(const ovrHmd& hmd) 1.202 +{ 1.203 + return findDevScreenForDevID(hmd->DisplayDeviceName); 1.204 +} 1.205 + 1.206 +LinuxDeviceScreen SDKWindow::findDevScreenForDevID(const char* deviceIDIn) 1.207 +{ 1.208 + const int maxNumDevices = 5; 1.209 + LinuxDeviceScreen screens[maxNumDevices]; 1.210 + int numDevices = getDeviceScreens(screens, maxNumDevices); 1.211 + 1.212 + if (numDevices > 0) 1.213 + { 1.214 + // Identify target for SDK window via hmd info. 1.215 + for (int i = 0; i < numDevices; ++i) 1.216 + { 1.217 + LinuxDeviceScreen& screen = screens[i]; 1.218 + 1.219 + char deviceID[32]; 1.220 + OVR_sprintf(deviceID, 32, "OVR%04d-%d", 1.221 + screen.productCode, screen.crtcid); 1.222 + 1.223 + if (strcmp(deviceIDIn, deviceID) == 0) 1.224 + { 1.225 + return screen; 1.226 + } 1.227 + } 1.228 + } 1.229 + 1.230 + return LinuxDeviceScreen(); 1.231 +} 1.232 + 1.233 +DistortionRotation SDKWindow::getRotation(const ovrHmd& hmd) 1.234 +{ 1.235 + LinuxDeviceScreen screen = findDevScreenForHMD(hmd); 1.236 + if (screen.isValid()) 1.237 + { 1.238 + return screen.rotation; 1.239 + } 1.240 + else 1.241 + { 1.242 + return DistRotateNone; 1.243 + } 1.244 +} 1.245 + 1.246 + 1.247 +bool SDKWindow::getVisualFromDrawable(GLXDrawable drawable, XVisualInfo* vinfoOut) 1.248 +{ 1.249 + struct _XDisplay* display = glXGetCurrentDisplay(); 1.250 + 1.251 + unsigned int value; 1.252 + glXQueryDrawable(display, drawable, GLX_FBCONFIG_ID, &value); 1.253 + const int attribs[] = {GLX_FBCONFIG_ID, (int)value, None}; 1.254 + int screen; 1.255 + glXQueryContext(display, glXGetCurrentContext(), GLX_SCREEN, &screen); 1.256 + int numElems; 1.257 + GLXFBConfig* config = glXChooseFBConfig(display, screen, attribs, &numElems); 1.258 + if (numElems > 0) 1.259 + { 1.260 + XVisualInfo* chosen = glXGetVisualFromFBConfig(display, *config); 1.261 + *vinfoOut = *chosen; 1.262 + XFree(config); 1.263 + return true; 1.264 + } 1.265 + return false; 1.266 +} 1.267 + 1.268 +SDKWindow::SDKWindow(const ovrHmd& hmd) : 1.269 + mXDisplay(NULL), 1.270 + mXScreen(-1), 1.271 + mXVisual(NULL), 1.272 + mXUniqueContext(-1), 1.273 + mXWindow(0), 1.274 + mFBConfigID(0) 1.275 +{ 1.276 + OVR_UNUSED(hmd); 1.277 +} 1.278 + 1.279 +SDKWindow::~SDKWindow() 1.280 +{ 1.281 + if (mXWindow) 1.282 + { 1.283 + XDeleteContext(mXDisplay, mXWindow, mXUniqueContext); 1.284 + XUnmapWindow(mXDisplay, mXWindow); 1.285 + XDestroyWindow(mXDisplay, mXWindow); 1.286 + mXWindow = static_cast<Window>(0); 1.287 + } 1.288 + 1.289 + if (mXVisual) 1.290 + { 1.291 + XFree(mXVisual); 1.292 + mXVisual = NULL; 1.293 + } 1.294 + 1.295 + if (mXDisplay) 1.296 + { 1.297 + XCloseDisplay(mXDisplay); 1.298 + } 1.299 +} 1.300 + 1.301 +void SDKWindow::buildVisualAndWindow(const LinuxDeviceScreen& devScreen) 1.302 +{ 1.303 + mXDisplay = XOpenDisplay(NULL); 1.304 + mXUniqueContext = XUniqueContext(); 1.305 + mXScreen = devScreen.screen; 1.306 + mFBConfigID = chooseFBConfigID(mXDisplay, mXScreen); 1.307 + 1.308 + mXVisual = getVisual(mXDisplay, mFBConfigID, mXScreen); 1.309 + if (mXVisual != NULL) 1.310 + { 1.311 + mXWindow = constructWindow(mXDisplay, mXScreen, mXVisual, devScreen); 1.312 + mDeviceScreen = devScreen; 1.313 + } 1.314 +} 1.315 + 1.316 +// Used in chooseVisual. May need to expose this to the end use so they can 1.317 +// choose an appropriate framebuffer configuration. 1.318 +struct FBConfig 1.319 +{ 1.320 + FBConfig() : 1.321 + redBits(8), 1.322 + greenBits(8), 1.323 + blueBits(8), 1.324 + alphaBits(8), 1.325 + depthBits(8), 1.326 + stencilBits(-1), 1.327 + doubleBuffer(true), 1.328 + auxBuffers(-1) 1.329 + {} 1.330 + 1.331 + int redBits; 1.332 + int greenBits; 1.333 + int blueBits; 1.334 + int alphaBits; 1.335 + int depthBits; 1.336 + int stencilBits; 1.337 + bool doubleBuffer; 1.338 + int auxBuffers; 1.339 + 1.340 + int xcfg; 1.341 +}; 1.342 + 1.343 +static int fbCalcContrib(int desired, int current) 1.344 +{ 1.345 + int diff = desired - current; 1.346 + if (current != -1) { return diff * diff; } 1.347 + else { return 0; } 1.348 +} 1.349 + 1.350 +// Choose frame buffer configuration and return fbConfigID. 1.351 +int SDKWindow::chooseFBConfigID(struct _XDisplay* display, int xscreen) 1.352 +{ 1.353 + int nativeCount = 0; 1.354 + GLXFBConfig* nativeConfigs = 1.355 + glXGetFBConfigs(display, xscreen, &nativeCount); 1.356 + if (!nativeCount) 1.357 + { 1.358 + OVR::LogError("[SDKWindow] No valid frame buffer configurations found."); 1.359 + return 0; 1.360 + } 1.361 + 1.362 + FBConfig* usables = static_cast<FBConfig*>(calloc(nativeCount, sizeof(FBConfig))); 1.363 + int numUsables = 0; 1.364 + 1.365 + for (int i = 0; i < nativeCount; ++i) 1.366 + { 1.367 + GLXFBConfig native = nativeConfigs[i]; 1.368 + FBConfig* usable = &usables[numUsables]; 1.369 + int v = 0; 1.370 + 1.371 + // Only frame buffer configcs with attached visuals. 1.372 + glXGetFBConfigAttrib(display, native, GLX_VISUAL_ID, &v); 1.373 + if (!v) { continue; } 1.374 + 1.375 + // Only RGBA frame buffers. 1.376 + glXGetFBConfigAttrib(display, native, GLX_RENDER_TYPE, &v); 1.377 + if (!(v & GLX_RGBA_BIT)) { continue; } 1.378 + 1.379 + glXGetFBConfigAttrib(display, native, GLX_DRAWABLE_TYPE, &v); 1.380 + if (!(v & GLX_WINDOW_BIT)) { continue; } 1.381 + 1.382 + glXGetFBConfigAttrib(display, native, GLX_DEPTH_SIZE, &usable->depthBits); 1.383 + glXGetFBConfigAttrib(display, native, GLX_STENCIL_SIZE, &usable->stencilBits); 1.384 + 1.385 + glXGetFBConfigAttrib(display, native, GLX_RED_SIZE, &usable->redBits); 1.386 + glXGetFBConfigAttrib(display, native, GLX_GREEN_SIZE, &usable->greenBits); 1.387 + glXGetFBConfigAttrib(display, native, GLX_BLUE_SIZE, &usable->blueBits); 1.388 + glXGetFBConfigAttrib(display, native, GLX_ALPHA_SIZE, &usable->alphaBits); 1.389 + 1.390 + glXGetFBConfigAttrib(display, native, GLX_ALPHA_SIZE, &usable->auxBuffers); 1.391 + 1.392 + glXGetFBConfigAttrib(display, native, GLX_DOUBLEBUFFER, &v); 1.393 + usable->doubleBuffer = v ? true : false; 1.394 + 1.395 + glXGetFBConfigAttrib(display, native, GLX_FBCONFIG_ID, &usable->xcfg); 1.396 + 1.397 + ++numUsables; 1.398 + } 1.399 + 1.400 + // We really want std::numeric_limits<int>::max() instead of hardcoded vals. 1.401 + const int MostMissing = 100; 1.402 + int leastMissing = MostMissing; 1.403 + int leastBias = MostMissing; 1.404 + 1.405 + const FBConfig* closest = NULL; 1.406 + 1.407 + // Desired is currently the default config built by constructor. 1.408 + FBConfig desired; 1.409 + 1.410 + for (int i = 0; i < numUsables; ++i) 1.411 + { 1.412 + const FBConfig* cur = &usables[i]; 1.413 + 1.414 + if (desired.doubleBuffer != cur->doubleBuffer) { continue; } 1.415 + 1.416 + int missing = 0; 1.417 + if (desired.alphaBits > 0 && cur->alphaBits == 0) { ++missing; } 1.418 + if (desired.depthBits > 0 && cur->depthBits == 0) { ++missing; } 1.419 + if (desired.stencilBits > 0 && cur->stencilBits == 0) { ++missing; } 1.420 + if (desired.redBits > 0 && desired.redBits != cur->redBits) { ++missing; } 1.421 + if (desired.greenBits > 0 && desired.greenBits != cur->greenBits) { ++missing; } 1.422 + if (desired.blueBits > 0 && desired.blueBits != cur->blueBits) { ++missing; } 1.423 + 1.424 + int bias = fbCalcContrib(desired.redBits, cur->redBits) 1.425 + + fbCalcContrib(desired.greenBits, cur->greenBits) 1.426 + + fbCalcContrib(desired.blueBits, cur->blueBits) 1.427 + + fbCalcContrib(desired.alphaBits, cur->alphaBits) 1.428 + + fbCalcContrib(desired.depthBits, cur->depthBits) 1.429 + + fbCalcContrib(desired.stencilBits, cur->stencilBits); 1.430 + 1.431 + if (missing < leastMissing) 1.432 + { 1.433 + closest = cur; 1.434 + } 1.435 + else if (missing == leastMissing) 1.436 + { 1.437 + // Now select against squared differences. 1.438 + if (bias < leastBias) 1.439 + { 1.440 + closest = cur; 1.441 + } 1.442 + } 1.443 + 1.444 + if (closest == cur) 1.445 + { 1.446 + leastMissing = missing; 1.447 + leastBias = bias; 1.448 + } 1.449 + } 1.450 + 1.451 + if (closest == NULL) 1.452 + { 1.453 + OVR::LogError("[SDKWindow] Failed to select appropriate frame buffer."); 1.454 + XFree(nativeConfigs); 1.455 + free(usables); 1.456 + return 0; 1.457 + } 1.458 + 1.459 + int retVal = closest->xcfg; 1.460 + 1.461 + XFree(nativeConfigs); 1.462 + free(usables); 1.463 + 1.464 + return retVal; 1.465 +} 1.466 + 1.467 +// Obtain visual from frame buffer configuration ID. 1.468 +XVisualInfo* SDKWindow::getVisual(struct _XDisplay* display, 1.469 + int fbConfigID, int xscreen) 1.470 +{ 1.471 + GLXFBConfig* cfg = getGLXFBConfig(display, fbConfigID, xscreen); 1.472 + XVisualInfo* viOut = NULL; 1.473 + if (cfg != NULL) 1.474 + { 1.475 + viOut = glXGetVisualFromFBConfig(display, *cfg); 1.476 + XFree(cfg); 1.477 + cfg = NULL; 1.478 + } 1.479 + else 1.480 + { 1.481 + OVR::LogError("Unable to find fb config ID."); 1.482 + } 1.483 + return viOut; 1.484 +} 1.485 + 1.486 +// GLXFBConfig pointer from frame buffer configuration ID. You must call 1.487 +// XFree on the GLXFBConfig pointer. 1.488 +GLXFBConfig* SDKWindow::getGLXFBConfig(struct _XDisplay* display, 1.489 + int fbConfigID, int xscreen) 1.490 +{ 1.491 + const int attribs[] = {GLX_FBCONFIG_ID, (int)fbConfigID, None}; 1.492 + int numElems; 1.493 + 1.494 + GLXFBConfig* config = glXChooseFBConfig(display, xscreen, attribs, &numElems); 1.495 + if (numElems > 0) 1.496 + { 1.497 + return config; 1.498 + } 1.499 + else 1.500 + { 1.501 + return NULL; 1.502 + } 1.503 +} 1.504 + 1.505 + 1.506 +static int gXLastError = -1; 1.507 +static int handleXError(struct _XDisplay* display, XErrorEvent* event) 1.508 +{ 1.509 + OVR_UNUSED(display); 1.510 + gXLastError = event->error_code; 1.511 + return 0; 1.512 +} 1.513 + 1.514 +static void obtainXErrorHandler() 1.515 +{ 1.516 + gXLastError = Success; 1.517 + XSetErrorHandler(handleXError); 1.518 +} 1.519 + 1.520 +static void releaseXErrorHandler(struct _XDisplay* display) 1.521 +{ 1.522 + XSync(display, False); 1.523 + XSetErrorHandler(NULL); 1.524 +} 1.525 + 1.526 +// Returns 0 on error, otherwise a valid X window is returned. 1.527 +static Window constructWindow(struct _XDisplay* xDisp, int xScreen, 1.528 + XVisualInfo* xVisual, 1.529 + const LinuxDeviceScreen& devScreen) 1.530 +{ 1.531 + XSetWindowAttributes wa; 1.532 + 1.533 + Window root = XRootWindow(xDisp, xScreen); 1.534 + Window xWindowOut = 0; 1.535 + 1.536 + // Create Window 1.537 + { 1.538 + Colormap xWinColorMapOut = XCreateColormap( 1.539 + xDisp, root, xVisual->visual, AllocNone); 1.540 + unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask; 1.541 + 1.542 + wa.colormap = xWinColorMapOut; 1.543 + wa.border_pixel = 0; 1.544 + wa.event_mask = StructureNotifyMask | ExposureMask | FocusChangeMask 1.545 + | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask 1.546 + | PropertyChangeMask; 1.547 + 1.548 + obtainXErrorHandler(); 1.549 + 1.550 + xWindowOut = XCreateWindow(xDisp, root, 1.551 + 0, 0, 1.552 + devScreen.width, devScreen.height, 1.553 + 0, 1.554 + xVisual->depth, 1.555 + InputOutput, 1.556 + xVisual->visual, 1.557 + wamask, 1.558 + &wa); 1.559 + 1.560 + releaseXErrorHandler(xDisp); 1.561 + 1.562 + if (!xWindowOut) 1.563 + { 1.564 + OVR::LogError("[SDKWindow] Failed to create SDK window."); 1.565 + return 0; 1.566 + } 1.567 + 1.568 + XFreeColormap(xDisp, xWinColorMapOut); 1.569 + } 1.570 + 1.571 + // OVERRIDE REDIRECT. 1.572 + XSetWindowAttributes attributes; 1.573 + attributes.override_redirect = True; 1.574 + XChangeWindowAttributes(xDisp, xWindowOut, 1.575 + CWOverrideRedirect, &attributes); 1.576 + 1.577 + // Show the window (do this in full screen or windowed). 1.578 + XMapRaised(xDisp, xWindowOut); 1.579 + XFlush(xDisp); 1.580 + 1.581 + // Position ourselves manually since there should be no WM managing us. 1.582 + XRaiseWindow(xDisp, xWindowOut); 1.583 + XMoveWindow(xDisp, xWindowOut, devScreen.offsetX, devScreen.offsetY); 1.584 + XResizeWindow(xDisp, xWindowOut, devScreen.width, devScreen.height); 1.585 + 1.586 + XFlush(xDisp); 1.587 + 1.588 + // WM Backup in case there still exists a WM managing us... 1.589 + Atom NET_WM_BYPASS_COMPOSITOR = 1.590 + XInternAtom(xDisp, "_NET_WM_BYPASS_COMPOSITOR", False); 1.591 + Atom NET_WM_STATE = 1.592 + XInternAtom(xDisp, "_NET_WM_STATE", False); 1.593 + Atom NET_WM_STATE_FULLSCREEN = 1.594 + XInternAtom(xDisp, "_NET_WM_STATE_FULLSCREEN", False); 1.595 + Atom NET_ACTIVE_WINDOW = 1.596 + XInternAtom(xDisp, "_NET_ACTIVE_WINDOW", False); 1.597 + 1.598 + // Bypass compositor if we are under a compositing WM. 1.599 + // Just in case a WM ignores our override_redirect. 1.600 + if (NET_WM_BYPASS_COMPOSITOR) 1.601 + { 1.602 + const unsigned long bypass = 1; 1.603 + XChangeProperty(xDisp, xWindowOut, 1.604 + NET_WM_BYPASS_COMPOSITOR, 1.605 + XA_CARDINAL, 32, PropModeReplace, 1.606 + (unsigned char*)&bypass, 1); 1.607 + } 1.608 + 1.609 + if (NET_WM_STATE && NET_WM_STATE_FULLSCREEN) 1.610 + { 1.611 + // BACKUP: If we are still managed by a WM we want fullscreen. 1.612 + const int EWMH_STATE_ADD = 1; 1.613 + 1.614 + if (NET_ACTIVE_WINDOW) 1.615 + { 1.616 + XEvent event; 1.617 + memset(&event, 0, sizeof(event)); 1.618 + 1.619 + event.type = ClientMessage; 1.620 + event.xclient.window = xWindowOut; 1.621 + event.xclient.format = 32; 1.622 + event.xclient.message_type = NET_ACTIVE_WINDOW; 1.623 + event.xclient.data.l[0] = 1; 1.624 + event.xclient.data.l[1] = 0; 1.625 + 1.626 + XSendEvent(xDisp, root, False, 1.627 + SubstructureNotifyMask | SubstructureRedirectMask, 1.628 + &event); 1.629 + } 1.630 + 1.631 + XEvent event; 1.632 + memset(&event, 0, sizeof(event)); 1.633 + 1.634 + event.type = ClientMessage; 1.635 + event.xclient.window = xWindowOut; 1.636 + event.xclient.format = 32; 1.637 + event.xclient.message_type = NET_WM_STATE; 1.638 + event.xclient.data.l[0] = EWMH_STATE_ADD; 1.639 + event.xclient.data.l[1] = NET_WM_STATE_FULLSCREEN; 1.640 + event.xclient.data.l[2] = 0; 1.641 + event.xclient.data.l[3] = 1; 1.642 + 1.643 + XSendEvent(xDisp, root, False, 1.644 + SubstructureNotifyMask | SubstructureRedirectMask, 1.645 + &event); 1.646 + } 1.647 + 1.648 + return xWindowOut; 1.649 +} 1.650 + 1.651 +} // namespace OVR 1.652 +