Example #1
0
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;
}
Example #2
0
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);
}