📄 sdl_x11modes.c
字号:
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_x11modes.c,v 1.4 2002/04/22 21:38:06 wmay Exp $";
#endif
/* Utilities for getting and setting the X display mode */
#include <stdlib.h>
#include <string.h>
#include "SDL_timer.h"
#include "SDL_error.h"
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "SDL_x11video.h"
#include "SDL_x11wm_c.h"
#include "SDL_x11modes_c.h"
#include "SDL_x11image_c.h"
#ifdef HAVE_XINERAMA
#include <XFree86/extensions/Xinerama.h>
#endif
#define MAX(a, b) (a > b ? a : b)
#ifdef XFREE86_VM
Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info)
{
SDL_NAME(XF86VidModeModeLine) *l = (SDL_NAME(XF86VidModeModeLine)*)((char*)info + sizeof info->dotclock);
return SDL_NAME(XF86VidModeGetModeLine)(dpy, scr, &info->dotclock, l);
}
#endif /* XFREE86_VM */
#ifdef XFREE86_VM
static void save_mode(_THIS)
{
memset(&saved_mode, 0, sizeof(saved_mode));
SDL_NAME(XF86VidModeGetModeInfo)(SDL_Display,SDL_Screen,&saved_mode);
SDL_NAME(XF86VidModeGetViewPort)(SDL_Display,SDL_Screen,&saved_view.x,&saved_view.y);
}
#endif
#ifdef XFREE86_VM
static void restore_mode(_THIS)
{
SDL_NAME(XF86VidModeModeLine) mode;
int unused;
if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) {
if ( (saved_mode.hdisplay != mode.hdisplay) ||
(saved_mode.vdisplay != mode.vdisplay) ) {
SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, &saved_mode);
}
}
if ( (saved_view.x != 0) || (saved_view.y != 0) ) {
SDL_NAME(XF86VidModeSetViewPort)(SDL_Display, SDL_Screen, saved_view.x, saved_view.y);
}
}
#endif
#ifdef XFREE86_VM
static int cmpmodes(const void *va, const void *vb)
{
const SDL_NAME(XF86VidModeModeInfo) *a = *(const SDL_NAME(XF86VidModeModeInfo)**)va;
const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb;
if(a->hdisplay > b->hdisplay)
return -1;
return b->vdisplay - a->vdisplay;
}
#endif
static void get_real_resolution(_THIS, int* w, int* h);
static void set_best_resolution(_THIS, int width, int height)
{
#ifdef XFREE86_VM
if ( use_vidmode ) {
SDL_NAME(XF86VidModeModeLine) mode;
SDL_NAME(XF86VidModeModeInfo) **modes;
int i;
int nmodes;
if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) &&
SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes)){
qsort(modes, nmodes, sizeof *modes, cmpmodes);
#ifdef XFREE86_DEBUG
printf("Available modes:\n");
for ( i = 0; i < nmodes; ++i ) {
printf("Mode %d: %dx%d\n", i,
modes[i]->hdisplay, modes[i]->vdisplay);
}
#endif
for ( i = nmodes-1; i > 0 ; --i ) {
if ( (modes[i]->hdisplay >= width) &&
(modes[i]->vdisplay >= height) )
break;
}
if ( (modes[i]->hdisplay != mode.hdisplay) ||
(modes[i]->vdisplay != mode.vdisplay) ) {
SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[i]);
}
XFree(modes);
}
}
#endif /* XFREE86_VM */
/* XiG */
#ifdef HAVE_XIGXME
#ifdef XIG_DEBUG
fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n",
width, height);
#endif
if ( SDL_modelist ) {
int i;
for ( i=0; SDL_modelist[i]; ++i ) {
if ( (SDL_modelist[i]->w >= width) &&
(SDL_modelist[i]->h >= height) ) {
break;
}
}
if ( SDL_modelist[i] ) { /* found one, lets try it */
int w, h;
/* check current mode so we can avoid uneccessary mode changes */
get_real_resolution(this, &w, &h);
if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
# ifdef XIG_DEBUG
fprintf(stderr, "XME: set_best_resolution: "
"XiGMiscChangeResolution: %d %d\n",
SDL_modelist[s]->w, SDL_modelist[s]->h);
# endif
XiGMiscChangeResolution(SDL_Display,
SDL_Screen,
0, /* view */
SDL_modelist[i]->w,
SDL_modelist[i]->h,
0);
XSync(SDL_Display, False);
}
}
}
#endif /* HAVE_XIGXME */
}
static void get_real_resolution(_THIS, int* w, int* h)
{
#ifdef XFREE86_VM
if ( use_vidmode ) {
SDL_NAME(XF86VidModeModeLine) mode;
int unused;
if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) {
*w = mode.hdisplay;
*h = mode.vdisplay;
return;
}
}
#endif
#ifdef HAVE_XIGXME
if ( use_xme ) {
int ractive;
XiGMiscResolutionInfo *modelist;
XiGMiscQueryResolutions(SDL_Display, SDL_Screen,
0, /* view */
&ractive, &modelist);
*w = modelist[ractive].width;
*h = modelist[ractive].height;
#ifdef XIG_DEBUG
fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h);
#endif
XFree(modelist);
return;
}
#endif /* XIG_XME */
*w = DisplayWidth(SDL_Display, SDL_Screen);
*h = DisplayHeight(SDL_Display, SDL_Screen);
}
/* Called after mapping a window - waits until the window is mapped */
void X11_WaitMapped(_THIS, Window win)
{
XEvent event;
do {
XMaskEvent(SDL_Display, StructureNotifyMask, &event);
} while ( (event.type != MapNotify) || (event.xmap.event != win) );
}
/* Called after unmapping a window - waits until the window is unmapped */
void X11_WaitUnmapped(_THIS, Window win)
{
XEvent event;
do {
XMaskEvent(SDL_Display, StructureNotifyMask, &event);
} while ( (event.type != UnmapNotify) || (event.xunmap.event != win) );
}
static void move_cursor_to(_THIS, int x, int y)
{
XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y);
}
static int add_visual(_THIS, int depth, int class)
{
XVisualInfo vi;
if(XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) {
int n = this->hidden->nvisuals;
this->hidden->visuals[n].depth = vi.depth;
this->hidden->visuals[n].visual = vi.visual;
this->hidden->nvisuals++;
}
return(this->hidden->nvisuals);
}
static int add_visual_byid(_THIS, const char *visual_id)
{
XVisualInfo *vi, template;
int nvis;
if ( visual_id ) {
memset(&template, 0, (sizeof template));
template.visualid = strtol(visual_id, NULL, 0);
vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis);
if ( vi ) {
int n = this->hidden->nvisuals;
this->hidden->visuals[n].depth = vi->depth;
this->hidden->visuals[n].visual = vi->visual;
this->hidden->nvisuals++;
XFree(vi);
}
}
return(this->hidden->nvisuals);
}
/* Global for the error handler */
int vm_event, vm_error = -1;
int X11_GetVideoModes(_THIS)
{
#ifdef XFREE86_VM
int buggy_X11;
int vm_major, vm_minor;
int nmodes;
SDL_NAME(XF86VidModeModeInfo) **modes;
#endif
#ifdef HAVE_XIGXME
int xme_major, xme_minor;
int ractive, nummodes;
XiGMiscResolutionInfo *modelist;
#endif
int i, n;
int screen_w;
int screen_h;
vm_error = -1;
use_vidmode = 0;
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
#ifdef XFREE86_VM
/* Metro-X 4.3.0 and earlier has a broken implementation of
XF86VidModeGetAllModeLines() - it hangs the client.
*/
buggy_X11 = 0;
if ( strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) {
FILE *metro_fp;
metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r");
if ( metro_fp != NULL ) {
int major, minor, patch, version;
major = 0; minor = 0; patch = 0;
fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch);
version = major*100+minor*10+patch;
if ( version < 431 ) {
buggy_X11 = 1;
}
fclose(metro_fp);
}
}
#if defined(__alpha__) || defined(__powerpc__)
/* The alpha and PPC XFree86 servers are also buggy */
buggy_X11 = 1;
#endif
/* Enumerate the available fullscreen modes */
if ( ! buggy_X11 ) {
if ( SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) &&
SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, &vm_major, &vm_minor) ) {
#ifdef BROKEN_XFREE86_4001
#ifdef X_XF86VidModeGetDotClocks /* Compiled under XFree86 4.0 */
/* Earlier X servers hang when doing vidmode */
if ( vm_major < 2 ) {
#ifdef XFREE86_DEBUG
printf("Compiled under XFree86 4.0, server is XFree86 3.X\n");
#endif
buggy_X11 = 1;
}
#else
/* XFree86 3.X code works with XFree86 4.0 servers */;
#endif /* XFree86 4.0 */
#endif /* XFree86 4.02 and newer are fixed wrt backwards compatibility */
} else {
buggy_X11 = 1;
}
}
if ( ! buggy_X11 &&
SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {
qsort(modes, nmodes, sizeof *modes, cmpmodes);
SDL_modelist = (SDL_Rect **)malloc((nmodes+2)*sizeof(SDL_Rect *));
if ( SDL_modelist ) {
n = 0;
for ( i=0; i<nmodes; ++i ) {
int w, h;
/* Check to see if we should add the screen size (Xinerama) */
w = modes[i]->hdisplay;
h = modes[i]->vdisplay;
if ( (screen_w * screen_h) >= (w * h) ) {
if ( (screen_w != w) || (screen_h != h) ) {
SDL_modelist[n] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
if ( SDL_modelist[n] ) {
SDL_modelist[n]->x = 0;
SDL_modelist[n]->y = 0;
SDL_modelist[n]->w = screen_w;
SDL_modelist[n]->h = screen_h;
++n;
}
}
screen_w = 0;
screen_h = 0;
}
/* Add the size from the video mode list */
SDL_modelist[n] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
if ( SDL_modelist[n] == NULL ) {
break;
}
SDL_modelist[n]->x = 0;
SDL_modelist[n]->y = 0;
SDL_modelist[n]->w = w;
SDL_modelist[n]->h = h;
++n;
}
SDL_modelist[n] = NULL;
}
XFree(modes);
use_vidmode = vm_major * 100 + vm_minor;
save_mode(this);
}
#endif /* XFREE86_VM */
/* XiG */
#ifdef HAVE_XIGXME
/* first lets make sure we have the extension, and it's at least v2.0 */
if (XiGMiscQueryVersion(SDL_Display, &xme_major, &xme_minor)) {
#ifdef XIG_DEBUG
fprintf(stderr, "XME: XiGMiscQueryVersion: V%d.%d\n",
xme_major, xme_minor);
#endif
/* work around a XiGMisc bogosity in our version of libXext */
if (xme_major == 0 && xme_major == 0) {
/* Ideally libxme would spit this out, but the problem is that
the right Query func will never be called if using the bogus
libXext version.
*/
fprintf(stderr,
"XME: If you are using Xi Graphics CDE and a Summit server, you need to\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -