Merge pull request #196 from Francesco149/xinerama

Add xinerama multi-monitor support and position window hints
This commit is contained in:
bearoso 2018-05-19 15:47:38 -05:00 committed by GitHub
commit 4dcf4ddc74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 133 additions and 20 deletions

26
unix/configure vendored
View File

@ -719,6 +719,7 @@ enable_jma
enable_screenshot enable_screenshot
with_x with_x
enable_xvideo enable_xvideo
enable_xinerama
enable_sound enable_sound
' '
ac_precious_vars='build_alias ac_precious_vars='build_alias
@ -1370,6 +1371,7 @@ Optional Features:
--enable-screenshot enable screenshot support through libpng (default: --enable-screenshot enable screenshot support through libpng (default:
yes) yes)
--enable-xvideo enable Xvideo if available (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) --enable-sound enable sound if available (default: yes)
Optional Packages: Optional Packages:
@ -6253,6 +6255,29 @@ if test "x$ac_cv_header_X11_extensions_Xv_h" = xyes; then :
fi 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 fi
# Check if we have sound code for this platform. # Check if we have sound code for this platform.
@ -6333,6 +6358,7 @@ libs................. $S9XLIBS
features: features:
Xvideo support....... $enable_xvideo Xvideo support....... $enable_xvideo
Xinerama support..... $enable_xinerama
sound support........ $enable_sound sound support........ $enable_sound
screenshot support... $enable_screenshot screenshot support... $enable_screenshot
netplay support...... $enable_netplay netplay support...... $enable_netplay

View File

