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 08:55:16 -07:00
committed by Colby Klein
parent 7ef14c340d
commit 557be7cf1b
57 changed files with 2616 additions and 370 deletions
+96
View File
@@ -129,6 +129,23 @@ bool X11Helper::MakeWindow( Window &win, int screenNum, int depth, Visual *visua
return true;
}
void X11Helper::SetWMState( const Window &root, const Window &win, const long action, const Atom atom )
{
if ( !Dpy )
return;
Atom wm_state = XInternAtom(Dpy, "_NET_WM_STATE", False);
XEvent xev;
memset( &xev, 0, sizeof( xev ));
xev.type = ClientMessage;
xev.xclient.window = Win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = action; // 0 = Remove, 1 = Add, 2 = Toggle
xev.xclient.data.l[1] = atom;
xev.xclient.data.l[2] = 0; // end list of Atoms
XSendEvent( Dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev );
}
int ErrorCallback( Display *d, XErrorEvent *err )
{
char errText[512];
@@ -144,6 +161,85 @@ int FatalCallback( Display *d )
RageException::Throw( "Fatal I/O error communicating with X server." );
}
#ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
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;
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;
}
#endif
/*
* (c) 2005, 2006 Ben Anderson, Steve Checkoway
* All rights reserved.
+8
View File
@@ -4,6 +4,8 @@
#include <X11/Xlib.h> // Window
#include <X11/Xutil.h>
#include <DisplaySpec.h>
namespace X11Helper
{
// All functions in here that return a bool return true on success, and
@@ -25,6 +27,12 @@ namespace X11Helper
// (Re)create the Window win.
bool MakeWindow( Window &win, int screenNum, int depth, Visual *visual,
int width, int height, bool overrideRedirect );
void SetWMState( const Window &root, const Window &win, const long action, const Atom atom );
#ifdef HAVE_XINERAMA
bool SetWMFullscreenMonitors( const DisplaySpec &target );
#endif
};
#endif