bool X11Helper::SetWMFullscreenMonitors( const DisplaySpec &target ) { int num_screens = 0; XineramaScreenInfo *screens = XineramaQueryScreens( Dpy, &num_screens ); if (screens == nullptr) { return false; } XineramaScreenInfo *end = screens + num_screens; Rage::RectI monitors{}; bool found_bounds = false; if (target.isVirtual()) { auto topmost = std::min_element( screens, end, []( XineramaScreenInfo &a, XineramaScreenInfo &b ) { return a.y_org < b.y_org; } ); monitors.top = topmost->screen_number; auto bottommost = std::max_element( screens, end, []( XineramaScreenInfo &a, XineramaScreenInfo &b ) { return a.y_org < b.y_org; } ); monitors.bottom = bottommost->screen_number; auto leftmost = std::min_element( screens, end, []( XineramaScreenInfo &a, XineramaScreenInfo &b ) { return a.x_org < b.x_org; } ); monitors.left = leftmost->screen_number; auto rightmost = std::max_element( screens, end, []( XineramaScreenInfo &a, XineramaScreenInfo &b ) { return a.x_org < b.x_org; } ); monitors.right = rightmost->screen_number; found_bounds = true; } else if (target.currentMode() != nullptr) { auto mon = std::find_if( screens, end, [&]( XineramaScreenInfo &screen ) { return screen.x_org == target.currentBounds().left && screen.y_org == target.currentBounds().top && screen.width == target.currentMode()->width && screen.height == target.currentMode()->height; } ); if (mon != end) { monitors.left = monitors.right = monitors.top = monitors.bottom = mon->screen_number; found_bounds = true; } } XFree( screens ); XWindowAttributes attr = {0}; if (!found_bounds || !XGetWindowAttributes( Dpy, Win, &attr )) { return false; } SetWMState( attr.root, Win, 1, XInternAtom( Dpy, "_NET_WM_STATE_FULLSCREEN", False )); XClientMessageEvent xclient = {0}; xclient.type = ClientMessage; xclient.window = Win; xclient.message_type = XInternAtom( Dpy, "_NET_WM_FULLSCREEN_MONITORS", False ); xclient.format = 32; xclient.data.l[0] = monitors.top; xclient.data.l[1] = monitors.bottom; xclient.data.l[2] = monitors.left; xclient.data.l[3] = monitors.right; xclient.data.l[4] = 1; XSendEvent( Dpy, attr.root, False, SubstructureRedirectMask | SubstructureNotifyMask, reinterpret_cast<XEvent *> (&xclient)); XFlush( Dpy ); return true; }
std::string RageDisplay::SetVideoMode( VideoModeParams p, bool &bNeedReloadTextures ) { std::string err; vector<std::string> vs; if( (err = this->TryVideoMode(p,bNeedReloadTextures)) == "" ) { return ""; } LOG->Trace( "TryVideoMode failed: %s", err.c_str() ); vs.push_back( err ); // fall back to settings that will most likely work p.bpp = 16; if( (err = this->TryVideoMode(p,bNeedReloadTextures)) == "" ) { return ""; } vs.push_back( err ); // "Intel(R) 82810E Graphics Controller" won't accept a 16 bpp surface if // the desktop is 32 bpp, so try 32 bpp as well. p.bpp = 32; if( (err = this->TryVideoMode(p,bNeedReloadTextures)) == "" ) { return ""; } vs.push_back( err ); // Fall back on a known resolution good rather than 640 x 480. DisplaySpecs dr; this->GetDisplaySpecs(dr); if( dr.empty() ) { vs.push_back( "No display resolutions" ); return SETVIDEOMODE_FAILED.GetValue() + " " + Rage::join(";",vs); } DisplaySpec d = *dr.begin(); // Try to find DisplaySpec corresponding to requested display for (const auto &candidate: dr) { if (candidate.currentMode() != nullptr) { d = candidate; if (candidate.id() == p.sDisplayId) { break; } } } p.sDisplayId = d.id(); const DisplayMode supported = d.currentMode() != nullptr ? *d.currentMode() : *d.supportedModes().begin(); p.width = supported.width; p.height = supported.height; p.rate = static_cast<int> (round(supported.refreshRate)); if( (err = this->TryVideoMode(p,bNeedReloadTextures)) == "" ) { return ""; } vs.push_back( err ); return SETVIDEOMODE_FAILED.GetValue() + " " + Rage::join(";",vs); }