Skip to content

Commit

Permalink
[linux] fixes for multimonitor mode with X11
Browse files Browse the repository at this point in the history
- always use xinerama if available to determine the screen dimensions
- use Xlib to determine screen size if xinerama isn't available
  • Loading branch information
mickelson committed Jan 6, 2017
1 parent 2101e2d commit b3175db
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 43 deletions.
23 changes: 16 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,13 @@ ifneq ($(FE_WINDOWS_COMPILE),1)
USE_GLES=1
else
#
# Test for Xinerama...
# Test for Xlib and Xinerama...
#
ifeq ($(shell $(PKG_CONFIG) --exists xinerama && echo "1" || echo "0"), 1)
USE_XINERAMA=1
ifeq ($(shell $(PKG_CONFIG) --exists x11 && echo "1" || echo "0"), 1)
USE_XLIB=1
ifeq ($(shell $(PKG_CONFIG) --exists xinerama && echo "1" || echo "0"), 1)
USE_XINERAMA=1
endif
endif
endif
endif
Expand Down Expand Up @@ -241,7 +244,7 @@ ifneq ($(NO_SWF),1)
LIBS += -ldl -lGL
endif
TEMP_LIBS += freetype2
CFLAGS += $(shell $(PKG_CONFIG) --cflags --silence-errors)
CFLAGS += $(shell $(PKG_CONFIG) --cflags --silence-errors freetype2)
endif
else
LIBS += -lopengl32
Expand Down Expand Up @@ -299,9 +302,15 @@ ifeq ($(USE_GLES),1)
FE_FLAGS += -DUSE_GLES
endif

ifeq ($(USE_XINERAMA),1)
FE_FLAGS += -DUSE_XINERAMA
LIBS += -lX11 -lXinerama
ifeq ($(USE_XLIB),1)
FE_FLAGS += -DUSE_XLIB
LIBS += -lX11

ifeq ($(USE_XINERAMA),1)
FE_FLAGS += -DUSE_XINERAMA
LIBS += -lXinerama
endif

endif

ifeq ($(USE_FONTCONFIG),1)
Expand Down
38 changes: 24 additions & 14 deletions src/fe_present.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void FePresent::init_monitors()
//
// We support multi-monitor setups on MS-Windows when in fullscreen or "fillscreen" mode
//
#ifdef SFML_SYSTEM_WINDOWS
#if defined(SFML_SYSTEM_WINDOWS)
if ( m_feSettings->get_info_bool( FeSettings::MultiMon )
&& !is_windowed_mode( m_feSettings->get_window_mode() ) )
{
Expand All @@ -178,27 +178,38 @@ void FePresent::init_monitors()
(*itr).transform *= correction;
}
else
#else
#ifdef USE_XINERAMA
if ( m_feSettings->get_info_bool( FeSettings::MultiMon )
&& !is_windowed_mode( m_feSettings->get_window_mode() ) )
#elif defined(USE_XINERAMA)
if ( 1 )
{
Display *xdisp = XOpenDisplay( NULL );
int num=0;

XineramaScreenInfo *si=XineramaQueryScreens( xdisp, &num );
if ( si )
{
for ( int i=0; i<num; i++ )
if (( m_feSettings->get_info_bool( FeSettings::MultiMon ) )
&& ( !is_windowed_mode( m_feSettings->get_window_mode() )))
{
for ( int i=0; i<num; i++ )
{
FeMonitor mon(
si[i].screen_number,
si[i].width,
si[i].height );

mon.transform = sf::Transform().translate(
si[i].x_org,
si[i].y_org );

m_mon.push_back( mon );
}
}
else
{
FeMonitor mon(
si[i].screen_number,
si[i].width,
si[i].height );

mon.transform = sf::Transform().translate(
si[i].x_org,
si[i].y_org );
si[0].screen_number,
si[0].width,
si[0].height );

m_mon.push_back( mon );
}
Expand All @@ -208,7 +219,6 @@ void FePresent::init_monitors()
XCloseDisplay( xdisp );
}
else
#endif // USE_XINERAMA
#endif
{
//
Expand Down
41 changes: 30 additions & 11 deletions src/fe_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,14 @@
#include "fe_util_osx.hpp"
#endif

#ifdef USE_XINERAMA
#include <X11/extensions/Xinerama.h>
#ifdef USE_XLIB
#include <X11/Xlib.h>
#ifdef USE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#endif


namespace {

void str_from_c( std::string &s, const char *c )
Expand Down Expand Up @@ -1047,13 +1051,13 @@ std::basic_string<sf::Uint32> clipboard_get_content()
return retval;
}

#ifdef USE_XINERAMA
#if defined(USE_XLIB)
//
// We use this in fe_window but implement it here because the XWindows
// namespace (Window, etc) clashes with the SFML namespace used in fe_window
// (sf::Window)
//
void get_xinerama_geometry( int &x, int &y, int &width, int &height )
void get_x11_geometry( bool multimon, int &x, int &y, int &width, int &height )
{
x=0;
y=0;
Expand All @@ -1063,21 +1067,36 @@ void get_xinerama_geometry( int &x, int &y, int &width, int &height )
::Display *xdisp = XOpenDisplay( NULL );
int num=0;

#ifdef USE_XINERAMA
XineramaScreenInfo *si=XineramaQueryScreens( xdisp, &num );

if ( num > 1 )
if ( multimon )
{
x=-si[0].x_org;
y=-si[0].y_org;
}
if ( num > 1 )
{
x=-si[0].x_org;
y=-si[0].y_org;
}

for ( int i=0; i<num; i++ )
for ( int i=0; i<num; i++ )
{
width = std::max( width, si[i].x_org + si[i].width );
height = std::max( height, si[i].y_org + si[i].height );
}
}
else
{
width = std::max( width, si[i].x_org + si[i].width );
height = std::max( height, si[i].y_org + si[i].height );
width = si[0].width;
height = si[0].height;
}

XFree( si );
#else
::Screen *xscreen = XDefaultScreenOfDisplay( xdisp );
width = XWidthOfScreen( xscreen );
height = XHeightOfScreen( xscreen );
#endif

XCloseDisplay( xdisp );
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/fe_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ std::basic_string<sf::Uint32> clipboard_get_content();
// namespace (Window, etc) clashes with the SFML namespace used in fe_window
// (sf::Window)
//
#ifdef USE_XINERAMA
void get_xinerama_geometry( int &, int &, int &, int & );
#if defined(USE_XLIB)
void get_x11_geometry( bool multimon, int &, int &, int &, int & );
#endif

#ifndef NO_MOVIE
Expand Down
29 changes: 20 additions & 9 deletions src/fe_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,23 @@ void FeWindow::onCreate()

ShowWindow(hw, SW_SHOW);
SetFocus( hw );
#endif

#ifdef USE_XINERAMA
if ( m_fes.get_info_bool( FeSettings::MultiMon ) )
{
int x, y, width, height;
get_xinerama_geometry( x, y, width, height );
#elif defined(USE_XLIB)
//
// Notes: if xinerama and multimon are enabled, this should set our window to cover all available
// monitors
//
// If multimon is disabled, this fixes positioning problems that SFML(?) seems to have where
// the window contents aren't drawn in the correct place vertically on fullscreen/fillscreen modes
//
int x, y, width, height;
get_x11_geometry(
m_fes.get_info_bool( FeSettings::MultiMon ) && !is_windowed_mode( m_fes.get_window_mode() ),
x, y, width, height );

setPosition( sf::Vector2i( x, y ) );
setSize( sf::Vector2u( width, height ) );

setPosition( sf::Vector2i( x, y ) );
setSize( sf::Vector2u( width, height ) );
}
#endif

setVerticalSyncEnabled(true);
Expand All @@ -186,6 +192,11 @@ void FeWindow::initial_create()

int win_mode = m_fes.get_window_mode();

#ifdef USE_XINERAMA
if ( m_fes.get_info_bool( FeSettings::MultiMon ) && ( win_mode != FeSettings::Default ))
std::cout << " ! NOTE: Use the 'Fill Screen' window mode if you want multiple monitor support to function correctly" << std::endl;
#endif

// Create window
create(
sf::VideoMode::getDesktopMode(),
Expand Down

0 comments on commit b3175db

Please sign in to comment.