src/video/x11/SDL_x11video.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. ALLOCA
  2. FREEA
  3. ALLOCA
  4. FREEA
  5. X11_Available
  6. X11_DeleteDevice
  7. X11_CreateDevice
  8. x_errhandler
  9. xio_errhandler
  10. create_aux_windows
  11. X11_VideoInit
  12. X11_DestroyWindow
  13. X11_SetSizeHints
  14. X11_CreateWindow
  15. X11_ResizeWindow
  16. X11_SetVideoMode
  17. X11_ToggleFullScreen
  18. X11_UpdateMouse
  19. COLOUR_DIST
  20. allocate_nearest
  21. X11_SetColors
  22. X11_SetGammaRamp
  23. X11_VideoQuit

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_x11video.c,v 1.6.2.82 2001/02/18 09:41:48 hercules Exp $";
  26 #endif
  27 
  28 /* X11 based SDL video driver implementation.
  29    Note:  This implementation does not currently need X11 thread locking,
  30           since the event thread uses a separate X connection and any
  31           additional locking necessary is handled internally.  However,
  32           if full locking is neccessary, take a look at XInitThreads().
  33 */
  34 
  35 #include <stdlib.h>
  36 #include <stdio.h>
  37 #include <unistd.h>
  38 #include <string.h>
  39 #include <sys/ioctl.h>
  40 #ifdef MTRR_SUPPORT
  41 #include <asm/mtrr.h>
  42 #include <sys/fcntl.h>
  43 #endif
  44 
  45 #ifdef HAVE_ALLOCA_H
  46 #include <alloca.h>
  47 #endif
  48 
  49 #ifdef HAVE_ALLOCA
  50 #define ALLOCA(n) ((void*)alloca(n))
     /* [<][>][^][v][top][bottom][index][help] */
  51 #define FREEA(p)
     /* [<][>][^][v][top][bottom][index][help] */
  52 #else
  53 #define ALLOCA(n) malloc(n)
     /* [<][>][^][v][top][bottom][index][help] */
  54 #define FREEA(p) free(p)
     /* [<][>][^][v][top][bottom][index][help] */
  55 #endif
  56 
  57 #include "SDL.h"
  58 #include "SDL_error.h"
  59 #include "SDL_timer.h"
  60 #include "SDL_thread.h"
  61 #include "SDL_video.h"
  62 #include "SDL_mouse.h"
  63 #include "SDL_endian.h"
  64 #include "SDL_sysvideo.h"
  65 #include "SDL_pixels_c.h"
  66 #include "SDL_events_c.h"
  67 #include "SDL_x11video.h"
  68 #include "SDL_x11wm_c.h"
  69 #include "SDL_x11mouse_c.h"
  70 #include "SDL_x11events_c.h"
  71 #include "SDL_x11modes_c.h"
  72 #include "SDL_x11image_c.h"
  73 #include "SDL_x11yuv_c.h"
  74 #include "SDL_x11gl_c.h"
  75 #include "SDL_x11gamma_c.h"
  76 #include "blank_cursor.h"
  77 
  78 /* Initialization/Query functions */
  79 static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat);
  80 static SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
  81 static int X11_ToggleFullScreen(_THIS, int on);
  82 static void X11_UpdateMouse(_THIS);
  83 static int X11_SetColors(_THIS, int firstcolor, int ncolors,
  84                          SDL_Color *colors);
  85 static int X11_SetGammaRamp(_THIS, Uint16 *ramp);
  86 static void X11_VideoQuit(_THIS);
  87 
  88 /* X11 driver bootstrap functions */
  89 
  90 static int X11_Available(void)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92         Display *display;
  93 
  94         display = XOpenDisplay(NULL);
  95         if ( display != NULL ) {
  96                 XCloseDisplay(display);
  97         }
  98         return(display != NULL);
  99 }
 100 
 101 static void X11_DeleteDevice(SDL_VideoDevice *device)
     /* [<][>][^][v][top][bottom][index][help] */
 102 {
 103         if ( device ) {
 104                 if ( device->hidden ) {
 105                         free(device->hidden);
 106                 }
 107                 if ( device->gl_data ) {
 108                         free(device->gl_data);
 109                 }
 110                 free(device);
 111         }
 112 }
 113 
 114 static SDL_VideoDevice *X11_CreateDevice(int devindex)
     /* [<][>][^][v][top][bottom][index][help] */
 115 {
 116         SDL_VideoDevice *device;
 117 
 118         /* Initialize all variables that we clean on shutdown */
 119         device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
 120         if ( device ) {
 121                 memset(device, 0, (sizeof *device));
 122                 device->hidden = (struct SDL_PrivateVideoData *)
 123                                 malloc((sizeof *device->hidden));
 124                 device->gl_data = (struct SDL_PrivateGLData *)
 125                                 malloc((sizeof *device->gl_data));
 126         }
 127         if ( (device == NULL) || (device->hidden == NULL) ||
 128                                  (device->gl_data == NULL) ) {
 129                 SDL_OutOfMemory();
 130                 X11_DeleteDevice(device);
 131                 return(0);
 132         }
 133         memset(device->hidden, 0, (sizeof *device->hidden));
 134         memset(device->gl_data, 0, (sizeof *device->gl_data));
 135 
 136         /* Set the driver flags */
 137         device->handles_any_size = 1;
 138 
 139         /* Set the function pointers */
 140         device->VideoInit = X11_VideoInit;
 141         device->ListModes = X11_ListModes;
 142         device->SetVideoMode = X11_SetVideoMode;
 143         device->ToggleFullScreen = X11_ToggleFullScreen;
 144         device->UpdateMouse = X11_UpdateMouse;
 145 #ifdef XFREE86_XV
 146         device->CreateYUVOverlay = X11_CreateYUVOverlay;
 147 #endif
 148         device->SetColors = X11_SetColors;
 149         device->UpdateRects = NULL;
 150         device->VideoQuit = X11_VideoQuit;
 151         device->AllocHWSurface = X11_AllocHWSurface;
 152         device->CheckHWBlit = NULL;
 153         device->FillHWRect = NULL;
 154         device->SetHWColorKey = NULL;
 155         device->SetHWAlpha = NULL;
 156         device->LockHWSurface = X11_LockHWSurface;
 157         device->UnlockHWSurface = X11_UnlockHWSurface;
 158         device->FlipHWSurface = X11_FlipHWSurface;
 159         device->FreeHWSurface = X11_FreeHWSurface;
 160         device->SetGamma = X11_SetVidModeGamma;
 161         device->GetGamma = X11_GetVidModeGamma;
 162         device->SetGammaRamp = X11_SetGammaRamp;
 163         device->GetGammaRamp = NULL;
 164 #ifdef HAVE_OPENGL
 165         device->GL_LoadLibrary = X11_GL_LoadLibrary;
 166         device->GL_GetProcAddress = X11_GL_GetProcAddress;
 167         device->GL_GetAttribute = X11_GL_GetAttribute;
 168         device->GL_MakeCurrent = X11_GL_MakeCurrent;
 169         device->GL_SwapBuffers = X11_GL_SwapBuffers;
 170 #endif
 171         device->SetCaption = X11_SetCaption;
 172         device->SetIcon = X11_SetIcon;
 173         device->IconifyWindow = X11_IconifyWindow;
 174         device->GrabInput = X11_GrabInput;
 175         device->GetWMInfo = X11_GetWMInfo;
 176         device->FreeWMCursor = X11_FreeWMCursor;
 177         device->CreateWMCursor = X11_CreateWMCursor;
 178         device->ShowWMCursor = X11_ShowWMCursor;
 179         device->WarpWMCursor = X11_WarpWMCursor;
 180         device->CheckMouseMode = X11_CheckMouseMode;
 181         device->InitOSKeymap = X11_InitOSKeymap;
 182         device->PumpEvents = X11_PumpEvents;
 183 
 184         device->free = X11_DeleteDevice;
 185 
 186         return device;
 187 }
 188 
 189 VideoBootStrap X11_bootstrap = {
 190         "x11", "X Window System",
 191         X11_Available, X11_CreateDevice
 192 };
 193 
 194 /* Shared memory information */
 195 extern int XShmQueryExtension(Display *dpy);    /* Not in X11 headers */
 196 
 197 /* Normal X11 error handler routine */
 198 static int (*X_handler)(Display *, XErrorEvent *) = NULL;
 199 static int x_errhandler(Display *d, XErrorEvent *e)
     /* [<][>][^][v][top][bottom][index][help] */
 200 {
 201 #ifdef XFREE86_VM
 202         extern int vm_error;
 203 #endif
 204 #ifdef XFREE86_DGAMOUSE
 205         extern int dga_error;
 206 #endif
 207 
 208 #ifdef XFREE86_VM
 209         /* VidMode errors are non-fatal. :) */
 210         /* Are the errors offset by one from the error base?
 211            e.g. the error base is 143, the code is 148, and the
 212                 actual error is XF86VidModeExtensionDisabled (4) ?
 213          */
 214         if ( (vm_error >= 0) &&
 215              (((e->error_code == BadRequest)&&(e->request_code == vm_error)) ||
 216               ((e->error_code > vm_error) &&
 217                (e->error_code <= (vm_error+XF86VidModeNumberErrors)))) ) {
 218 #ifdef XFREE86_DEBUG
 219 { char errmsg[1024];
 220   XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg));
 221 printf("VidMode error: %s\n", errmsg);
 222 }
 223 #endif
 224                 return(0);
 225         }
 226 #endif /* XFREE86_VM */
 227 
 228 #ifdef XFREE86_DGAMOUSE
 229         /* DGA errors can be non-fatal. :) */
 230         if ( (dga_error >= 0) &&
 231              ((e->error_code > dga_error) &&
 232               (e->error_code <= (dga_error+XF86DGANumberErrors))) ) {
 233 #ifdef XFREE86_DEBUG
 234 { char errmsg[1024];
 235   XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg));
 236 printf("DGA error: %s\n", errmsg);
 237 }
 238 #endif
 239                 return(0);
 240         }
 241 #endif /* XFREE86_DGAMOUSE */
 242 
 243         return(X_handler(d,e));
 244 }
 245 
 246 /* X11 I/O error handler routine */
 247 static int (*XIO_handler)(Display *) = NULL;
 248 static int xio_errhandler(Display *d)
     /* [<][>][^][v][top][bottom][index][help] */
 249 {
 250         /* Ack!  Lost X11 connection! */
 251 
 252         /* We will crash if we try to clean up our display */
 253         if ( current_video->hidden->Ximage ) {
 254                 SDL_VideoSurface->pixels = NULL;
 255         }
 256         current_video->hidden->X11_Display = NULL;
 257 
 258         /* Continue with the standard X11 error handler */
 259         return(XIO_handler(d));
 260 }
 261 
 262 /* Create auxiliary (toplevel) windows with the current visual */
 263 static void create_aux_windows(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 264 {
 265     XSetWindowAttributes xattr;
 266     XWMHints *hints;
 267     XTextProperty titleprop, iconprop;
 268     int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen));
 269 
 270     /* Don't create any extra windows if we are being managed */
 271     if ( SDL_windowid ) {
 272         FSwindow = 0;
 273         WMwindow = strtol(SDL_windowid, NULL, 0);
 274         return;
 275     }
 276 
 277     if(FSwindow)
 278         XDestroyWindow(SDL_Display, FSwindow);
 279 
 280     xattr.override_redirect = True;
 281     xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0;
 282     xattr.border_pixel = 0;
 283     xattr.colormap = SDL_XColorMap;
 284 
 285     FSwindow = XCreateWindow(SDL_Display, SDL_Root, 0, 0, 32, 32, 0,
 286                              this->hidden->depth, InputOutput, SDL_Visual,
 287                              CWOverrideRedirect | CWBackPixel | CWBorderPixel
 288                              | CWColormap,
 289                              &xattr);
 290 
 291     XSelectInput(SDL_Display, FSwindow, StructureNotifyMask);
 292 
 293     /* Tell KDE to keep the fullscreen window on top */
 294     {
 295         XEvent ev;
 296         long mask;
 297 
 298         memset(&ev, 0, sizeof(ev));
 299         ev.xclient.type = ClientMessage;
 300         ev.xclient.window = SDL_Root;
 301         ev.xclient.message_type = XInternAtom(SDL_Display,
 302                                               "KWM_KEEP_ON_TOP", False);
 303         ev.xclient.format = 32;
 304         ev.xclient.data.l[0] = FSwindow;
 305         ev.xclient.data.l[1] = CurrentTime;
 306         mask = SubstructureRedirectMask;
 307         XSendEvent(SDL_Display, SDL_Root, False, mask, &ev);
 308     }
 309 
 310     hints = NULL;
 311     titleprop.value = iconprop.value = NULL;
 312     if(WMwindow) {
 313         /* All window attributes must survive the recreation */
 314         hints = XGetWMHints(SDL_Display, WMwindow);
 315         XGetWMName(SDL_Display, WMwindow, &titleprop);
 316         XGetWMIconName(SDL_Display, WMwindow, &iconprop);
 317         XDestroyWindow(SDL_Display, WMwindow);
 318     }
 319 
 320     /* Create the window for windowed management */
 321     /* (reusing the xattr structure above) */
 322     WMwindow = XCreateWindow(SDL_Display, SDL_Root, 0, 0, 32, 32, 0,
 323                              this->hidden->depth, InputOutput, SDL_Visual,
 324                              CWBackPixel | CWBorderPixel | CWColormap,
 325                              &xattr);
 326 
 327     /* Set the input hints so we get keyboard input */
 328     if(!hints) {
 329         hints = XAllocWMHints();
 330         hints->input = True;
 331         hints->flags = InputHint;
 332     }
 333     XSetWMHints(SDL_Display, WMwindow, hints);
 334     XFree(hints);
 335     if(titleprop.value) {
 336         XSetWMName(SDL_Display, WMwindow, &titleprop);
 337         XFree(titleprop.value);
 338     }
 339     if(iconprop.value) {
 340         XSetWMIconName(SDL_Display, WMwindow, &iconprop);
 341         XFree(iconprop.value);
 342     }
 343 
 344     XSelectInput(SDL_Display, WMwindow,
 345                  FocusChangeMask | KeyPressMask | KeyReleaseMask
 346                  | PropertyChangeMask | StructureNotifyMask | KeymapStateMask);
 347 
 348     /* Set the class hints so we can get an icon (AfterStep) */
 349     {
 350         XClassHint *classhints;
 351         classhints = XAllocClassHint();
 352         if(classhints != NULL) {
 353             classhints->res_name = "SDL_App";
 354             classhints->res_class = "SDL_App";
 355             XSetClassHint(SDL_Display, WMwindow, classhints);
 356             XFree(classhints);
 357         }
 358     }
 359 
 360     /* Allow the window to be deleted by the window manager */
 361     WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False);
 362     XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1);
 363 }
 364 
 365 static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat)
     /* [<][>][^][v][top][bottom][index][help] */
 366 {
 367         char *display;
 368         int i;
 369 
 370         /* Open the X11 display */
 371         display = NULL;         /* Get it from DISPLAY environment variable */
 372 
 373         if ( (strncmp(XDisplayName(display), ":", 1) == 0) ||
 374              (strncmp(XDisplayName(display), "unix:", 5) == 0) ) {
 375                 local_X11 = 1;
 376         } else {
 377                 local_X11 = 0;
 378         }
 379         SDL_Display = XOpenDisplay(display);
 380         if ( SDL_Display == NULL ) {
 381                 SDL_SetError("Couldn't open X11 display");
 382                 return(-1);
 383         }
 384 #ifdef X11_DEBUG
 385         XSynchronize(SDL_Display, True);
 386 #endif
 387 
 388         /* Create an alternate X display for graphics updates -- allows us
 389            to do graphics updates in a separate thread from event handling.
 390            Thread-safe X11 doesn't seem to exist.
 391          */
 392         GFX_Display = XOpenDisplay(display);
 393         if ( GFX_Display == NULL ) {
 394                 SDL_SetError("Couldn't open X11 display");
 395                 return(-1);
 396         }
 397 
 398         /* Set the normal X error handler */
 399         X_handler = XSetErrorHandler(x_errhandler);
 400 
 401         /* Set the error handler if we lose the X display */
 402         XIO_handler = XSetIOErrorHandler(xio_errhandler);
 403 
 404         /* use default screen (from $DISPLAY) */
 405         SDL_Screen = DefaultScreen(SDL_Display);
 406 
 407 #ifndef NO_SHARED_MEMORY
 408         /* Check for MIT shared memory extension */
 409         use_mitshm = 0;
 410         if ( local_X11 ) {
 411                 use_mitshm = XShmQueryExtension(SDL_Display);
 412         }
 413 #endif /* NO_SHARED_MEMORY */
 414 
 415         /* See whether or not we need to swap pixels */
 416         swap_pixels = 0;
 417         if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
 418                 if ( XImageByteOrder(SDL_Display) == MSBFirst ) {
 419                         swap_pixels = 1;
 420                 }
 421         } else {
 422                 if ( XImageByteOrder(SDL_Display) == LSBFirst ) {
 423                         swap_pixels = 1;
 424                 }
 425         }
 426 
 427         /* Get the available video modes */
 428         if(X11_GetVideoModes(this) < 0)
 429             return -1;
 430 
 431         /* Determine the default screen depth:
 432            Use the default visual (or at least one with the same depth) */
 433         SDL_DisplayColormap = DefaultColormap(SDL_Display, SDL_Screen);
 434         for(i = 0; i < this->hidden->nvisuals; i++)
 435             if(this->hidden->visuals[i].depth == DefaultDepth(SDL_Display,
 436                                                               SDL_Screen))
 437                 break;
 438         if(i == this->hidden->nvisuals) {
 439             /* default visual was useless, take the deepest one instead */
 440             i = 0;
 441         }
 442         SDL_Visual = this->hidden->visuals[i].visual;
 443         if ( SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen) ) {
 444             SDL_XColorMap = SDL_DisplayColormap;
 445         } else {
 446             SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
 447                                             SDL_Visual, AllocNone);
 448         }
 449         this->hidden->depth = this->hidden->visuals[i].depth;
 450         vformat->BitsPerPixel = this->hidden->visuals[i].bpp;
 451         if ( vformat->BitsPerPixel > 8 ) {
 452                 vformat->Rmask = SDL_Visual->red_mask;
 453                 vformat->Gmask = SDL_Visual->green_mask;
 454                 vformat->Bmask = SDL_Visual->blue_mask;
 455         }
 456         X11_SaveVidModeGamma(this);
 457 
 458         /* See if we have been passed a window to use */
 459         SDL_windowid = getenv("SDL_WINDOWID");
 460 
 461         /* Create the fullscreen and managed windows */
 462         create_aux_windows(this);
 463 
 464         /* Create the blank cursor */
 465         SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask,
 466                                         BLANK_CWIDTH, BLANK_CHEIGHT,
 467                                                 BLANK_CHOTX, BLANK_CHOTY);
 468 
 469         /* Fill in some window manager capabilities */
 470         this->info.wm_available = 1;
 471 
 472         /* We're done! */
 473         XFlush(SDL_Display);
 474         return(0);
 475 }
 476 
 477 static void X11_DestroyWindow(_THIS, SDL_Surface *screen)
     /* [<][>][^][v][top][bottom][index][help] */
 478 {
 479         /* Clean up OpenGL */
 480         if ( screen ) {
 481                 screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT);
 482         }
 483         X11_GL_Shutdown(this);
 484 
 485         if ( ! SDL_windowid ) {
 486                 /* Hide the managed window */
 487                 if ( WMwindow ) {
 488                         XUnmapWindow(SDL_Display, WMwindow);
 489                 }
 490                 if ( screen && (screen->flags & SDL_FULLSCREEN) ) {
 491                         screen->flags &= ~SDL_FULLSCREEN;
 492                         X11_LeaveFullScreen(this);
 493                 }
 494 
 495                 /* Destroy the output window */
 496                 if ( SDL_Window ) {
 497                         XDestroyWindow(SDL_Display, SDL_Window);
 498                 }
 499 
 500                 /* Free the colormap entries */
 501                 if ( SDL_XPixels ) {
 502                         int numcolors;
 503                         unsigned long pixel;
 504 
 505                         numcolors = SDL_Visual->map_entries;
 506                         for ( pixel=0; pixel<numcolors; ++pixel ) {
 507                                 while ( SDL_XPixels[pixel] > 0 ) {
 508                                         XFreeColors(GFX_Display,
 509                                                 SDL_DisplayColormap,&pixel,1,0);
 510                                         --SDL_XPixels[pixel];
 511                                 }
 512                         }
 513                         free(SDL_XPixels);
 514                         SDL_XPixels = NULL;
 515                 } 
 516 
 517                 /* Free the graphics context */
 518                 if ( SDL_GC ) {
 519                         XFreeGC(SDL_Display, SDL_GC);
 520                         SDL_GC = 0;
 521                 }
 522         }
 523 }
 524 
 525 static void X11_SetSizeHints(_THIS, int w, int h, Uint32 flags)
     /* [<][>][^][v][top][bottom][index][help] */
 526 {
 527         XSizeHints *hints;
 528 
 529         hints = XAllocSizeHints();
 530         if ( hints ) {
 531                 if ( flags & SDL_RESIZABLE ) {
 532                         hints->min_width = 32;
 533                         hints->min_height = 32;
 534                         hints->max_height = 4096;
 535                         hints->max_width = 4096;
 536                 } else {
 537                         hints->min_width = hints->max_width = w;
 538                         hints->min_height = hints->max_height = h;
 539                 }
 540                 hints->flags = PMaxSize | PMinSize;
 541                 if ( flags & SDL_FULLSCREEN ) {
 542                         hints->x = 0;
 543                         hints->y = 0;
 544                         hints->flags |= USPosition;
 545                 } else
 546                 /* Center it, if desired */
 547                 if ( getenv("SDL_VIDEO_CENTERED") ) {
 548                         int display_w, display_h;
 549 
 550                         display_w = DisplayWidth(SDL_Display, SDL_Screen);
 551                         display_h = DisplayHeight(SDL_Display, SDL_Screen);
 552                         hints->x = (display_w - w)/2;
 553                         hints->y = (display_h - h)/2;
 554                         hints->flags |= USPosition;
 555                         XMoveWindow(SDL_Display, WMwindow, hints->x, hints->y);
 556 
 557                         /* Flush the resize event so we don't catch it later */
 558                         XSync(SDL_Display, True);
 559                 }
 560                 XSetWMNormalHints(SDL_Display, WMwindow, hints);
 561                 XFree(hints);
 562         }
 563 
 564         /* Respect the window caption style */
 565         if ( flags & SDL_NOFRAME ) {
 566                 SDL_bool set;
 567                 Atom WM_HINTS;
 568 
 569                 /* We haven't modified the window manager hints yet */
 570                 set = SDL_FALSE;
 571 
 572                 /* First try to set MWM hints */
 573                 WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True);
 574                 if ( WM_HINTS != None ) {
 575                         /* Hints used by Motif compliant window managers */
 576                         struct {
 577                                 unsigned long flags;
 578                                 unsigned long functions;
 579                                 unsigned long decorations;
 580                                 long input_mode;
 581                                 unsigned long status;
 582                         } MWMHints = { (1L << 1), 0, 0, 0, 0 };
 583 
 584                         XChangeProperty(SDL_Display, WMwindow,
 585                                         WM_HINTS, WM_HINTS, 32,
 586                                         PropModeReplace,
 587                                         (unsigned char *)&MWMHints,
 588                                         sizeof(MWMHints)/sizeof(long));
 589                         set = SDL_TRUE;
 590                 }
 591                 /* Now try to set KWM hints */
 592                 WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True);
 593                 if ( WM_HINTS != None ) {
 594                         long KWMHints = 0;
 595 
 596                         XChangeProperty(SDL_Display, WMwindow,
 597                                         WM_HINTS, WM_HINTS, 32,
 598                                         PropModeReplace,
 599                                         (unsigned char *)&KWMHints,
 600                                         sizeof(KWMHints)/sizeof(long));
 601                         set = SDL_TRUE;
 602                 }
 603                 /* Now try to set GNOME hints */
 604                 WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True);
 605                 if ( WM_HINTS != None ) {
 606                         long GNOMEHints = 0;
 607 
 608                         XChangeProperty(SDL_Display, WMwindow,
 609                                         WM_HINTS, WM_HINTS, 32,
 610                                         PropModeReplace,
 611                                         (unsigned char *)&GNOMEHints,
 612                                         sizeof(GNOMEHints)/sizeof(long));
 613                         set = SDL_TRUE;
 614                 }
 615                 /* Finally set the transient hints if necessary */
 616                 if ( ! set ) {
 617                         XSetTransientForHint(SDL_Display, WMwindow, SDL_Root);
 618                 }
 619         } else {
 620                 SDL_bool set;
 621                 Atom WM_HINTS;
 622 
 623                 /* We haven't modified the window manager hints yet */
 624                 set = SDL_FALSE;
 625 
 626                 /* First try to unset MWM hints */
 627                 WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True);
 628                 if ( WM_HINTS != None ) {
 629                         XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
 630                         set = SDL_TRUE;
 631                 }
 632                 /* Now try to unset KWM hints */
 633                 WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True);
 634                 if ( WM_HINTS != None ) {
 635                         XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
 636                         set = SDL_TRUE;
 637                 }
 638                 /* Now try to unset GNOME hints */
 639                 WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True);
 640                 if ( WM_HINTS != None ) {
 641                         XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
 642                         set = SDL_TRUE;
 643                 }
 644                 /* Finally unset the transient hints if necessary */
 645                 if ( ! set ) {
 646                         /* NOTE: Does this work? */
 647                         XSetTransientForHint(SDL_Display, WMwindow, None);
 648                 }
 649         }
 650 }
 651 
 652 static int X11_CreateWindow(_THIS, SDL_Surface *screen,
     /* [<][>][^][v][top][bottom][index][help] */
 653                             int w, int h, int bpp, Uint32 flags)
 654 {
 655         int i, depth;
 656         Visual *vis;
 657         int vis_change;
 658 
 659         /* If a window is already present, destroy it and start fresh */
 660         if ( SDL_Window ) {
 661                 X11_DestroyWindow(this, screen);
 662         }
 663 
 664         /* See if we have been given a window id */
 665         if ( SDL_windowid ) {
 666                 SDL_Window = strtol(SDL_windowid, NULL, 0);
 667         } else {
 668                 SDL_Window = 0;
 669         }
 670 
 671         /* find out which visual we are going to use */
 672         if ( flags & SDL_OPENGL ) {
 673                 XVisualInfo *vi;
 674 
 675                 vi = X11_GL_GetVisual(this);
 676                 if( !vi ) {
 677                         return -1;
 678                 }
 679                 vis = vi->visual;
 680                 depth = vi->depth;
 681         } else if ( SDL_windowid ) {
 682                 XWindowAttributes a;
 683 
 684                 XGetWindowAttributes(SDL_Display, SDL_Window, &a);
 685                 vis = a.visual;
 686                 depth = a.depth;
 687         } else {
 688                 for ( i = 0; i < this->hidden->nvisuals; i++ ) {
 689                         if ( this->hidden->visuals[i].bpp == bpp )
 690                                 break;
 691                 }
 692                 if ( i == this->hidden->nvisuals ) {
 693                         SDL_SetError("No matching visual for requested depth");
 694                         return -1;      /* should never happen */
 695                 }
 696                 vis = this->hidden->visuals[i].visual;
 697                 depth = this->hidden->visuals[i].depth;
 698         }
 699 #ifdef X11_DEBUG
 700         printf("Choosing %s visual at %d bpp - %d colormap entries\n", vis->class == PseudoColor ? "PseudoColor" : (vis->class == TrueColor ? "TrueColor" : (vis->class == DirectColor ? "DirectColor" : "Unknown")), depth, vis->map_entries);
 701 #endif
 702         vis_change = (vis != SDL_Visual);
 703         SDL_Visual = vis;
 704         this->hidden->depth = depth;
 705 
 706         /* Allocate the new pixel format for this video mode */
 707         if ( ! SDL_ReallocFormat(screen, bpp,
 708                         vis->red_mask, vis->green_mask, vis->blue_mask, 0) )
 709                 return -1;
 710 
 711         /* Create the appropriate colormap */
 712         if ( SDL_XColorMap != SDL_DisplayColormap ) {
 713                 XFreeColormap(SDL_Display, SDL_XColorMap);
 714         }
 715         if ( SDL_Visual->class == PseudoColor ) {
 716             int ncolors;
 717 
 718             /* Allocate the pixel flags */
 719             ncolors = SDL_Visual->map_entries;
 720             SDL_XPixels = malloc(ncolors * sizeof(int));
 721             if(SDL_XPixels == NULL) {
 722                 SDL_OutOfMemory();
 723                 return -1;
 724             }
 725             memset(SDL_XPixels, 0, ncolors * sizeof(*SDL_XPixels));
 726 
 727             /* always allocate a private colormap on non-default visuals */
 728             if ( SDL_Visual != DefaultVisual(SDL_Display, SDL_Screen) ) {
 729                 flags |= SDL_HWPALETTE;
 730             }
 731             if ( flags & SDL_HWPALETTE ) {
 732                 screen->flags |= SDL_HWPALETTE;
 733                 SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
 734                                                 SDL_Visual, AllocAll);
 735             } else {
 736                 SDL_XColorMap = SDL_DisplayColormap;
 737             }
 738         } else if ( SDL_Visual->class == DirectColor ) {
 739 
 740             /* Create a colormap which we can manipulate for gamma */
 741             SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
 742                                             SDL_Visual, AllocAll);
 743             XSync(SDL_Display, False);
 744 
 745             /* Initialize the colormap to the identity mapping */
 746             SDL_GetGammaRamp(0, 0, 0);
 747             this->screen = screen;
 748             X11_SetGammaRamp(this, this->gamma);
 749             this->screen = NULL;
 750         } else {
 751             /* Create a read-only colormap for our window */
 752             SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
 753                                             SDL_Visual, AllocNone);
 754         }
 755 
 756         /* Recreate the auxiliary windows, if needed (required for GL) */
 757         if ( vis_change )
 758             create_aux_windows(this);
 759 
 760         if(screen->flags & SDL_HWPALETTE) {
 761             /* Since the full-screen window might have got a nonzero background
 762                colour (0 is white on some displays), we should reset the
 763                background to 0 here since that is what the user expects
 764                with a private colormap */
 765             XSetWindowBackground(SDL_Display, FSwindow, 0);
 766             XClearWindow(SDL_Display, FSwindow);
 767         }
 768 
 769         /* resize the (possibly new) window manager window */
 770         if( !SDL_windowid ) {
 771                 X11_SetSizeHints(this, w, h, flags);
 772                 current_w = w;
 773                 current_h = h;
 774                 XResizeWindow(SDL_Display, WMwindow, w, h);
 775         }
 776 
 777         /* Create (or use) the X11 display window */
 778         if ( !SDL_windowid ) {
 779                 if ( flags & SDL_OPENGL ) {
 780                         if ( X11_GL_CreateWindow(this, w, h) < 0 ) {
 781                                 return(-1);
 782                         }
 783                 } else {
 784                         XSetWindowAttributes swa;
 785 
 786                         swa.background_pixel = 0;
 787                         swa.border_pixel = 0;
 788                         swa.colormap = SDL_XColorMap;
 789                         SDL_Window = XCreateWindow(SDL_Display, WMwindow,
 790                                                 0, 0, w, h, 0, depth,
 791                                                 InputOutput, SDL_Visual,
 792                                                 CWBackPixel | CWBorderPixel
 793                                                 | CWColormap, &swa);
 794                 }
 795                 /* Only manage our input if we own the window */
 796                 XSelectInput(SDL_Display, SDL_Window,
 797                                         ( EnterWindowMask | LeaveWindowMask
 798                                         | ButtonPressMask | ButtonReleaseMask
 799                                         | PointerMotionMask | ExposureMask ));
 800         }
 801 
 802         /* Create the graphics context here, once we have a window */
 803         if ( flags & SDL_OPENGL ) {
 804                 if ( X11_GL_CreateContext(this) < 0 ) {
 805                         return(-1);
 806                 } else {
 807                         screen->flags |= SDL_OPENGL;
 808                 }
 809         } else {
 810                 XGCValues gcv;
 811 
 812                 gcv.graphics_exposures = False;
 813                 SDL_GC = XCreateGC(SDL_Display, SDL_Window,
 814                                    GCGraphicsExposures, &gcv);
 815                 if ( ! SDL_GC ) {
 816                         SDL_SetError("Couldn't create graphics context");
 817                         return(-1);
 818                 }
 819         }
 820 
 821         /* Set our colormaps when not setting a GL mode */
 822         if ( ! (flags & SDL_OPENGL) ) {
 823                 XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap);
 824                 if( !SDL_windowid ) {
 825                     XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap);
 826                     XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap);
 827                 }
 828         }
 829 
 830 #if 0 /* This is an experiment - are the graphics faster now? - nope. */
 831         if ( getenv("SDL_VIDEO_X11_BACKINGSTORE") )
 832 #endif
 833         /* Cache the window in the server, when possible */
 834         {
 835                 Screen *xscreen;
 836                 XSetWindowAttributes a;
 837 
 838                 xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen);
 839                 a.backing_store = DoesBackingStore(xscreen);
 840                 if ( a.backing_store != NotUseful ) {
 841                         XChangeWindowAttributes(SDL_Display, SDL_Window,
 842                                                 CWBackingStore, &a);
 843                 }
 844         }
 845 
 846         /* Update the internal keyboard state */
 847         X11_SetKeyboardState(SDL_Display, NULL);
 848 
 849         /* Map them both and go fullscreen, if requested */
 850         if ( ! SDL_windowid ) {
 851                 XMapWindow(SDL_Display, SDL_Window);
 852                 XMapWindow(SDL_Display, WMwindow);
 853                 if ( flags & SDL_FULLSCREEN ) {
 854                         screen->flags |= SDL_FULLSCREEN;
 855                         X11_WaitMapped(this, WMwindow);
 856 #ifdef GRAB_FULLSCREEN
 857                         X11_EnterFullScreen(this);
 858 #else
 859                         X11_QueueEnterFullScreen(this);
 860 #endif
 861                 } else {
 862                         screen->flags &= ~SDL_FULLSCREEN;
 863                 }
 864         }
 865         return(0);
 866 }
 867 
 868 static int X11_ResizeWindow(_THIS,
     /* [<][>][^][v][top][bottom][index][help] */
 869                         SDL_Surface *screen, int w, int h, Uint32 flags)
 870 {
 871         if ( ! SDL_windowid ) {
 872                 /* Resize the window manager window */
 873                 X11_SetSizeHints(this, w, h, flags);
 874                 current_w = w;
 875                 current_h = h;
 876                 XResizeWindow(SDL_Display, WMwindow, w, h);
 877 
 878                 /* Resize the fullscreen and display windows */
 879                 if ( flags & SDL_FULLSCREEN ) {
 880                         if ( screen->flags & SDL_FULLSCREEN ) {
 881                                 X11_ResizeFullScreen(this);
 882                         } else {
 883                                 screen->flags |= SDL_FULLSCREEN;
 884 #ifdef GRAB_FULLSCREEN
 885                                 X11_EnterFullScreen(this);
 886 #else
 887                                 X11_QueueEnterFullScreen(this);
 888 #endif
 889                         }
 890                 } else {
 891                         if ( screen->flags & SDL_FULLSCREEN ) {
 892                                 screen->flags &= ~SDL_FULLSCREEN;
 893                                 X11_LeaveFullScreen(this);
 894                         }
 895                 }
 896                 XResizeWindow(SDL_Display, SDL_Window, w, h);
 897         }
 898         return(0);
 899 }
 900 
 901 SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current,
     /* [<][>][^][v][top][bottom][index][help] */
 902                                 int width, int height, int bpp, Uint32 flags)
 903 {
 904         Uint32 saved_flags;
 905 
 906         /* Lock the event thread, in multi-threading environments */
 907         SDL_Lock_EventThread();
 908 
 909         /* Check the combination of flags we were passed */
 910         if ( flags & SDL_FULLSCREEN ) {
 911                 /* Clear fullscreen flag if not supported */
 912                 if ( SDL_windowid ) {
 913                         flags &= ~SDL_FULLSCREEN;
 914                 }
 915         }
 916 
 917         /* Flush any delayed updates */
 918         XSync(GFX_Display, False);
 919 
 920         /* Set up the X11 window */
 921         saved_flags = current->flags;
 922         if (SDL_Window && (saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)
 923             && bpp == current->format->BitsPerPixel) {
 924                 if (X11_ResizeWindow(this, current, width, height, flags) < 0) {
 925                         current = NULL;
 926                         goto done;
 927                 }
 928         } else {
 929                 if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) {
 930                         current = NULL;
 931                         goto done;
 932                 }
 933         }
 934 
 935         /* Set up the new mode framebuffer */
 936         if ( ((current->w != width) || (current->h != height)) ||
 937              ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) {
 938                 current->w = width;
 939                 current->h = height;
 940                 current->pitch = SDL_CalculatePitch(current);
 941                 X11_ResizeImage(this, current, flags);
 942         }
 943         current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME));
 944 
 945   done:
 946         /* Release the event thread */
 947         XSync(SDL_Display, False);
 948         SDL_Unlock_EventThread();
 949 
 950         /* We're done! */
 951         return(current);
 952 }
 953 
 954 static int X11_ToggleFullScreen(_THIS, int on)
     /* [<][>][^][v][top][bottom][index][help] */
 955 {
 956         Uint32 event_thread;
 957 
 958         /* Don't switch if we don't own the window */
 959         if ( SDL_windowid ) {
 960                 return(0);
 961         }
 962 
 963         /* Don't lock if we are the event thread */
 964         event_thread = SDL_EventThreadID();
 965         if ( event_thread && (SDL_ThreadID() == event_thread) ) {
 966                 event_thread = 0;
 967         }
 968         if ( event_thread ) {
 969                 SDL_Lock_EventThread();
 970         }
 971         if ( on ) {
 972 #ifdef GRAB_FULLSCREEN
 973                 this->screen->flags |= SDL_FULLSCREEN;
 974                 X11_EnterFullScreen(this);
 975 #else
 976                 X11_QueueEnterFullScreen(this);
 977 #endif
 978         } else {
 979                 this->screen->flags &= ~SDL_FULLSCREEN;
 980                 X11_LeaveFullScreen(this);
 981         }
 982         X11_RefreshDisplay(this);
 983         if ( event_thread ) {
 984                 SDL_Unlock_EventThread();
 985         }
 986         SDL_ResetKeyboard();
 987         return(1);
 988 }
 989 
 990 /* Update the current mouse state and position */
 991 static void X11_UpdateMouse(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 992 {
 993         Window u1; int u2;
 994         Window current_win;
 995         int x, y;
 996         unsigned int mask;
 997 
 998         /* Lock the event thread, in multi-threading environments */
 999         SDL_Lock_EventThread();
1000         if ( XQueryPointer(SDL_Display, SDL_Window, &u1, &current_win,
1001                            &u2, &u2, &x, &y, &mask) ) {
1002                 if ( (x >= 0) && (x < SDL_VideoSurface->w) &&
1003                      (y >= 0) && (y < SDL_VideoSurface->h) ) {
1004                         SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
1005                         SDL_PrivateMouseMotion(0, 0, x, y);
1006                 } else {
1007                         SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
1008                 }
1009         }
1010         SDL_Unlock_EventThread();
1011 }
1012 
1013 /* simple colour distance metric. Supposed to be better than a plain
1014    Euclidian distance anyway. */
1015 #define COLOUR_FACTOR 3
1016 #define LIGHT_FACTOR 1
1017 #define COLOUR_DIST(r1, g1, b1, r2, g2, b2)                             \
     /* [<][>][^][v][top][bottom][index][help] */
1018         (COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2))   \
1019          + LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2)))
1020 
1021 static void allocate_nearest(_THIS, SDL_Color *colors,
     /* [<][>][^][v][top][bottom][index][help] */
1022                              SDL_Color *want, int nwant)
1023 {
1024         /*
1025          * There is no way to know which ones to choose from, so we retrieve
1026          * the entire colormap and try the nearest possible, until we find one
1027          * that is shared.
1028          */
1029         XColor all[256];
1030         int i;
1031         for(i = 0; i < 256; i++)
1032                 all[i].pixel = i;
1033         /* 
1034          * XQueryColors sets the flags in the XColor struct, so we use
1035          * that to keep track of which colours are available
1036          */
1037         XQueryColors(GFX_Display, SDL_XColorMap, all, 256);
1038 
1039         for(i = 0; i < nwant; i++) {
1040                 XColor *c;
1041                 int j;
1042                 int best = 0;
1043                 int mindist = 0x7fffffff;
1044                 int ri = want[i].r;
1045                 int gi = want[i].g;
1046                 int bi = want[i].b;
1047                 for(j = 0; j < 256; j++) {
1048                         int rj, gj, bj, d2;
1049                         if(!all[j].flags)
1050                                 continue;       /* unavailable colour cell */
1051                         rj = all[j].red >> 8;
1052                         gj = all[j].green >> 8;
1053                         bj = all[j].blue >> 8;
1054                         d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj);
1055                         if(d2 < mindist) {
1056                                 mindist = d2;
1057                                 best = j;
1058                         }
1059                 }
1060                 if(SDL_XPixels[best])
1061                         continue; /* already allocated, waste no more time */
1062                 c = all + best;
1063                 if(XAllocColor(GFX_Display, SDL_XColorMap, c)) {
1064                         /* got it */
1065                         colors[best].r = c->red >> 8;
1066                         colors[best].g = c->green >> 8;
1067                         colors[best].b = c->blue >> 8;
1068                         ++SDL_XPixels[best];
1069                 } else {
1070                         /* 
1071                          * The colour couldn't be allocated, probably being
1072                          * owned as a r/w cell by another client. Flag it as
1073                          * unavailable and try again. The termination of the
1074                          * loop is guaranteed since at least black and white
1075                          * are always there.
1076                          */
1077                         c->flags = 0;
1078                         i--;
1079                 }
1080         }
1081 }
1082 
1083 int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
     /* [<][>][^][v][top][bottom][index][help] */
1084 {
1085         int nrej = 0;
1086 
1087         /* Check to make sure we have a colormap allocated */
1088         if ( SDL_XPixels == NULL ) {
1089                 return(0);
1090         }
1091         if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
1092                 /* private writable colormap: just set the colours we need */
1093                 XColor  *xcmap;
1094                 int i;
1095                 xcmap = ALLOCA(ncolors*sizeof(*xcmap));
1096                 if(xcmap == NULL)
1097                         return 0;
1098                 for ( i=0; i<ncolors; ++i ) {
1099                         xcmap[i].pixel = i + firstcolor;
1100                         xcmap[i].red   = (colors[i].r<<8)|colors[i].r;
1101                         xcmap[i].green = (colors[i].g<<8)|colors[i].g;
1102                         xcmap[i].blue  = (colors[i].b<<8)|colors[i].b;
1103                         xcmap[i].flags = (DoRed|DoGreen|DoBlue);
1104                 }
1105                 XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
1106                 XSync(GFX_Display, False);
1107                 FREEA(xcmap);
1108         } else {
1109                 /*
1110                  * Shared colormap: We only allocate read-only cells, which
1111                  * increases the likelyhood of colour sharing with other
1112                  * clients. The pixel values will almost certainly be
1113                  * different from the requested ones, so the user has to
1114                  * walk the colormap and see which index got what colour.
1115                  *
1116                  * We can work directly with the logical palette since it
1117                  * has already been set when we get here.
1118                  */
1119                 SDL_Color *want, *reject;
1120                 unsigned long *freelist;
1121                 int i;
1122                 int nfree = 0;
1123                 int nc = this->screen->format->palette->ncolors;
1124                 colors = this->screen->format->palette->colors;
1125                 freelist = ALLOCA(nc * sizeof(*freelist));
1126                 /* make sure multiple allocations of the same cell are freed */
1127                 for(i = 0; i < ncolors; i++) {
1128                         int pixel = firstcolor + i;
1129                         while(SDL_XPixels[pixel]) {
1130                                 freelist[nfree++] = pixel;
1131                                 --SDL_XPixels[pixel];
1132                         }
1133                 }
1134                 XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0);
1135                 FREEA(freelist);
1136 
1137                 want = ALLOCA(ncolors * sizeof(SDL_Color));
1138                 reject = ALLOCA(ncolors * sizeof(SDL_Color));
1139                 memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color));
1140                 /* make sure the user isn't fooled by her own wishes
1141                    (black is safe, always available in the default colormap) */
1142                 memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color));
1143 
1144                 /* now try to allocate the colours */
1145                 for(i = 0; i < ncolors; i++) {
1146                         XColor col;
1147                         col.red = want[i].r << 8;
1148                         col.green = want[i].g << 8;
1149                         col.blue = want[i].b << 8;
1150                         col.flags = DoRed | DoGreen | DoBlue;
1151                         if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) {
1152                                 /* We got the colour, or at least the nearest
1153                                    the hardware could get. */
1154                                 colors[col.pixel].r = col.red >> 8;
1155                                 colors[col.pixel].g = col.green >> 8;
1156                                 colors[col.pixel].b = col.blue >> 8;
1157                                 ++SDL_XPixels[col.pixel];
1158                         } else {
1159                                 /*
1160                                  * no more free cells, add it to the list
1161                                  * of rejected colours
1162                                  */
1163                                 reject[nrej++] = want[i];
1164                         }
1165                 }
1166                 if(nrej)
1167                         allocate_nearest(this, colors, reject, nrej);
1168                 FREEA(reject);
1169                 FREEA(want);
1170         }
1171         return nrej == 0;
1172 }
1173 
1174 int X11_SetGammaRamp(_THIS, Uint16 *ramp)
     /* [<][>][^][v][top][bottom][index][help] */
1175 {
1176         int i, ncolors;
1177         XColor xcmap[256];
1178 
1179         /* See if actually setting the gamma is supported */
1180         if ( SDL_Visual->class != DirectColor ) {
1181             SDL_SetError("Gamma correction not supported on this visual");
1182             return(-1);
1183         }
1184 
1185         /* Calculate the appropriate palette for the given gamma ramp */
1186         ncolors = SDL_Visual->map_entries;
1187         for ( i=0; i<ncolors; ++i ) {
1188                 Uint8 c = (256 * i / ncolors);
1189                 xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c);
1190                 xcmap[i].red   = ramp[0*256+c];
1191                 xcmap[i].green = ramp[1*256+c];
1192                 xcmap[i].blue  = ramp[2*256+c];
1193                 xcmap[i].flags = (DoRed|DoGreen|DoBlue);
1194         }
1195         XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
1196         XSync(GFX_Display, False);
1197         return(0);
1198 }
1199 
1200 /* Note:  If we are terminated, this could be called in the middle of
1201    another SDL video routine -- notably UpdateRects.
1202 */
1203 void X11_VideoQuit(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
1204 {
1205         /* Shutdown everything that's still up */
1206         /* The event thread should be done, so we can touch SDL_Display */
1207         if ( SDL_Display != NULL ) {
1208                 /* Flush any delayed updates */
1209                 XSync(GFX_Display, False);
1210 
1211                 /* Start shutting down the windows */
1212                 X11_DestroyImage(this, this->screen);
1213                 X11_DestroyWindow(this, this->screen);
1214                 X11_FreeVideoModes(this);
1215                 if ( SDL_XColorMap != SDL_DisplayColormap ) {
1216                         XFreeColormap(SDL_Display, SDL_XColorMap);
1217                 }
1218                 if ( SDL_iconcolors ) {
1219                         unsigned long pixel;
1220                         int numcolors =
1221                                 ((this->screen->format)->palette)->ncolors;
1222                         for ( pixel=0; pixel<numcolors; ++pixel ) {
1223                                 while ( SDL_iconcolors[pixel] > 0 ) {
1224                                         XFreeColors(SDL_Display,
1225                                                 SDL_DisplayColormap,&pixel,1,0);
1226                                         --SDL_iconcolors[pixel];
1227                                 }
1228                         }
1229                         free(SDL_iconcolors);
1230                         SDL_iconcolors = NULL;
1231                 } 
1232                 /* Restore gamma settings if they've changed */
1233                 if ( SDL_GetAppState() & SDL_APPACTIVE ) {
1234                         X11_SwapVidModeGamma(this);
1235                 }
1236 
1237                 /* Free that blank cursor */
1238                 if ( SDL_BlankCursor != NULL ) {
1239                         this->FreeWMCursor(this, SDL_BlankCursor);
1240                         SDL_BlankCursor = NULL;
1241                 }
1242 
1243                 /* Close the X11 graphics connection */
1244                 if ( GFX_Display != NULL ) {
1245                         XCloseDisplay(GFX_Display);
1246                         GFX_Display = NULL;
1247                 }
1248 
1249                 /* Close the X11 display connection */
1250                 XCloseDisplay(SDL_Display);
1251                 SDL_Display = NULL;
1252 
1253                 /* Reset the X11 error handlers */
1254                 if ( XIO_handler ) {
1255                         XSetIOErrorHandler(XIO_handler);
1256                 }
1257                 if ( X_handler ) {
1258                         XSetErrorHandler(X_handler);
1259                 }
1260 
1261                 /* Unload GL library after X11 shuts down */
1262                 X11_GL_UnloadLibrary(this);
1263         }
1264         if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
1265                 /* Direct screen access, no memory buffer */
1266                 this->screen->pixels = NULL;
1267         }
1268 }
1269 

/* [<][>][^][v][top][bottom][index][help] */