Add proper fullscreen and resolution changing support using XRandR. This makes XRandR mandatory, but I don't see any reason why we can't do that, and providing alternatives would be difficult at best for little payoff.

This commit is contained in:
Ben Anderson
2005-12-02 21:17:36 +00:00
parent 60bdd7ae04
commit 7da3272486
5 changed files with 127 additions and 15 deletions
+19
View File
@@ -31,6 +31,25 @@ AC_DEFUN([SM_X_WITH_OPENGL],
[$XLIBS])
AC_DEFINE(HAVE_X11, 1, [X11 libraries present])
fi
# Check for Xrandr
# Can someone fix this for me? This is producing bizarre warnings from
# configure... I have no clue what I'm doing -Ben
AC_CHECK_LIB(Xrandr, XRRSizes, have_xrandr=yes, have_xrandr=no)
AC_CHECK_HEADER(X11/extensions/Xrandr.h, have_xrandr_header=yes, have_xrandr_header=no)
if test "$have_xrandr_header" = "no"; then
have_xrandr=no
fi
if test "$have_xrandr" = "no"; then
echo "*** Direct X11 support needs Xrandr libraries and headers."
echo "*** Couldn't find needed headers. Continuing without X11 backend."
$no_x = yes
else
LIBS="$LIBS -lXrandr"
fi
AM_CONDITIONAL(HAVE_X11, test "$no_x" != "yes")
AC_SUBST(XCFLAGS)
@@ -5,12 +5,15 @@
#include "archutils/Unix/X11Helper.h"
#include "PrefsManager.h" // XXX
#include "RageDisplay.h" // VideoModeParams
#include "DisplayResolutions.h"
#include <stack>
#include <math.h> // ceil()
#define GLX_GLXEXT_PROTOTYPES
#include <GL/glx.h> // All sorts of stuff...
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#if defined(HAVE_LIBXTST)
#include <X11/extensions/XTest.h>
@@ -36,10 +39,21 @@ LowLevelWindow_X11::LowLevelWindow_X11()
LOG->Info( "X server vendor: %s [%i.%i.%i.%i]", XServerVendor( X11Helper::Dpy ), iMajor, iMinor, iRevision, iPatch );
LOG->Info( "Server GLX vendor: %s [%s]", glXQueryServerString( X11Helper::Dpy, iScreen, GLX_VENDOR ), glXQueryServerString( X11Helper::Dpy, iScreen, GLX_VERSION ) );
LOG->Info( "Client GLX vendor: %s [%s]", glXGetClientString( X11Helper::Dpy, GLX_VENDOR ), glXGetClientString( X11Helper::Dpy, GLX_VERSION ) );
m_bWasWindowed = true;
}
LowLevelWindow_X11::~LowLevelWindow_X11()
{
// Reset the display
if( !m_bWasWindowed )
{
XRRScreenConfiguration *screenConfig = XRRGetScreenInfo( X11Helper::Dpy, RootWindow( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ) ) );
XRRSetScreenConfig( X11Helper::Dpy, screenConfig, RootWindow( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ) ), 0, 1, CurrentTime );
XRRFreeScreenConfigInfo( screenConfig );
XUngrabKeyboard( X11Helper::Dpy, CurrentTime );
}
X11Helper::Stop(); // Xlib cleans up the window for us
}
@@ -74,7 +88,7 @@ CString LowLevelWindow_X11::TryVideoMode( const VideoModeParams &p, bool &bNewDe
hints.min_width = hints.max_width = hints.base_width = p.width;
hints.min_height = hints.max_height = hints.base_height = p.height;
if( !m_bWindowIsOpen || p.bpp != CurrentParams.bpp )
if( !m_bWindowIsOpen || p.bpp != CurrentParams.bpp || ( m_bWasWindowed != p.windowed ) )
{
// Different depth, or we didn't make a window before. New context.
bNewDeviceOut = true;
@@ -111,7 +125,9 @@ CString LowLevelWindow_X11::TryVideoMode( const VideoModeParams &p, bool &bNewDe
/* Enable StructureNotifyMask, so we receive a MapNotify for the following XMapWindow. */
X11Helper::OpenMask( StructureNotifyMask );
if( !X11Helper::MakeWindow(xvi->screen, xvi->depth, xvi->visual, p.width, p.height) )
// I get strange behavior if I add override redirect after creating the window.
// So, let's recreate the window when changing that state.
if( !X11Helper::MakeWindow(xvi->screen, xvi->depth, xvi->visual, p.width, p.height, !p.windowed) )
{
return "Failed to create the window.";
}
@@ -157,6 +173,58 @@ CString LowLevelWindow_X11::TryVideoMode( const VideoModeParams &p, bool &bNewDe
bNewDeviceOut = false;
}
XRRScreenConfiguration *screenConfig = XRRGetScreenInfo( X11Helper::Dpy, RootWindow( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ) ) );
if( !p.windowed )
{
// Find a matching mode.
int sizesXct;
XRRScreenSize *sizesX = XRRSizes( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ), &sizesXct );
ASSERT_M( sizesXct != 0, "Couldn't get resolution list from X server" );
int sizeMatch = -1;
int i = 0;
while(i < sizesXct)
{
if(sizesX[i].width == p.width && sizesX[i].height == p.height)
{
sizeMatch = i;
break;
}
i++;
}
// Set this mode.
// XXX: This doesn't handle if the config has changed since we queried it (see man Xrandr)
XRRSetScreenConfig( X11Helper::Dpy, screenConfig, RootWindow( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ) ), sizeMatch, 1, CurrentTime );
// Move the window to the corner that the screen focuses in on.
XMoveWindow( X11Helper::Dpy, X11Helper::Win, 0, 0 );
XRaiseWindow( X11Helper::Dpy, X11Helper::Win );
if( m_bWasWindowed )
{
// We want to prevent the WM from catching anything that comes from the keyboard.
XGrabKeyboard( X11Helper::Dpy, X11Helper::Win, True,
GrabModeAsync, GrabModeAsync, CurrentTime );
m_bWasWindowed = false;
}
}
else
{
if( !m_bWasWindowed )
{
XRRSetScreenConfig( X11Helper::Dpy, screenConfig, RootWindow( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ) ), 0, 1, CurrentTime );
// In windowed mode, we actually want the WM to function normally.
// Release any previous grab.
XUngrabKeyboard( X11Helper::Dpy, CurrentTime );
m_bWasWindowed = true;
}
}
XRRFreeScreenConfigInfo( screenConfig );
// Do this before resizing the window so that pane-style WMs (Ion,
// ratpoison) don't resize us back inappropriately.
@@ -166,13 +234,6 @@ CString LowLevelWindow_X11::TryVideoMode( const VideoModeParams &p, bool &bNewDe
// catching WM normal hints changes in mapped windows.
XResizeWindow( X11Helper::Dpy, X11Helper::Win, p.width, p.height );
// Center the window in the display.
int w = DisplayWidth( X11Helper::Dpy, DefaultScreen(X11Helper::Dpy) );
int h = DisplayHeight( X11Helper::Dpy, DefaultScreen(X11Helper::Dpy) );
int x = (w - p.width)/2;
int y = (h - p.height)/2;
XMoveWindow( X11Helper::Dpy, X11Helper::Win, x, y );
CurrentParams = p;
return ""; // Success
@@ -224,6 +285,23 @@ void LowLevelWindow_X11::SwapBuffers()
}
}
void LowLevelWindow_X11::GetDisplayResolutions( DisplayResolutions &out ) const
{
// This _NEEDS_ Xrandr to be present, but feck, who doesn't have it?
int sizesXct;
XRRScreenSize *sizesX = XRRSizes( X11Helper::Dpy, DefaultScreen( X11Helper::Dpy ), &sizesXct );
ASSERT_M( sizesXct != 0, "Couldn't get resolution list from X server" );
int i = 0;
while(i < sizesXct)
{
DisplayResolution res = { sizesX[i].width, sizesX[i].height };
out.s.insert( res );
i++;
}
}
/*
* (c) 2005 Ben Anderson
* All rights reserved.
@@ -18,9 +18,12 @@ public:
void SwapBuffers();
VideoModeParams GetActualVideoModeParams() const { return CurrentParams; }
void GetDisplayResolutions( DisplayResolutions &out ) const;
private:
bool m_bWindowIsOpen;
bool m_bWasWindowed;
VideoModeParams CurrentParams;
};
+16 -5
View File
@@ -1,7 +1,7 @@
#include "global.h"
#include "X11Helper.h"
#include <X11/Xlib.h> // Display, Window
#include <X11/Xlib.h>
#include "RageLog.h"
#include "RageDisplay.h"
@@ -86,7 +86,7 @@ static bool pApplyMasks()
return true;
}
bool X11Helper::MakeWindow( int screenNum, int depth, Visual *visual, int width, int height )
bool X11Helper::MakeWindow( int screenNum, int depth, Visual *visual, int width, int height, bool overrideRedirect )
{
vector<long>::iterator i;
@@ -116,9 +116,20 @@ bool X11Helper::MakeWindow( int screenNum, int depth, Visual *visual, int width,
winAttribs.colormap = XCreateColormap( Dpy, RootWindow(Dpy, screenNum), visual, AllocNone );
Win = XCreateWindow( Dpy, RootWindow(Dpy, screenNum), 0, 0, width,
height, 0, depth, InputOutput, visual,
CWBorderPixel | CWColormap | CWEventMask, &winAttribs );
if( overrideRedirect )
{
winAttribs.override_redirect = True;
Win = XCreateWindow( Dpy, RootWindow(Dpy, screenNum), 0, 0, width,
height, 0, depth, InputOutput, visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &winAttribs );
}
else
{
Win = XCreateWindow( Dpy, RootWindow(Dpy, screenNum), 0, 0, width,
height, 0, depth, InputOutput, visual,
CWBorderPixel | CWColormap | CWEventMask, &winAttribs );
}
g_bHaveWin = true;
+2 -1
View File
@@ -26,8 +26,9 @@ namespace X11Helper
// (Re)create the window on the screen of this number with this depth,
// this visual type, this width (optional -- you can resize the window
// in your callback later), and this height (optional).
// Also, whether to enable override redirect on the window.
bool MakeWindow(int screenNum, int depth, Visual *visual,
int width=32, int height=32);
int width=32, int height=32, bool overrideRedirect=false);
// Unmask one X event type mask thingy (XSelectInput() arg 3) on the
// current window. Masked/unmasked events will carry between windows.