@ -406,6 +406,22 @@ if test "x$enable_xvideo" = "xyes"; then
]) ])
fi 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. # Check if we have sound code for this platform.
AC_ARG_ENABLE([sound], AC_ARG_ENABLE([sound],
@ -473,6 +489,7 @@ libs................. $S9XLIBS
features: features:
Xvideo support....... $enable_xvideo Xvideo support....... $enable_xvideo
Xinerama support..... $enable_xinerama
sound support........ $enable_sound sound support........ $enable_sound
screenshot support... $enable_screenshot screenshot support... $enable_screenshot
netplay support...... $enable_netplay netplay support...... $enable_netplay

View File

@ -214,6 +214,10 @@
#define FOURCC_YUY2 0x32595559 #define FOURCC_YUY2 0x32595559
#endif #endif
#ifdef USE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef MITSHM #ifdef MITSHM
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
@ -299,6 +303,9 @@ struct GUIData
unsigned char u_table[1 << 15]; unsigned char u_table[1 << 15];
unsigned char v_table[1 << 15]; unsigned char v_table[1 << 15];
#endif #endif
#ifdef USE_XINERAMA
uint32 xinerama_head;
#endif
#ifdef MITSHM #ifdef MITSHM
XShmSegmentInfo sm_info; XShmSegmentInfo sm_info;
bool8 use_shared_memory; bool8 use_shared_memory;
@ -363,6 +370,9 @@ void S9xExtraDisplayUsage (void)
#ifdef USE_XVIDEO #ifdef USE_XVIDEO
S9xMessage(S9X_INFO, S9X_USAGE, "-xvideo Hardware accelerated scaling"); S9xMessage(S9X_INFO, S9X_USAGE, "-xvideo Hardware accelerated scaling");
S9xMessage(S9X_INFO, S9X_USAGE, "-maxaspect Try to fill the display, in fullscreen"); 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 #endif
S9xMessage(S9X_INFO, S9X_USAGE, ""); S9xMessage(S9X_INFO, S9X_USAGE, "");
S9xMessage(S9X_INFO, S9X_USAGE, "-v1 Video mode: Blocky (default)"); S9xMessage(S9X_INFO, S9X_USAGE, "-v1 Video mode: Blocky (default)");
@ -391,6 +401,16 @@ void S9xParseDisplayArg (char **argv, int &i, int argc)
if (!strcasecmp(argv[i], "-maxaspect")) if (!strcasecmp(argv[i], "-maxaspect"))
GUI.maxaspect = TRUE; GUI.maxaspect = TRUE;
else else
#endif
#ifdef USE_XINERAMA
if (!strcasecmp(argv[i], "-xineramahead"))
{
if (i + 1 < argc)
GUI.xinerama_head = atoi(argv[++i]);
else
S9xUsage();
}
else
#endif #endif
if (!strncasecmp(argv[i], "-v", 2)) if (!strncasecmp(argv[i], "-v", 2))
{ {
@ -555,6 +575,9 @@ const char * S9xParseDisplayConfig (ConfigFile &conf, int pass)
GUI.use_xvideo = conf.GetBool("Unix/X11::Xvideo", FALSE); GUI.use_xvideo = conf.GetBool("Unix/X11::Xvideo", FALSE);
GUI.maxaspect = conf.GetBool("Unix/X11::MaxAspect", FALSE); GUI.maxaspect = conf.GetBool("Unix/X11::MaxAspect", FALSE);
#endif #endif
#ifdef USE_XINERAMA
GUI.xinerama_head = conf.GetUInt("Unix/X11::XineramaHead", 0);
#endif
if (conf.Exists("Unix/X11::VideoMode")) if (conf.Exists("Unix/X11::VideoMode"))
{ {
@ -855,13 +878,60 @@ void S9xInitDisplay (int argc, char **argv)
attrib.background_pixel = BlackPixelOfScreen(GUI.screen); attrib.background_pixel = BlackPixelOfScreen(GUI.screen);
attrib.colormap = XCreateColormap(GUI.display, RootWindowOfScreen(GUI.screen), GUI.visual, AllocNone); 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. */ /* Try to switch to Fullscreen. */
if (GUI.fullscreen == TRUE) 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. */ /* Create the window with maximum screen width,height positioned at 0,0. */
GUI.window = XCreateWindow(GUI.display, RootWindowOfScreen(GUI.screen), GUI.window = XCreateWindow(GUI.display, RootWindowOfScreen(GUI.screen),
0, 0, Hints.x, Hints.y,
WidthOfScreen(GUI.screen), HeightOfScreen(GUI.screen), 0, screen_w, screen_h, 0,
GUI.depth, InputOutput, GUI.visual, CWBackPixel | CWColormap, &attrib); GUI.depth, InputOutput, GUI.visual, CWBackPixel | CWColormap, &attrib);
/* Try to tell the Window Manager not to decorate this window. */ /* Try to tell the Window Manager not to decorate this window. */
@ -874,20 +944,20 @@ void S9xInitDisplay (int argc, char **argv)
if (GUI.use_xvideo) if (GUI.use_xvideo)
{ {
// Set some defaults // Set some defaults
GUI.scale_w = WidthOfScreen(GUI.screen); GUI.scale_w = screen_w;
GUI.scale_h = HeightOfScreen(GUI.screen); GUI.scale_h = screen_h;
GUI.imageHeight = SNES_HEIGHT_EXTENDED * 2; GUI.imageHeight = SNES_HEIGHT_EXTENDED * 2;
if (! GUI.maxaspect) if (! GUI.maxaspect)
{ {
// Compute the maximum screen size for scaling xvideo window. // 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 snesAspect = (double)SNES_WIDTH / SNES_HEIGHT_EXTENDED;
double ratio = screenAspect / snesAspect; double ratio = screenAspect / snesAspect;
printf("\tScreen (%dx%d) aspect %f vs SNES (%dx%d) aspect %f (ratio: %f)\n", 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, SNES_WIDTH,SNES_HEIGHT_EXTENDED,snesAspect,
ratio); ratio);
@ -897,12 +967,12 @@ void S9xInitDisplay (int argc, char **argv)
// widescreen monitor, 4:3 snes // widescreen monitor, 4:3 snes
// match height, scale width // match height, scale width
GUI.scale_w /= ratio; GUI.scale_w /= ratio;
GUI.x_offset = (WidthOfScreen(GUI.screen) - GUI.scale_w) / 2; GUI.x_offset = (screen_w - GUI.scale_w) / 2;
} else { } else {
// narrow monitor, 4:3 snes // narrow monitor, 4:3 snes
// match width, scale height // match width, scale height
GUI.scale_h *= ratio; GUI.scale_h *= ratio;
GUI.y_offset = (HeightOfScreen(GUI.screen) - GUI.scale_h) / 2; GUI.y_offset = (screen_h - GUI.scale_h) / 2;
} }
} }
@ -912,23 +982,21 @@ void S9xInitDisplay (int argc, char **argv)
#endif #endif
{ {
/* Last: position the output window in the center of the screen. */ /* Last: position the output window in the center of the screen. */
GUI.x_offset = (WidthOfScreen(GUI.screen) - SNES_WIDTH * 2) / 2; GUI.x_offset = (screen_w - SNES_WIDTH * 2) / 2;
GUI.y_offset = (HeightOfScreen(GUI.screen) - SNES_HEIGHT_EXTENDED * 2) / 2; GUI.y_offset = (screen_h - SNES_HEIGHT_EXTENDED * 2) / 2;
} }
} else { } 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 */ /* Tell the Window Manager that we do not wish to be resizable */
XSizeHints Hints; Hints.flags = PSize | PMinSize | PMaxSize | PPosition;
memset((void *) &Hints, 0, sizeof(XSizeHints)); Hints.x = screen_left + (screen_w - SNES_WIDTH * 2) / 2;
Hints.y = screen_top + (screen_h - SNES_HEIGHT_EXTENDED * 2) / 2;
Hints.flags = PSize | PMinSize | PMaxSize;
Hints.min_width = Hints.max_width = Hints.base_width = SNES_WIDTH * 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; 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. */ /* Last: Windowed SNES is not drawn with any offsets. */
GUI.x_offset = GUI.y_offset = 0; GUI.x_offset = GUI.y_offset = 0;
@ -938,6 +1006,8 @@ void S9xInitDisplay (int argc, char **argv)
#endif #endif
} }
XSetWMNormalHints(GUI.display, GUI.window, &Hints);
/* Load UI cursors */ /* Load UI cursors */
static XColor bg, fg; static XColor bg, fg;
static char data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static char data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };