📄 sdl_x11video.c
字号:
} /* Only manage our input if we own the window */ XSelectInput(SDL_Display, SDL_Window, ( EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask )); } /* Create the graphics context here, once we have a window */ if ( flags & SDL_OPENGL ) { if ( X11_GL_CreateContext(this) < 0 ) { return(-1); } else { screen->flags |= SDL_OPENGL; } } else { XGCValues gcv; gcv.graphics_exposures = False; SDL_GC = XCreateGC(SDL_Display, SDL_Window, GCGraphicsExposures, &gcv); if ( ! SDL_GC ) { SDL_SetError("Couldn't create graphics context"); return(-1); } } /* Set our colormaps when not setting a GL mode */ if ( ! (flags & SDL_OPENGL) ) { XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); if( !SDL_windowid ) { XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap); XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap); } }#if 0 /* This is an experiment - are the graphics faster now? - nope. */ if ( SDL_getenv("SDL_VIDEO_X11_BACKINGSTORE") )#endif /* Cache the window in the server, when possible */ { Screen *xscreen; XSetWindowAttributes a; xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen); a.backing_store = DoesBackingStore(xscreen); if ( a.backing_store != NotUseful ) { XChangeWindowAttributes(SDL_Display, SDL_Window, CWBackingStore, &a); } } /* 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); window_w = w; window_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) && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) { 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; } } /* Update the internal keyboard state */ X11_SetKeyboardState(SDL_Display, NULL); /* When the window is first mapped, ignore non-modifier keys */ if ( !current->w && !current->h ) { Uint8 *keys = SDL_GetKeyState(NULL); int i; for ( i = 0; i < SDLK_LAST; ++i ) { switch (i) { case SDLK_NUMLOCK: case SDLK_CAPSLOCK: case SDLK_LCTRL: case SDLK_RCTRL: case SDLK_LSHIFT: case SDLK_RSHIFT: case SDLK_LALT: case SDLK_RALT: case SDLK_LMETA: case SDLK_RMETA: case SDLK_MODE: break; default: keys[i] = SDL_RELEASED; break; } } } /* 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); } /* Clear these flags and set them only if they are in the new set. */ current->flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); 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 = SDL_stack_alloc(XColor, ncolors); 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); SDL_stack_free(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 = SDL_stack_alloc(unsigned long, nc); /* 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); SDL_stack_free(freelist); want = SDL_stack_alloc(SDL_Color, ncolors); reject = SDL_stack_alloc(SDL_Color, ncolors); SDL_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) */ SDL_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); SDL_stack_free(reject); SDL_stack_free(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); /* Close the connection with the IM server */ #ifdef X_HAVE_UTF8_STRING if (SDL_IC != NULL) { XUnsetICFocus(SDL_IC); XDestroyIC(SDL_IC); SDL_IC = NULL; } if (SDL_IM != NULL) { XCloseIM(SDL_IM); SDL_IM = NULL; } #endif /* 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]; } } SDL_free(SDL_iconcolors); SDL_iconcolors = NULL; } /* Restore gamma settings if they've changed */ if ( SDL_GetAppState() & SDL_APPACTIVE ) { X11_SwapVidModeGamma(this); } /* Restore DPMS and screensaver settings */ X11_RestoreScreenSaver(this, SDL_Display, screensaver_timeout, dpms_enabled); /* 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; }#if SDL_VIDEO_DRIVER_X11_XME XiGMiscDestroy();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -