📄 sdl_x11video.c
字号:
}
/* Update the internal keyboard state */
X11_SetKeyboardState(SDL_Display, NULL);
/* Map them both and go fullscreen, if requested */
if ( ! SDL_windowid ) {
XMapWindow(SDL_Display, SDL_Window);
XMapWindow(SDL_Display, WMwindow);
X11_WaitMapped(this, WMwindow);
if ( flags & SDL_FULLSCREEN ) {
screen->flags |= SDL_FULLSCREEN;
X11_EnterFullScreen(this);
} else {
screen->flags &= ~SDL_FULLSCREEN;
}
}
return(0);
}
static int X11_ResizeWindow(_THIS,
SDL_Surface *screen, int w, int h, Uint32 flags)
{
if ( ! SDL_windowid ) {
/* Resize the window manager window */
X11_SetSizeHints(this, w, h, flags);
current_w = w;
current_h = h;
XResizeWindow(SDL_Display, WMwindow, w, h);
/* Resize the fullscreen and display windows */
if ( flags & SDL_FULLSCREEN ) {
if ( screen->flags & SDL_FULLSCREEN ) {
X11_ResizeFullScreen(this);
} else {
screen->flags |= SDL_FULLSCREEN;
X11_EnterFullScreen(this);
}
} else {
if ( screen->flags & SDL_FULLSCREEN ) {
screen->flags &= ~SDL_FULLSCREEN;
X11_LeaveFullScreen(this);
}
}
XResizeWindow(SDL_Display, SDL_Window, w, h);
}
return(0);
}
SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
Uint32 saved_flags;
/* Lock the event thread, in multi-threading environments */
SDL_Lock_EventThread();
/* Check the combination of flags we were passed */
if ( flags & SDL_FULLSCREEN ) {
/* Clear fullscreen flag if not supported */
if ( SDL_windowid ) {
flags &= ~SDL_FULLSCREEN;
}
}
/* Flush any delayed updates */
XSync(GFX_Display, False);
/* Set up the X11 window */
saved_flags = current->flags;
if (SDL_Window && (saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)
&& bpp == current->format->BitsPerPixel) {
if (X11_ResizeWindow(this, current, width, height, flags) < 0) {
current = NULL;
goto done;
}
} else {
if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) {
current = NULL;
goto done;
}
}
/* Set up the new mode framebuffer */
if ( ((current->w != width) || (current->h != height)) ||
((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) {
current->w = width;
current->h = height;
current->pitch = SDL_CalculatePitch(current);
X11_ResizeImage(this, current, flags);
}
current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME));
done:
/* Release the event thread */
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
/* We're done! */
return(current);
}
static int X11_ToggleFullScreen(_THIS, int on)
{
Uint32 event_thread;
/* Don't switch if we don't own the window */
if ( SDL_windowid ) {
return(0);
}
/* Don't lock if we are the event thread */
event_thread = SDL_EventThreadID();
if ( event_thread && (SDL_ThreadID() == event_thread) ) {
event_thread = 0;
}
if ( event_thread ) {
SDL_Lock_EventThread();
}
if ( on ) {
this->screen->flags |= SDL_FULLSCREEN;
X11_EnterFullScreen(this);
} else {
this->screen->flags &= ~SDL_FULLSCREEN;
X11_LeaveFullScreen(this);
}
X11_RefreshDisplay(this);
if ( event_thread ) {
SDL_Unlock_EventThread();
}
SDL_ResetKeyboard();
return(1);
}
/* Update the current mouse state and position */
static void X11_UpdateMouse(_THIS)
{
Window u1; int u2;
Window current_win;
int x, y;
unsigned int mask;
/* Lock the event thread, in multi-threading environments */
SDL_Lock_EventThread();
if ( XQueryPointer(SDL_Display, SDL_Window, &u1, ¤t_win,
&u2, &u2, &x, &y, &mask) ) {
if ( (x >= 0) && (x < SDL_VideoSurface->w) &&
(y >= 0) && (y < SDL_VideoSurface->h) ) {
SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
SDL_PrivateMouseMotion(0, 0, x, y);
} else {
SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
}
}
SDL_Unlock_EventThread();
}
/* simple colour distance metric. Supposed to be better than a plain
Euclidian distance anyway. */
#define COLOUR_FACTOR 3
#define LIGHT_FACTOR 1
#define COLOUR_DIST(r1, g1, b1, r2, g2, b2) \
(COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2)) \
+ LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2)))
static void allocate_nearest(_THIS, SDL_Color *colors,
SDL_Color *want, int nwant)
{
/*
* There is no way to know which ones to choose from, so we retrieve
* the entire colormap and try the nearest possible, until we find one
* that is shared.
*/
XColor all[256];
int i;
for(i = 0; i < 256; i++)
all[i].pixel = i;
/*
* XQueryColors sets the flags in the XColor struct, so we use
* that to keep track of which colours are available
*/
XQueryColors(GFX_Display, SDL_XColorMap, all, 256);
for(i = 0; i < nwant; i++) {
XColor *c;
int j;
int best = 0;
int mindist = 0x7fffffff;
int ri = want[i].r;
int gi = want[i].g;
int bi = want[i].b;
for(j = 0; j < 256; j++) {
int rj, gj, bj, d2;
if(!all[j].flags)
continue; /* unavailable colour cell */
rj = all[j].red >> 8;
gj = all[j].green >> 8;
bj = all[j].blue >> 8;
d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj);
if(d2 < mindist) {
mindist = d2;
best = j;
}
}
if(SDL_XPixels[best])
continue; /* already allocated, waste no more time */
c = all + best;
if(XAllocColor(GFX_Display, SDL_XColorMap, c)) {
/* got it */
colors[c->pixel].r = c->red >> 8;
colors[c->pixel].g = c->green >> 8;
colors[c->pixel].b = c->blue >> 8;
++SDL_XPixels[c->pixel];
} else {
/*
* The colour couldn't be allocated, probably being
* owned as a r/w cell by another client. Flag it as
* unavailable and try again. The termination of the
* loop is guaranteed since at least black and white
* are always there.
*/
c->flags = 0;
i--;
}
}
}
int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
int nrej = 0;
/* Check to make sure we have a colormap allocated */
if ( SDL_XPixels == NULL ) {
return(0);
}
if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
/* private writable colormap: just set the colours we need */
XColor *xcmap;
int i;
xcmap = ALLOCA(ncolors*sizeof(*xcmap));
if(xcmap == NULL)
return 0;
for ( i=0; i<ncolors; ++i ) {
xcmap[i].pixel = i + firstcolor;
xcmap[i].red = (colors[i].r<<8)|colors[i].r;
xcmap[i].green = (colors[i].g<<8)|colors[i].g;
xcmap[i].blue = (colors[i].b<<8)|colors[i].b;
xcmap[i].flags = (DoRed|DoGreen|DoBlue);
}
XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
XSync(GFX_Display, False);
FREEA(xcmap);
} else {
/*
* Shared colormap: We only allocate read-only cells, which
* increases the likelyhood of colour sharing with other
* clients. The pixel values will almost certainly be
* different from the requested ones, so the user has to
* walk the colormap and see which index got what colour.
*
* We can work directly with the logical palette since it
* has already been set when we get here.
*/
SDL_Color *want, *reject;
unsigned long *freelist;
int i;
int nfree = 0;
int nc = this->screen->format->palette->ncolors;
colors = this->screen->format->palette->colors;
freelist = ALLOCA(nc * sizeof(*freelist));
/* make sure multiple allocations of the same cell are freed */
for(i = 0; i < ncolors; i++) {
int pixel = firstcolor + i;
while(SDL_XPixels[pixel]) {
freelist[nfree++] = pixel;
--SDL_XPixels[pixel];
}
}
XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0);
FREEA(freelist);
want = ALLOCA(ncolors * sizeof(SDL_Color));
reject = ALLOCA(ncolors * sizeof(SDL_Color));
memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color));
/* make sure the user isn't fooled by her own wishes
(black is safe, always available in the default colormap) */
memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color));
/* now try to allocate the colours */
for(i = 0; i < ncolors; i++) {
XColor col;
col.red = want[i].r << 8;
col.green = want[i].g << 8;
col.blue = want[i].b << 8;
col.flags = DoRed | DoGreen | DoBlue;
if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) {
/* We got the colour, or at least the nearest
the hardware could get. */
colors[col.pixel].r = col.red >> 8;
colors[col.pixel].g = col.green >> 8;
colors[col.pixel].b = col.blue >> 8;
++SDL_XPixels[col.pixel];
} else {
/*
* no more free cells, add it to the list
* of rejected colours
*/
reject[nrej++] = want[i];
}
}
if(nrej)
allocate_nearest(this, colors, reject, nrej);
FREEA(reject);
FREEA(want);
}
return nrej == 0;
}
int X11_SetGammaRamp(_THIS, Uint16 *ramp)
{
int i, ncolors;
XColor xcmap[256];
/* See if actually setting the gamma is supported */
if ( SDL_Visual->class != DirectColor ) {
SDL_SetError("Gamma correction not supported on this visual");
return(-1);
}
/* Calculate the appropriate palette for the given gamma ramp */
ncolors = SDL_Visual->map_entries;
for ( i=0; i<ncolors; ++i ) {
Uint8 c = (256 * i / ncolors);
xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c);
xcmap[i].red = ramp[0*256+c];
xcmap[i].green = ramp[1*256+c];
xcmap[i].blue = ramp[2*256+c];
xcmap[i].flags = (DoRed|DoGreen|DoBlue);
}
XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
XSync(GFX_Display, False);
return(0);
}
/* Note: If we are terminated, this could be called in the middle of
another SDL video routine -- notably UpdateRects.
*/
void X11_VideoQuit(_THIS)
{
/* Shutdown everything that's still up */
/* The event thread should be done, so we can touch SDL_Display */
if ( SDL_Display != NULL ) {
/* Flush any delayed updates */
XSync(GFX_Display, False);
/* Start shutting down the windows */
X11_DestroyImage(this, this->screen);
X11_DestroyWindow(this, this->screen);
X11_FreeVideoModes(this);
if ( SDL_XColorMap != SDL_DisplayColormap ) {
XFreeColormap(SDL_Display, SDL_XColorMap);
}
if ( SDL_iconcolors ) {
unsigned long pixel;
Colormap dcmap = DefaultColormap(SDL_Display,
SDL_Screen);
for(pixel = 0; pixel < 256; ++pixel) {
while(SDL_iconcolors[pixel] > 0) {
XFreeColors(GFX_Display,
dcmap, &pixel, 1, 0);
--SDL_iconcolors[pixel];
}
}
free(SDL_iconcolors);
SDL_iconcolors = NULL;
}
/* Restore gamma settings if they've changed */
if ( SDL_GetAppState() & SDL_APPACTIVE ) {
X11_SwapVidModeGamma(this);
}
/* Free that blank cursor */
if ( SDL_BlankCursor != NULL ) {
this->FreeWMCursor(this, SDL_BlankCursor);
SDL_BlankCursor = NULL;
}
/* Close the X11 graphics connection */
if ( GFX_Display != NULL ) {
XCloseDisplay(GFX_Display);
GFX_Display = NULL;
}
/* Close the X11 display connection */
XCloseDisplay(SDL_Display);
SDL_Display = NULL;
/* Reset the X11 error handlers */
if ( XIO_handler ) {
XSetIOErrorHandler(XIO_handler);
}
if ( X_handler ) {
XSetErrorHandler(X_handler);
}
/* Unload GL library after X11 shuts down */
X11_GL_UnloadLibrary(this);
}
if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
/* Direct screen access, no memory buffer */
this->screen->pixels = NULL;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -