📄 sdl_x11modes.c
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org*/#include "SDL_config.h"/* Utilities for getting and setting the X display mode */#include <stdio.h>#include "SDL_timer.h"#include "SDL_events.h"#include "../../events/SDL_events_c.h"#include "SDL_x11video.h"#include "SDL_x11wm_c.h"#include "SDL_x11modes_c.h"#include "SDL_x11image_c.h"/*#define X11MODES_DEBUG*/#define MAX(a, b) (a > b ? a : b)#if SDL_VIDEO_DRIVER_X11_XRANDRstatic int cmpmodelist(const void *va, const void *vb){ const SDL_Rect *a = *(const SDL_Rect **)va; const SDL_Rect *b = *(const SDL_Rect **)vb; if ( a->w == b->w ) return b->h - a->h; else return b->w - a->w;}#endif#if SDL_VIDEO_DRIVER_X11_VIDMODEBool 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, (int*)&info->dotclock, l);}#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */#if SDL_VIDEO_DRIVER_X11_VIDMODEstatic void save_mode(_THIS){ SDL_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#if SDL_VIDEO_DRIVER_X11_VIDMODEstatic 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#if SDL_VIDEO_DRIVER_X11_VIDMODEstatic 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 b->vdisplay - a->vdisplay; else return b->hdisplay - a->hdisplay;}#endifstatic void get_real_resolution(_THIS, int* w, int* h);static void set_best_resolution(_THIS, int width, int height){#if SDL_VIDEO_DRIVER_X11_VIDMODE if ( use_vidmode ) { SDL_NAME(XF86VidModeModeLine) mode; SDL_NAME(XF86VidModeModeInfo) **modes; int i; int nmodes; int best = -1; if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) && SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes) ) { for ( i = 0; i < nmodes ; i++ ) { if ( (modes[i]->hdisplay == width) && (modes[i]->vdisplay == height) ) { best = i; break; } if ( modes[i]->hdisplay >= width && modes[i]->vdisplay >= height ) { if ( best < 0 || (modes[i]->hdisplay < modes[best]->hdisplay && modes[i]->vdisplay <= modes[best]->vdisplay) || (modes[i]->vdisplay < modes[best]->vdisplay && modes[i]->hdisplay <= modes[best]->hdisplay) ) { best = i; } } } if ( best >= 0 && ((modes[best]->hdisplay != mode.hdisplay) || (modes[best]->vdisplay != mode.vdisplay)) ) {#ifdef X11MODES_DEBUG printf("Best Mode %d: %d x %d @ %d\n", best, modes[best]->hdisplay, modes[best]->vdisplay, (modes[best]->htotal && modes[best]->vtotal) ? (1000 * modes[best]->dotclock / (modes[best]->htotal * modes[best]->vtotal)) : 0 );#endif SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[best]); } XFree(modes); } }#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ /* XiG */#if SDL_VIDEO_DRIVER_X11_XME if ( use_xme && SDL_modelist ) { int i;#ifdef X11MODES_DEBUG fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n", width, height);#endif 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 X11MODES_DEBUG fprintf(stderr, "XME: set_best_resolution: " "XiGMiscChangeResolution: %d %d\n", SDL_modelist[i]->w, SDL_modelist[i]->h);#endif XiGMiscChangeResolution(SDL_Display, SDL_Screen, 0, /* view */ SDL_modelist[i]->w, SDL_modelist[i]->h, 0); XSync(SDL_Display, False); } } }#endif /* SDL_VIDEO_DRIVER_X11_XME */#if SDL_VIDEO_DRIVER_X11_XRANDR if ( use_xrandr && SDL_modelist ) {#ifdef X11MODES_DEBUG fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n", width, height);#endif int i, nsizes; XRRScreenSize *sizes; /* find the smallest resolution that is at least as big as the user requested */ sizes = XRRConfigSizes(screen_config, &nsizes); for ( i = (nsizes-1); i >= 0; i-- ) { if ( (SDL_modelist[i]->w >= width) && (SDL_modelist[i]->h >= height) ) { break; } } if ( i >= 0 && 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) ) { int size_id;#ifdef X11MODES_DEBUG fprintf(stderr, "XRANDR: set_best_resolution: " "XXRSetScreenConfig: %d %d\n", SDL_modelist[i]->w, SDL_modelist[i]->h);#endif /* find the matching size entry index */ for ( size_id = 0; size_id < nsizes; ++size_id ) { if ( (sizes[size_id].width == SDL_modelist[i]->w) && (sizes[size_id].height == SDL_modelist[i]->h) ) break; } XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, size_id, saved_rotation, CurrentTime); } } }#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */}static void get_real_resolution(_THIS, int* w, int* h){#if SDL_VIDEO_DRIVER_X11_XME 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 X11MODES_DEBUG fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h);#endif XFree(modelist); return; }#endif /* SDL_VIDEO_DRIVER_X11_XME */#if SDL_VIDEO_DRIVER_X11_VIDMODE 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 /* SDL_VIDEO_DRIVER_X11_VIDMODE */#if SDL_VIDEO_DRIVER_X11_XRANDR if ( use_xrandr ) { int nsizes; XRRScreenSize* sizes; sizes = XRRConfigSizes(screen_config, &nsizes); if ( nsizes > 0 ) { int cur_size; Rotation cur_rotation; cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation); if ( cur_size >= 0 && cur_size < nsizes ) { *w = sizes[cur_size].width; *h = sizes[cur_size].height; }#ifdef X11MODES_DEBUG fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h);#endif return; } }#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */#if SDL_VIDEO_DRIVER_X11_XINERAMA if ( use_xinerama ) { *w = xinerama_info.width; *h = xinerama_info.height; return; }#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ *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 ) { SDL_memset(&template, 0, (sizeof template)); template.visualid = SDL_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;#if SDL_VIDEO_DRIVER_X11_XINERAMAstatic int CheckXinerama(_THIS, int *major, int *minor){ const char *env; /* Default the extension not available */ *major = *minor = 0; /* Allow environment override */ env = getenv("SDL_VIDEO_X11_XINERAMA"); if ( env && !SDL_atoi(env) ) { return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -