5 1 new backport x11 fs rework (#1485)

* Use XRandR 1.2 to set fullscreen resolution for single output

Squash of roothorick's PR #497
(also includes Kyzentun's CMake changes from PR #716)

* Cherry-pick json c++1x stuff (b9e3d7174e)

* Cherry-pick c++11 support from 5bba5c0038 and 9f8b045309

* rework Linux (X11) fullscreen, improve display-related Graphics Options

Implement option to select between monitors for exclusive fullscreen mode
on X11 (using XRandR 1.2), or use a fullscreen borderless window.

Reimplement resolution/refresh rate/display mode-related option rows
using Lua, update choices dynamically so only known-good groupings of
resolution/refresh rate/aspect ratio can be selected.

Minimally update Windows/MacOS LowLevelWindow implementations to support
changes made for Linux side. Fullscreen Borderless Window/multi monitor
support from X11 not implemented for those in this commit.

* allow forcibly disabling xinerama use on Linux

When libXinerama is available, SM tries to use it to find the proper
monitor indexes to use to set _NET_WM_FULLSCREEN_MONITORS (on borderless
fullscreen). xfwm4 seems to assume that monitors are numbered in increasing
order from left to right (rather than using the Xinerama-assigned numbers),
so _NET_WM_FULLSCREEN_MONITORS misbehaves on Xfce.

This commit bypasses use of libXinerama, and instead forces SM to induce fullscreen
on the desired monitor in the backup, hacky way: remove all window hints, move window
to desired monitor, then add _NET_WM_STATE_FULLSCREEN hint. This works on
mutter and Xfce.

* Remove multiple warnings on redundant define.

This used to be hard-coded due to pthread related items, but now it's dynamically determined.

* fix _fallback menu behavior for unrecognized aspect ratios

* Fix error recreating existing FS texture

* Bump deployment target to 10.7 to use libc++ on XCode 8

* Add explicit casts to please clang

* Update changelog
This commit is contained in:
Drew Barbarello
2017-06-18 11:55:16 -04:00
committed by Colby Klein
parent 7ef14c340d
commit 557be7cf1b
57 changed files with 2616 additions and 370 deletions
+44 -20
View File
@@ -4,7 +4,7 @@
#include "RageLog.h"
#include "RageUtil.h"
#include "RageDisplay.h"
#include "DisplayResolutions.h"
#include "DisplaySpec.h"
#include "arch/ArchHooks/ArchHooks.h"
#include "archutils/Win32/AppInstance.h"
#include "archutils/Win32/Crash.h"
@@ -539,29 +539,53 @@ HWND GraphicsWindow::GetHwnd()
return g_hWndMain;
}
void GraphicsWindow::GetDisplayResolutions( DisplayResolutions &out )
void GraphicsWindow::GetDisplaySpecs( DisplaySpecs &out )
{
DEVMODE dm;
ZERO( dm );
dm.dmSize = sizeof(dm);
int i=0;
while(EnumDisplaySettings(NULL, i++, &dm))
{
const size_t DM_DRIVER_EXTRA_BYTES = 4096;
const size_t DMSIZE = sizeof( DEVMODE ) + DM_DRIVER_EXTRA_BYTES;
auto reset = [=]( std::unique_ptr<DEVMODE> &p ) {
::memset( p.get(), 0, DMSIZE );
p->dmSize = sizeof( DEVMODE );
p->dmDriverExtra = static_cast<WORD> (DM_DRIVER_EXTRA_BYTES);
};
auto isvalid = []( std::unique_ptr<DEVMODE> &dm ) {
// Windows 8 and later don't support less than 32bpp, so don't even test
// for them. GetDisplayResolutions is only for resolutions anyway. -Kyz
if(dm.dmBitsPerPel < 32)
// for them. GetDisplaySpecs only tracks resolution/refresh rate anyway. -Kyz, drewbarbs
return (dm->dmFields & DM_PELSWIDTH) && (dm->dmFields & DM_PELSHEIGHT) && (dm->dmFields & DM_DISPLAYFREQUENCY)
&& (dm->dmBitsPerPel >= 32 || !(dm->dmFields & DM_BITSPERPEL));
};
std::unique_ptr<DEVMODE> dm( static_cast<DEVMODE*> (operator new(DMSIZE)) );
reset( dm );
int i = 0;
std::set<DisplayMode> modes;
while ( EnumDisplaySettingsEx( nullptr, i++, dm.get(), 0 ) )
{
if ( isvalid( dm ) && ChangeDisplaySettingsEx( nullptr, dm.get(), nullptr, CDS_TEST, nullptr ) == DISP_CHANGE_SUCCESSFUL )
{
continue;
}
DisplayResolution res = { dm.dmPelsWidth, dm.dmPelsHeight };
std::set<DisplayResolution>::iterator entry= out.find(res);
if(entry == out.end())
{
if(ChangeDisplaySettings(&dm, CDS_TEST)==DISP_CHANGE_SUCCESSFUL)
{
out.insert(res);
}
DisplayMode m = { dm->dmPelsWidth, dm->dmPelsHeight, static_cast<double> (dm->dmDisplayFrequency) };
modes.insert(m);
}
reset( dm );
}
reset( dm );
// Get the current display mode
if ( EnumDisplaySettingsEx( nullptr, ENUM_CURRENT_SETTINGS, dm.get(), 0 ) && isvalid( dm ) )
{
DisplayMode m = { dm->dmPelsWidth, dm->dmPelsHeight, static_cast<double> (dm->dmDisplayFrequency) };
RectI bounds = { 0, 0, static_cast<int> (m.width), static_cast<int> (m.height) };
out.insert( DisplaySpec( "", "Fullscreen", modes, m, bounds ) );
}
else if ( !modes.empty() )
{
LOG->Warn( "Could not retrieve valid current display mode" );
out.insert( DisplaySpec( "", "Fullscreen", *modes.begin() ) );
}
else
{
LOG->Warn( "Could not retrieve *any* DisplaySpec's!" );
}
}