add xinerama multi-monitor support and position window hints

This commit is contained in:
Franc[e]sco 2017-05-10 21:27:27 +02:00
parent 1188fa2a1e
commit 81694ae8f9
3 changed files with 133 additions and 20 deletions

26
unix/configure vendored
View File

@ -719,6 +719,7 @@ enable_jma
enable_screenshot
with_x
enable_xvideo
enable_xinerama
enable_sound
'
ac_precious_vars='build_alias
@ -1370,6 +1371,7 @@ Optional Features:
--enable-screenshot enable screenshot support through libpng (default:
yes)
--enable-xvideo enable Xvideo if available (default: yes)
--enable-xinerama enable Xinerama if available (default: yes)
--enable-sound enable sound if available (default: yes)
Optional Packages:
@ -6265,6 +6267,29 @@ if test "x$ac_cv_header_X11_extensions_Xv_h" = xyes; then :
fi
fi
# Check if we can build with Xinerama multi-monitor support
# Check whether --enable-xinerama was given.
if test "${enable_xinerama+set}" = set; then :
enableval=$enable_xinerama;
else
enable_xinerama="yes"
fi
if test "x$enable_xinerama" = "xyes"; then
enable_xinerama="no"
ac_fn_cxx_check_header_mongrel "$LINENO" "X11/extensions/Xinerama.h" "ac_cv_header_X11_extensions_Xinerama_h" "$ac_includes_default"
if test "x$ac_cv_header_X11_extensions_Xinerama_h" = xyes; then :
enable_xinerama="yes"
S9XLIBS="$S9XLIBS -lXinerama"
S9XDEFS="$S9XDEFS -DUSE_XINERAMA"
fi
fi
# Check if we have sound code for this platform.
@ -6343,6 +6368,7 @@ libs................. $S9XLIBS
features:
Xvideo support....... $enable_xvideo
Xinerama support..... $enable_xinerama
sound support........ $enable_sound
screenshot support... $enable_screenshot
netplay support...... $enable_netplay

View File

@ -418,6 +418,22 @@ if test "x$enable_xvideo" = "xyes"; then
])
fi
# Check if we can build with Xinerama multi-monitor support
AC_ARG_ENABLE([xinerama],
[AS_HELP_STRING([--enable-xinerama],
[enable Xinerama if available (default: yes)])],
[], [enable_xinerama="yes"])
if test "x$enable_xinerama" = "xyes"; then
enable_xinerama="no"
AC_CHECK_HEADER([X11/extensions/Xinerama.h],
[
enable_xinerama="yes"
S9XLIBS="$S9XLIBS -lXinerama"
S9XDEFS="$S9XDEFS -DUSE_XINERAMA"
])
fi
# Check if we have sound code for this platform.
AC_ARG_ENABLE([sound],
@ -483,6 +499,7 @@ libs................. $S9XLIBS
features:
Xvideo support....... $enable_xvideo
Xinerama support..... $enable_xinerama
sound support........ $enable_sound
screenshot support... $enable_screenshot
netplay support...... $enable_netplay

View File

@ -212,6 +212,10 @@
#define FOURCC_YUY2 0x32595559
#endif
#ifdef USE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef MITSHM
#include <sys/ipc.h>
#include <sys/shm.h>
@ -297,6 +301,9 @@ struct GUIData
unsigned char u_table[1 << 15];
unsigned char v_table[1 << 15];
#endif
#ifdef USE_XINERAMA
uint32 xinerama_head;
#endif
#ifdef MITSHM
XShmSegmentInfo sm_info;
bool8 use_shared_memory;
@ -361,6 +368,9 @@ void S9xExtraDisplayUsage (void)
#ifdef USE_XVIDEO
S9xMessage(S9X_INFO, S9X_USAGE, "-xvideo Hardware accelerated scaling");
S9xMessage(S9X_INFO, S9X_USAGE, "-maxaspect Try to fill the display, in fullscreen");
#endif
#ifdef USE_XINERAMA
S9xMessage(S9X_INFO, S9X_USAGE, "-xineramahead Xinerama head number for multi-monitor setups");
#endif
S9xMessage(S9X_INFO, S9X_USAGE, "");
S9xMessage(S9X_INFO, S9X_USAGE, "-v1 Video mode: Blocky (default)");
@ -389,6 +399,16 @@ void S9xParseDisplayArg (char **argv, int &i, int argc)
if (!strcasecmp(argv[i], "-maxaspect"))
GUI.maxaspect = TRUE;
else
#endif
#ifdef USE_XINERAMA
if (!strcasecmp(argv[i], "-xineramahead"))
{
if (i + 1 < argc)
GUI.xinerama_head = atoi(argv[++i]);
else
S9xUsage();
}
else
#endif
if (!strncasecmp(argv[i], "-v", 2))
{
@ -553,6 +573,9 @@ const char * S9xParseDisplayConfig (ConfigFile &conf, int pass)
GUI.use_xvideo = conf.GetBool("Unix/X11::Xvideo", FALSE);
GUI.maxaspect = conf.GetBool("Unix/X11::MaxAspect", FALSE);
#endif
#ifdef USE_XINERAMA
GUI.xinerama_head = conf.GetUInt("Unix/X11::XineramaHead", 0);
#endif
if (conf.Exists("Unix/X11::VideoMode"))
{
@ -853,33 +876,80 @@ void S9xInitDisplay (int argc, char **argv)
attrib.background_pixel = BlackPixelOfScreen(GUI.screen);
attrib.colormap = XCreateColormap(GUI.display, RootWindowOfScreen(GUI.screen), GUI.visual, AllocNone);
int screen_left = 0, screen_top = 0;
int screen_w = WidthOfScreen(GUI.screen), screen_h = HeightOfScreen(GUI.screen);
#ifdef USE_XINERAMA
int heads = 0;
XineramaScreenInfo* si = 0;
int useless1, useless2;
if (!XineramaQueryExtension(GUI.display, &useless1, &useless2)) {
puts("Xinerama is not available");
goto xinerama_end;
}
if (!XineramaIsActive(GUI.display)) {
puts("Xinerama is not active");
goto xinerama_end;
}
si = XineramaQueryScreens(GUI.display, &heads);
if (!si) {
puts("XineramaQueryScreens failed");
goto xinerama_end;
}
if (GUI.xinerama_head >= heads) {
printf("Invalid xinerama head id (expected 0-%d, got %u)\n", heads - 1, GUI.xinerama_head);
goto xinerama_end;
}
si = &si[GUI.xinerama_head];
screen_left = si->x_org;
screen_top = si->y_org;
screen_w = si->width;
screen_h = si->height;
printf("Selected xinerama head %u (%d,%d %dx%d)\n", GUI.xinerama_head, screen_left, screen_top, screen_w, screen_h);
xinerama_end:
#endif
XSizeHints Hints;
memset((void *) &Hints, 0, sizeof(XSizeHints));
/* Try to switch to Fullscreen. */
if (GUI.fullscreen == TRUE)
{
Hints.flags = PPosition;
Hints.x = screen_left;
Hints.y = screen_top;
/* Create the window with maximum screen width,height positioned at 0,0. */
GUI.window = XCreateWindow(GUI.display, RootWindowOfScreen(GUI.screen),
0, 0,
WidthOfScreen(GUI.screen), HeightOfScreen(GUI.screen), 0,
Hints.x, Hints.y,
screen_w, screen_h, 0,
GUI.depth, InputOutput, GUI.visual, CWBackPixel | CWColormap, &attrib);
#ifdef USE_XVIDEO
if (GUI.use_xvideo)
{
// Set some defaults
GUI.scale_w = WidthOfScreen(GUI.screen);
GUI.scale_h = HeightOfScreen(GUI.screen);
GUI.scale_w = screen_w;
GUI.scale_h = screen_h;
GUI.imageHeight = SNES_HEIGHT_EXTENDED * 2;
if (! GUI.maxaspect)
{
// Compute the maximum screen size for scaling xvideo window.
double screenAspect = (double)WidthOfScreen(GUI.screen) / HeightOfScreen(GUI.screen);
double screenAspect = (double)screen_w / screen_h;
double snesAspect = (double)SNES_WIDTH / SNES_HEIGHT_EXTENDED;
double ratio = screenAspect / snesAspect;
printf("\tScreen (%dx%d) aspect %f vs SNES (%dx%d) aspect %f (ratio: %f)\n",
WidthOfScreen(GUI.screen),HeightOfScreen(GUI.screen),screenAspect,
screen_w,screen_h,screenAspect,
SNES_WIDTH,SNES_HEIGHT_EXTENDED,snesAspect,
ratio);
@ -889,12 +959,12 @@ void S9xInitDisplay (int argc, char **argv)
// widescreen monitor, 4:3 snes
// match height, scale width
GUI.scale_w /= ratio;
GUI.x_offset = (WidthOfScreen(GUI.screen) - GUI.scale_w) / 2;
GUI.x_offset = (screen_w - GUI.scale_w) / 2;
} else {
// narrow monitor, 4:3 snes
// match width, scale height
GUI.scale_h *= ratio;
GUI.y_offset = (HeightOfScreen(GUI.screen) - GUI.scale_h) / 2;
GUI.y_offset = (screen_h - GUI.scale_h) / 2;
}
}
@ -904,23 +974,21 @@ void S9xInitDisplay (int argc, char **argv)
#endif
{
/* Last: position the output window in the center of the screen. */
GUI.x_offset = (WidthOfScreen(GUI.screen) - SNES_WIDTH * 2) / 2;
GUI.y_offset = (HeightOfScreen(GUI.screen) - SNES_HEIGHT_EXTENDED * 2) / 2;
GUI.x_offset = (screen_w - SNES_WIDTH * 2) / 2;
GUI.y_offset = (screen_h - SNES_HEIGHT_EXTENDED * 2) / 2;
}
} else {
/* Create the window. */
GUI.window = XCreateWindow(GUI.display, RootWindowOfScreen(GUI.screen),
(WidthOfScreen(GUI.screen) - SNES_WIDTH * 2) / 2, (HeightOfScreen(GUI.screen) - SNES_HEIGHT_EXTENDED * 2) / 2,
SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 0, GUI.depth, InputOutput, GUI.visual, CWBackPixel | CWColormap, &attrib);
/* Tell the Window Manager that we do not wish to be resizable */
XSizeHints Hints;
memset((void *) &Hints, 0, sizeof(XSizeHints));
Hints.flags = PSize | PMinSize | PMaxSize;
Hints.flags = PSize | PMinSize | PMaxSize | PPosition;
Hints.x = screen_left + (screen_w - SNES_WIDTH * 2) / 2;
Hints.y = screen_top + (screen_h - SNES_HEIGHT_EXTENDED * 2) / 2;
Hints.min_width = Hints.max_width = Hints.base_width = SNES_WIDTH * 2;
Hints.min_height = Hints.max_height = Hints.base_height = SNES_HEIGHT_EXTENDED * 2;
XSetWMNormalHints(GUI.display, GUI.window, &Hints);
/* Create the window. */
GUI.window = XCreateWindow(GUI.display, RootWindowOfScreen(GUI.screen),
Hints.x, Hints.y,
SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 0, GUI.depth, InputOutput, GUI.visual, CWBackPixel | CWColormap, &attrib);
/* Last: Windowed SNES is not drawn with any offsets. */
GUI.x_offset = GUI.y_offset = 0;
@ -930,6 +998,8 @@ void S9xInitDisplay (int argc, char **argv)
#endif
}
XSetWMNormalHints(GUI.display, GUI.window, &Hints);
/* Load UI cursors */
static XColor bg, fg;
static char data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };