19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL - Simple DirectMedia Layer
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Copyright (C) 1997-2012 Sam Lantinga
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is free software; you can redistribute it and/or
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    modify it under the terms of the GNU Lesser General Public
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License as published by the Free Software Foundation; either
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    version 2.1 of the License, or (at your option) any later version.
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is distributed in the hope that it will be useful,
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    but WITHOUT ANY WARRANTY; without even the implied warranty of
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Lesser General Public License for more details.
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    You should have received a copy of the GNU Lesser General Public
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License along with this library; if not, write to the Free Software
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Sam Lantinga
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    slouken@libsdl.org
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_config.h"
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* X11 based SDL video driver implementation.
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   Note:  This implementation does not currently need X11 thread locking,
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          since the event thread uses a separate X connection and any
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          additional locking necessary is handled internally.  However,
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if full locking is neccessary, take a look at XInitThreads().
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <unistd.h>
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/ioctl.h>
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef MTRR_SUPPORT
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <asm/mtrr.h>
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/fcntl.h>
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_endian.h"
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_timer.h"
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_thread.h"
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_video.h"
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_mouse.h"
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "../SDL_sysvideo.h"
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "../SDL_pixels_c.h"
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "../../events/SDL_events_c.h"
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11video.h"
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11wm_c.h"
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11mouse_c.h"
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11events_c.h"
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11modes_c.h"
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11image_c.h"
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11yuv_c.h"
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11gl_c.h"
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_x11gamma_c.h"
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "../blank_cursor.h"
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef X_HAVE_UTF8_STRING
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <locale.h>
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Initialization/Query functions */
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_VideoInit(_THIS, SDL_PixelFormat *vformat);
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_ToggleFullScreen(_THIS, int on);
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void X11_UpdateMouse(_THIS);
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_SetColors(_THIS, int firstcolor, int ncolors,
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 SDL_Color *colors);
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_SetGammaRamp(_THIS, Uint16 *ramp);
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void X11_VideoQuit(_THIS);
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
71e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hallint  X11_wmXAdjust;
72e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hallint  X11_wmYAdjust;
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* X11 driver bootstrap functions */
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_Available(void)
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Display *display = NULL;
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_X11_LoadSymbols() ) {
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		display = XOpenDisplay(NULL);
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( display != NULL ) {
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XCloseDisplay(display);
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_X11_UnloadSymbols();
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(display != NULL);
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void X11_DeleteDevice(SDL_VideoDevice *device)
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( device ) {
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( device->hidden ) {
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(device->hidden);
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( device->gl_data ) {
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(device->gl_data);
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_free(device);
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_X11_UnloadSymbols();
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_VideoDevice *X11_CreateDevice(int devindex)
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_VideoDevice *device = NULL;
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_X11_LoadSymbols() ) {
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Initialize all variables that we clean on shutdown */
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( device ) {
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_memset(device, 0, (sizeof *device));
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			device->hidden = (struct SDL_PrivateVideoData *)
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_malloc((sizeof *device->hidden));
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			device->gl_data = (struct SDL_PrivateGLData *)
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_malloc((sizeof *device->gl_data));
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( (device == NULL) || (device->hidden == NULL) ||
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                         (device->gl_data == NULL) ) {
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_OutOfMemory();
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			X11_DeleteDevice(device); /* calls SDL_X11_UnloadSymbols(). */
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return(0);
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_memset(device->hidden, 0, (sizeof *device->hidden));
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_OPENGL_GLX
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->gl_data->swap_interval = -1;
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Set the driver flags */
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->handles_any_size = 1;
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Set the function pointers */
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->VideoInit = X11_VideoInit;
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->ListModes = X11_ListModes;
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetVideoMode = X11_SetVideoMode;
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->ToggleFullScreen = X11_ToggleFullScreen;
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->UpdateMouse = X11_UpdateMouse;
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_XV
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->CreateYUVOverlay = X11_CreateYUVOverlay;
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetColors = X11_SetColors;
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->UpdateRects = NULL;
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->VideoQuit = X11_VideoQuit;
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->AllocHWSurface = X11_AllocHWSurface;
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->CheckHWBlit = NULL;
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->FillHWRect = NULL;
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetHWColorKey = NULL;
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetHWAlpha = NULL;
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->LockHWSurface = X11_LockHWSurface;
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->UnlockHWSurface = X11_UnlockHWSurface;
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->FlipHWSurface = X11_FlipHWSurface;
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->FreeHWSurface = X11_FreeHWSurface;
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetGamma = X11_SetVidModeGamma;
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GetGamma = X11_GetVidModeGamma;
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetGammaRamp = X11_SetGammaRamp;
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GetGammaRamp = NULL;
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_OPENGL_GLX
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GL_LoadLibrary = X11_GL_LoadLibrary;
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GL_GetProcAddress = X11_GL_GetProcAddress;
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GL_GetAttribute = X11_GL_GetAttribute;
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GL_MakeCurrent = X11_GL_MakeCurrent;
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GL_SwapBuffers = X11_GL_SwapBuffers;
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetCaption = X11_SetCaption;
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->SetIcon = X11_SetIcon;
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->IconifyWindow = X11_IconifyWindow;
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GrabInput = X11_GrabInput;
169e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall		device->GetWindowPos = X11_GetWindowPos;
170e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall		device->SetWindowPos = X11_SetWindowPos;
171e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall		device->IsWindowVisible = X11_IsWindowVisible;
172e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall		device->GetMonitorDPI = X11_GetMonitorDPI;
173e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall		device->GetMonitorRect = X11_GetMonitorRect;
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->GetWMInfo = X11_GetWMInfo;
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->FreeWMCursor = X11_FreeWMCursor;
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->CreateWMCursor = X11_CreateWMCursor;
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->ShowWMCursor = X11_ShowWMCursor;
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->WarpWMCursor = X11_WarpWMCursor;
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->CheckMouseMode = X11_CheckMouseMode;
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->InitOSKeymap = X11_InitOSKeymap;
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->PumpEvents = X11_PumpEvents;
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		device->free = X11_DeleteDevice;
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return device;
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallVideoBootStrap X11_bootstrap = {
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	"x11", "X Window System",
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	X11_Available, X11_CreateDevice
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Normal X11 error handler routine */
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int (*X_handler)(Display *, XErrorEvent *) = NULL;
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int x_errhandler(Display *d, XErrorEvent *e)
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_VIDMODE
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	extern int vm_error;
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_DGAMOUSE
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	extern int dga_error;
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_VIDMODE
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* VidMode errors are non-fatal. :) */
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Are the errors offset by one from the error base?
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   e.g. the error base is 143, the code is 148, and the
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        actual error is XF86VidModeExtensionDisabled (4) ?
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 */
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( (vm_error >= 0) &&
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	     (((e->error_code == BadRequest)&&(e->request_code == vm_error)) ||
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	      ((e->error_code > vm_error) &&
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	       (e->error_code <= (vm_error+XF86VidModeNumberErrors)))) ) {
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef X11_DEBUG
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ char errmsg[1024];
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg));
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallprintf("VidMode error: %s\n", errmsg);
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        	return(0);
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
2249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_DGAMOUSE
2269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* DGA errors can be non-fatal. :) */
2279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( (dga_error >= 0) &&
2289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	     ((e->error_code > dga_error) &&
2299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	      (e->error_code <= (dga_error+XF86DGANumberErrors))) ) {
2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef X11_DEBUG
2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ char errmsg[1024];
2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg));
2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallprintf("DGA error: %s\n", errmsg);
2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        	return(0);
2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */
2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(X_handler(d,e));
2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* X11 I/O error handler routine */
2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int (*XIO_handler)(Display *) = NULL;
2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int xio_errhandler(Display *d)
2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Ack!  Lost X11 connection! */
2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* We will crash if we try to clean up our display */
2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_VideoSurface && current_video->hidden->Ximage ) {
2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_VideoSurface->pixels = NULL;
2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	current_video->hidden->X11_Display = NULL;
2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Continue with the standard X11 error handler */
2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(XIO_handler(d));
2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int (*Xext_handler)(Display *, _Xconst char *, _Xconst char *) = NULL;
2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int xext_errhandler(Display *d, _Xconst char *ext, _Xconst char *reason)
2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef X11_DEBUG
2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	printf("Xext error inside SDL (may be harmless):\n");
2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	printf("  Extension \"%s\" %s on display \"%s\".\n",
2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	       ext, reason, XDisplayString(d));
2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (SDL_strcmp(reason, "missing") == 0) {
2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/*
2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * Since the query itself, elsewhere, can handle a missing extension
2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 *  and the default behaviour in Xlib is to write to stderr, which
2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 *  generates unnecessary bug reports, we just ignore these.
2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 */
2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return 0;
2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Everything else goes to the default handler... */
2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return Xext_handler(d, ext, reason);
2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Find out what class name we should use */
2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic char *get_classname(char *classname, int maxlen)
2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *spot;
2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__LINUX__) || defined(__FREEBSD__)
2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char procfile[1024];
2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char linkfile[1024];
2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int linksize;
2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* First allow environment variable override */
2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( spot ) {
2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_strlcpy(classname, spot, maxlen);
2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return classname;
2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Next look at the application's executable name */
2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__LINUX__) || defined(__FREEBSD__)
3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__LINUX__)
3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#elif defined(__FREEBSD__)
3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid());
3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#error Where can we find the executable name?
3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	linksize = readlink(procfile, linkfile, sizeof(linkfile)-1);
3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( linksize > 0 ) {
3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		linkfile[linksize] = '\0';
3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spot = SDL_strrchr(linkfile, '/');
3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( spot ) {
3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_strlcpy(classname, spot+1, maxlen);
3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_strlcpy(classname, linkfile, maxlen);
3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return classname;
3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* __LINUX__ */
3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Finally use the default we've used forever */
3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_strlcpy(classname, "SDL_App", maxlen);
3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return classname;
3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Create auxiliary (toplevel) windows with the current visual */
3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void create_aux_windows(_THIS)
3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int x = 0, y = 0;
3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char classname[1024];
3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XSetWindowAttributes xattr;
3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XWMHints *hints;
3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned long app_event_mask;
3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen));
3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Look up some useful Atoms */
3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False);
3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Don't create any extra windows if we are being managed */
3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( SDL_windowid ) {
3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	FSwindow = 0;
3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	WMwindow = SDL_strtol(SDL_windowid, NULL, 0);
3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return;
3439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(FSwindow)
3469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XDestroyWindow(SDL_Display, FSwindow);
3479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_XINERAMA
3499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( use_xinerama ) {
3509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        x = xinerama_info.x_org;
3519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        y = xinerama_info.y_org;
3529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    xattr.override_redirect = True;
3559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0;
3569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    xattr.border_pixel = 0;
3579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    xattr.colormap = SDL_XColorMap;
3589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    FSwindow = XCreateWindow(SDL_Display, SDL_Root,
360e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall                             x + X11_wmXAdjust,
361e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall                             y + X11_wmYAdjust,
362e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall                             32, 32, 0,
3639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     this->hidden->depth, InputOutput, SDL_Visual,
3649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     CWOverrideRedirect | CWBackPixel | CWBorderPixel
3659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     | CWColormap,
3669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     &xattr);
3679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XSelectInput(SDL_Display, FSwindow, StructureNotifyMask);
3699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Tell KDE to keep the fullscreen window on top */
3719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
3729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XEvent ev;
3739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	long mask;
3749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_memset(&ev, 0, sizeof(ev));
3769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ev.xclient.type = ClientMessage;
3779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ev.xclient.window = SDL_Root;
3789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ev.xclient.message_type = XInternAtom(SDL_Display,
3799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					      "KWM_KEEP_ON_TOP", False);
3809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ev.xclient.format = 32;
3819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ev.xclient.data.l[0] = FSwindow;
3829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ev.xclient.data.l[1] = CurrentTime;
3839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	mask = SubstructureRedirectMask;
3849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSendEvent(SDL_Display, SDL_Root, False, mask, &ev);
3859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    hints = NULL;
3889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(WMwindow) {
3899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* All window attributes must survive the recreation */
3909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	hints = XGetWMHints(SDL_Display, WMwindow);
3919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XDestroyWindow(SDL_Display, WMwindow);
3929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Create the window for windowed management */
3959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* (reusing the xattr structure above) */
3969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    WMwindow = XCreateWindow(SDL_Display, SDL_Root,
3979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                             x, y, 32, 32, 0,
3989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     this->hidden->depth, InputOutput, SDL_Visual,
3999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     CWBackPixel | CWBorderPixel | CWColormap,
4009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     &xattr);
4019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Set the input hints so we get keyboard input */
4039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(!hints) {
4049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	hints = XAllocWMHints();
4059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	hints->input = True;
4069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	hints->flags = InputHint;
4079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XSetWMHints(SDL_Display, WMwindow, hints);
4099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XFree(hints);
4109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    X11_SetCaptionNoLock(this, this->wm_title, this->wm_icon);
4119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    app_event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask
4139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	| PropertyChangeMask | StructureNotifyMask | KeymapStateMask;
4149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XSelectInput(SDL_Display, WMwindow, app_event_mask);
4159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Set the class hints so we can get an icon (AfterStep) */
4179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    get_classname(classname, sizeof(classname));
4189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
4199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XClassHint *classhints;
4209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	classhints = XAllocClassHint();
4219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(classhints != NULL) {
4229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    classhints->res_name = classname;
4239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    classhints->res_class = classname;
4249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    XSetClassHint(SDL_Display, WMwindow, classhints);
4259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    XFree(classhints);
4269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		pid_t pid = getpid();
4319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		char hostname[256];
4329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1) {
4349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			Atom _NET_WM_PID = XInternAtom(SDL_Display, "_NET_WM_PID", False);
4359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			Atom WM_CLIENT_MACHINE = XInternAtom(SDL_Display, "WM_CLIENT_MACHINE", False);
4369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hostname[sizeof(hostname)-1] = '\0';
4389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XChangeProperty(SDL_Display, WMwindow, _NET_WM_PID, XA_CARDINAL, 32,
4399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					PropModeReplace, (unsigned char *)&pid, 1);
4409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XChangeProperty(SDL_Display, WMwindow, WM_CLIENT_MACHINE, XA_STRING, 8,
4419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					PropModeReplace, (unsigned char *)hostname, SDL_strlen(hostname));
4429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Setup the communication with the IM server */
4469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* create_aux_windows may be called several times against the same
4479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   Display.  We should reuse the SDL_IM if one has been opened for
4489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   the Display, so we should not simply reset SDL_IM here.  */
4499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	#ifdef X_HAVE_UTF8_STRING
4519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (SDL_X11_HAVE_UTF8) {
4529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Discard obsolete resources if any.  */
4539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (SDL_IM != NULL && SDL_Display != XDisplayOfIM(SDL_IM)) {
4549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Just a double check. I don't think this
4559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		           code is ever executed. */
4569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_SetError("display has changed while an IM is kept");
4579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (SDL_IC) {
4589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				XUnsetICFocus(SDL_IC);
4599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				XDestroyIC(SDL_IC);
4609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_IC = NULL;
4619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
4629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XCloseIM(SDL_IM);
4639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_IM = NULL;
4649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Open an input method.  */
4679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (SDL_IM == NULL) {
4689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			char *old_locale = NULL, *old_modifiers = NULL;
4699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			const char *p;
4709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			size_t n;
4719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* I'm not comfortable to do locale setup
4729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   here.  However, we need C library locale
4739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   (and xlib modifiers) to be set based on the
4749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   user's preference to use XIM, and many
4759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   existing game programs doesn't take care of
4769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   users' locale preferences, so someone other
4779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   than the game program should do it.
4789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   Moreover, ones say that some game programs
4799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   heavily rely on the C locale behaviour,
4809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   e.g., strcol()'s, and we can't change the C
4819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   library locale.  Given the situation, I
4829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   couldn't find better place to do the
4839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   job... */
4849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Save the current (application program's)
4869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   locale settings.  */
4879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			p = setlocale(LC_ALL, NULL);
4889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( p ) {
4899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				n = SDL_strlen(p)+1;
4909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				old_locale = SDL_stack_alloc(char, n);
4919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if ( old_locale ) {
4929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_strlcpy(old_locale, p, n);
4939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
4949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
4959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			p = XSetLocaleModifiers(NULL);
4969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( p ) {
4979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				n = SDL_strlen(p)+1;
4989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				old_modifiers = SDL_stack_alloc(char, n);
4999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if ( old_modifiers ) {
5009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_strlcpy(old_modifiers, p, n);
5019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
5029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
5039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Fetch the user's preferences and open the
5059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   input method with them.  */
5069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			setlocale(LC_ALL, "");
5079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSetLocaleModifiers("");
5089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_IM = XOpenIM(SDL_Display, NULL, classname, classname);
5099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Restore the application's locale settings
5119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   so that we don't break the application's
5129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   expected behaviour.  */
5139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( old_locale ) {
5149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/* We need to restore the C library
5159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   locale first, since the
5169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   interpretation of the X modifier
5179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   may depend on it.  */
5189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				setlocale(LC_ALL, old_locale);
5199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_stack_free(old_locale);
5209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
5219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( old_modifiers ) {
5229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				XSetLocaleModifiers(old_modifiers);
5239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_stack_free(old_modifiers);
5249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
5259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
5269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Create a new input context for the new window just created.  */
5289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (SDL_IM == NULL) {
5299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_SetError("no input method could be opened");
5309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
5319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (SDL_IC != NULL) {
5329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/* Discard the old IC before creating new one.  */
5339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    XUnsetICFocus(SDL_IC);
5349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    XDestroyIC(SDL_IC);
5359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
5369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Theoretically we should check the current IM supports
5379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   PreeditNothing+StatusNothing style (i.e., root window method)
5389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   before creating the IC.  However, it is the bottom line method,
5399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   and we supports any other options.  If the IM didn't support
5409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   root window method, the following call fails, and SDL falls
5419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   back to pre-XIM keyboard handling.  */
5429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_IC = pXCreateIC(SDL_IM,
5439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XNClientWindow, WMwindow,
5449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XNFocusWindow, WMwindow,
5459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
5469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XNResourceName, classname,
5479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XNResourceClass, classname,
5489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					NULL);
5499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (SDL_IC == NULL) {
5519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_SetError("no input context could be created");
5529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				XCloseIM(SDL_IM);
5539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_IM = NULL;
5549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			} else {
5559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/* We need to receive X events that an IM wants and to pass
5569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   them to the IM through XFilterEvent. The set of events may
5579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   vary depending on the IM implementation and the options
5589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   specified through various routes. Although unlikely, the
5599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   xlib specification allows IM to change the event requirement
5609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   with its own circumstances, it is safe to call SelectInput
5619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   whenever we re-create an IC.  */
5629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				unsigned long mask = 0;
5639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				char *ret = pXGetICValues(SDL_IC, XNFilterEvents, &mask, NULL);
5649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (ret != NULL) {
5659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XUnsetICFocus(SDL_IC);
5669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XDestroyIC(SDL_IC);
5679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_IC = NULL;
5689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_SetError("no input context could be created");
5699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XCloseIM(SDL_IM);
5709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_IM = NULL;
5719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				} else {
5729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XSelectInput(SDL_Display, WMwindow, app_event_mask | mask);
5739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XSetICFocus(SDL_IC);
5749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
5759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
5769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
5779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
5789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	#endif
5799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Allow the window to be deleted by the window manager */
5819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1);
5829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_VideoInit(_THIS, SDL_PixelFormat *vformat)
5859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *env;
5879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *display;
5889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int i;
5899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Open the X11 display */
5919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	display = NULL;		/* Get it from DISPLAY environment variable */
5929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) ||
5949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	     (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) {
5959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		local_X11 = 1;
5969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
5979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		local_X11 = 0;
5989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
5999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Display = XOpenDisplay(display);
6009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC)
6019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* On Tru64 if linking without -lX11, it fails and you get following message.
6029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * Xlib: connection to ":0.0" refused by server
6039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * Xlib: XDM authorization key matches an existing client!
6049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 *
6059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * It succeeds if retrying 1 second later
6069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * or if running xhost +localhost on shell.
6079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 *
6089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 */
6099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Display == NULL ) {
6109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Delay(1000);
6119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Display = XOpenDisplay(display);
6129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Display == NULL ) {
6159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_SetError("Couldn't open X11 display");
6169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return(-1);
6179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef X11_DEBUG
6199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSynchronize(SDL_Display, True);
6209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Create an alternate X display for graphics updates -- allows us
6239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   to do graphics updates in a separate thread from event handling.
6249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   Thread-safe X11 doesn't seem to exist.
6259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 */
6269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	GFX_Display = XOpenDisplay(display);
6279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( GFX_Display == NULL ) {
6289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XCloseDisplay(SDL_Display);
6299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Display = NULL;
6309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_SetError("Couldn't open X11 display");
6319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return(-1);
6329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set the normal X error handler */
6359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	X_handler = XSetErrorHandler(x_errhandler);
6369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set the error handler if we lose the X display */
6389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XIO_handler = XSetIOErrorHandler(xio_errhandler);
6399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set the X extension error handler */
6419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Xext_handler = XSetExtensionErrorHandler(xext_errhandler);
6429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* use default screen (from $DISPLAY) */
6449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Screen = DefaultScreen(SDL_Display);
6459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NO_SHARED_MEMORY
6479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Check for MIT shared memory extension */
6489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	use_mitshm = 0;
6499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( local_X11 ) {
6509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		use_mitshm = XShmQueryExtension(SDL_Display);
6519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* NO_SHARED_MEMORY */
6539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Get the available video modes */
6559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(X11_GetVideoModes(this) < 0) {
6569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XCloseDisplay(GFX_Display);
6579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		GFX_Display = NULL;
6589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XCloseDisplay(SDL_Display);
6599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Display = NULL;
6609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    return -1;
6619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Determine the current screen size */
6649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	this->info.current_w = DisplayWidth(SDL_Display, SDL_Screen);
6659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	this->info.current_h = DisplayHeight(SDL_Display, SDL_Screen);
6669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Determine the default screen depth:
6689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	   Use the default visual (or at least one with the same depth) */
6699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_DisplayColormap = DefaultColormap(SDL_Display, SDL_Screen);
6709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(i = 0; i < this->hidden->nvisuals; i++)
6719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(this->hidden->visuals[i].depth == DefaultDepth(SDL_Display,
6729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall							      SDL_Screen))
6739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		break;
6749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(i == this->hidden->nvisuals) {
6759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* default visual was useless, take the deepest one instead */
6769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    i = 0;
6779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Visual = this->hidden->visuals[i].visual;
6799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen) ) {
6809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_XColorMap = SDL_DisplayColormap;
6819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
6829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
6839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					    SDL_Visual, AllocNone);
6849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	this->hidden->depth = this->hidden->visuals[i].depth;
6869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	vformat->BitsPerPixel = this->hidden->visuals[i].bpp;
6879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( vformat->BitsPerPixel > 8 ) {
6889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		vformat->Rmask = SDL_Visual->red_mask;
6899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	  	vformat->Gmask = SDL_Visual->green_mask;
6909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	  	vformat->Bmask = SDL_Visual->blue_mask;
6919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( this->hidden->depth == 32 ) {
6939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		vformat->Amask = (0xFFFFFFFF & ~(vformat->Rmask|vformat->Gmask|vformat->Bmask));
6949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	X11_SaveVidModeGamma(this);
6969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Allow environment override of screensaver disable. */
6989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
6999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( env ) {
7009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		allow_screensaver = SDL_atoi(env);
7019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
7029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef SDL_VIDEO_DISABLE_SCREENSAVER
7039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		allow_screensaver = 0;
7049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
7059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		allow_screensaver = 1;
7069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
7079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* See if we have been passed a window to use */
7109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_windowid = SDL_getenv("SDL_WINDOWID");
7119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Create the fullscreen and managed windows */
7139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	create_aux_windows(this);
7149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Create the blank cursor */
7169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask,
7179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					BLANK_CWIDTH, BLANK_CHEIGHT,
7189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall						BLANK_CHOTX, BLANK_CHOTY);
7199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Fill in some window manager capabilities */
7219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	this->info.wm_available = 1;
7229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* We're done! */
7249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XFlush(SDL_Display);
7259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(0);
7269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
7279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void X11_DestroyWindow(_THIS, SDL_Surface *screen)
7299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
7309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Clean up OpenGL */
7319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( screen ) {
7329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT);
7339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	X11_GL_Shutdown(this);
7359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( ! SDL_windowid ) {
7379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Hide the managed window */
7389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WMwindow ) {
7399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XUnmapWindow(SDL_Display, WMwindow);
7409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( screen && (screen->flags & SDL_FULLSCREEN) ) {
7429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			screen->flags &= ~SDL_FULLSCREEN;
7439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			X11_LeaveFullScreen(this);
7449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Destroy the output window */
7479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_Window ) {
7489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XDestroyWindow(SDL_Display, SDL_Window);
7499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Free the colormap entries */
7529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_XPixels ) {
7539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			int numcolors;
7549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			unsigned long pixel;
7559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			numcolors = SDL_Visual->map_entries;
7569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			for ( pixel=0; pixel<numcolors; ++pixel ) {
7579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				while ( SDL_XPixels[pixel] > 0 ) {
7589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XFreeColors(GFX_Display,
7599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall						SDL_DisplayColormap,&pixel,1,0);
7609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					--SDL_XPixels[pixel];
7619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
7629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(SDL_XPixels);
7649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_XPixels = NULL;
7659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Free the graphics context */
7689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_GC ) {
7699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XFreeGC(SDL_Display, SDL_GC);
7709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_GC = 0;
7719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
7749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_bool X11_WindowPosition(_THIS, int *x, int *y, int w, int h)
7769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
7779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
7789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
7799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( window ) {
7809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_sscanf(window, "%d,%d", x, y) == 2 ) {
7819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return SDL_TRUE;
7829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_strcmp(window, "center") == 0 ) {
7849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			center = window;
7859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( center ) {
7889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		*x = (DisplayWidth(SDL_Display, SDL_Screen) - w)/2;
7899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		*y = (DisplayHeight(SDL_Display, SDL_Screen) - h)/2;
7909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return SDL_TRUE;
7919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return SDL_FALSE;
7939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
7949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void X11_SetSizeHints(_THIS, int w, int h, Uint32 flags)
7969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
7979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSizeHints *hints;
7989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	hints = XAllocSizeHints();
8009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( hints ) {
8019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!(flags & SDL_RESIZABLE)) {
8029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->min_width = hints->max_width = w;
8039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->min_height = hints->max_height = h;
8049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->flags = PMaxSize | PMinSize;
8059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( flags & SDL_FULLSCREEN ) {
8079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->x = 0;
8089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->y = 0;
8099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->flags |= USPosition;
8109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else
8119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Center it, if desired */
8129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( X11_WindowPosition(this, &hints->x, &hints->y, w, h) ) {
8139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			hints->flags |= USPosition;
8149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Hints must be set before moving the window, otherwise an
8169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   unwanted ConfigureNotify event will be issued */
8179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSetWMNormalHints(SDL_Display, WMwindow, hints);
8189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XMoveWindow(SDL_Display, WMwindow, hints->x, hints->y);
8209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Flush the resize event so we don't catch it later */
8229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSync(SDL_Display, True);
8239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XSetWMNormalHints(SDL_Display, WMwindow, hints);
8259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XFree(hints);
8269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Respect the window caption style */
8299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( flags & SDL_NOFRAME ) {
8309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_bool set;
8319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Atom WM_HINTS;
8329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* We haven't modified the window manager hints yet */
8349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		set = SDL_FALSE;
8359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* First try to set MWM hints */
8379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True);
8389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WM_HINTS != None ) {
8399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Hints used by Motif compliant window managers */
8409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			struct {
8419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				unsigned long flags;
8429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				unsigned long functions;
8439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				unsigned long decorations;
8449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				long input_mode;
8459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				unsigned long status;
8469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			} MWMHints = { (1L << 1), 0, 0, 0, 0 };
8479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XChangeProperty(SDL_Display, WMwindow,
8499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                WM_HINTS, WM_HINTS, 32,
8509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                PropModeReplace,
8519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					(unsigned char *)&MWMHints,
8529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					sizeof(MWMHints)/sizeof(long));
8539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			set = SDL_TRUE;
8549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Now try to set KWM hints */
8569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True);
8579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WM_HINTS != None ) {
8589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			long KWMHints = 0;
8599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XChangeProperty(SDL_Display, WMwindow,
8619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                WM_HINTS, WM_HINTS, 32,
8629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                PropModeReplace,
8639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					(unsigned char *)&KWMHints,
8649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					sizeof(KWMHints)/sizeof(long));
8659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			set = SDL_TRUE;
8669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Now try to set GNOME hints */
8689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True);
8699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WM_HINTS != None ) {
8709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			long GNOMEHints = 0;
8719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XChangeProperty(SDL_Display, WMwindow,
8739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                WM_HINTS, WM_HINTS, 32,
8749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                PropModeReplace,
8759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					(unsigned char *)&GNOMEHints,
8769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					sizeof(GNOMEHints)/sizeof(long));
8779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			set = SDL_TRUE;
8789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Finally set the transient hints if necessary */
8809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( ! set ) {
8819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSetTransientForHint(SDL_Display, WMwindow, SDL_Root);
8829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
8849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_bool set;
8859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Atom WM_HINTS;
8869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* We haven't modified the window manager hints yet */
8889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		set = SDL_FALSE;
8899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* First try to unset MWM hints */
8919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True);
8929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WM_HINTS != None ) {
8939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
8949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			set = SDL_TRUE;
8959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Now try to unset KWM hints */
8979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True);
8989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WM_HINTS != None ) {
8999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
9009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			set = SDL_TRUE;
9019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Now try to unset GNOME hints */
9039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True);
9049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( WM_HINTS != None ) {
9059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
9069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			set = SDL_TRUE;
9079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Finally unset the transient hints if necessary */
9099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( ! set ) {
9109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XDeleteProperty(SDL_Display, WMwindow, XA_WM_TRANSIENT_FOR);
9119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_CreateWindow(_THIS, SDL_Surface *screen,
9169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    int w, int h, int bpp, Uint32 flags)
9179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int i, depth;
9199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Visual *vis;
9209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int vis_change;
9219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Uint32 Amask;
9229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* If a window is already present, destroy it and start fresh */
9249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Window ) {
9259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_DestroyWindow(this, screen);
9269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		switch_waiting = 0; /* Prevent jump back to now-meaningless state. */
9279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* See if we have been given a window id */
9309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_windowid ) {
9319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Window = SDL_strtol(SDL_windowid, NULL, 0);
9329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
9339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Window = 0;
9349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* find out which visual we are going to use */
9379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( flags & SDL_OPENGL ) {
9389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XVisualInfo *vi;
9399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		vi = X11_GL_GetVisual(this);
9419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if( !vi ) {
9429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return -1;
9439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		vis = vi->visual;
9459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		depth = vi->depth;
9469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else if ( SDL_windowid ) {
9479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XWindowAttributes a;
9489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XGetWindowAttributes(SDL_Display, SDL_Window, &a);
9509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		vis = a.visual;
9519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		depth = a.depth;
9529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
9539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for ( i = 0; i < this->hidden->nvisuals; i++ ) {
9549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( this->hidden->visuals[i].bpp == bpp )
9559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
9569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( i == this->hidden->nvisuals ) {
9589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_SetError("No matching visual for requested depth");
9599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return -1;	/* should never happen */
9609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		vis = this->hidden->visuals[i].visual;
9629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		depth = this->hidden->visuals[i].depth;
9639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef X11_DEBUG
9659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        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);
9669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
9679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	vis_change = (vis != SDL_Visual);
9689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Visual = vis;
9699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	this->hidden->depth = depth;
9709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Allocate the new pixel format for this video mode */
9729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( this->hidden->depth == 32 ) {
9739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Amask = (0xFFFFFFFF & ~(vis->red_mask|vis->green_mask|vis->blue_mask));
9749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
9759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Amask = 0;
9769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( ! SDL_ReallocFormat(screen, bpp,
9789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			vis->red_mask, vis->green_mask, vis->blue_mask, Amask) ) {
9799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return -1;
9809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Create the appropriate colormap */
9839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_XColorMap != SDL_DisplayColormap ) {
9849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XFreeColormap(SDL_Display, SDL_XColorMap);
9859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Visual->class == PseudoColor ) {
9879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    int ncolors;
9889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* Allocate the pixel flags */
9909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    ncolors = SDL_Visual->map_entries;
9919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_XPixels = SDL_malloc(ncolors * sizeof(int));
9929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if(SDL_XPixels == NULL) {
9939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_OutOfMemory();
9949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return -1;
9959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    }
9969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_memset(SDL_XPixels, 0, ncolors * sizeof(*SDL_XPixels));
9979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* always allocate a private colormap on non-default visuals */
9999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if ( SDL_Visual != DefaultVisual(SDL_Display, SDL_Screen) ) {
10009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		flags |= SDL_HWPALETTE;
10019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    }
10029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    if ( flags & SDL_HWPALETTE ) {
10039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		screen->flags |= SDL_HWPALETTE;
10049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
10059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                                SDL_Visual, AllocAll);
10069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    } else {
10079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_XColorMap = SDL_DisplayColormap;
10089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    }
10099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else if ( SDL_Visual->class == DirectColor ) {
10109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* Create a colormap which we can manipulate for gamma */
10129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
10139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                            SDL_Visual, AllocAll);
10149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            XSync(SDL_Display, False);
10159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* Initialize the colormap to the identity mapping */
10179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_GetGammaRamp(0, 0, 0);
10189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    this->screen = screen;
10199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    X11_SetGammaRamp(this, this->gamma);
10209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    this->screen = NULL;
10219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
10229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* Create a read-only colormap for our window */
10239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
10249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	                                    SDL_Visual, AllocNone);
10259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Recreate the auxiliary windows, if needed (required for GL) */
10289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( vis_change )
10299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    create_aux_windows(this);
10309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(screen->flags & SDL_HWPALETTE) {
10329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    /* Since the full-screen window might have got a nonzero background
10339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	       colour (0 is white on some displays), we should reset the
10349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	       background to 0 here since that is what the user expects
10359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	       with a private colormap */
10369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    XSetWindowBackground(SDL_Display, FSwindow, 0);
10379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    XClearWindow(SDL_Display, FSwindow);
10389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* resize the (possibly new) window manager window */
10419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if( !SDL_windowid ) {
10429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        X11_SetSizeHints(this, w, h, flags);
10439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		window_w = w;
10449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		window_h = h;
10459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XResizeWindow(SDL_Display, WMwindow, w, h);
10469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Create (or use) the X11 display window */
10499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( !SDL_windowid ) {
10509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( flags & SDL_OPENGL ) {
10519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( X11_GL_CreateWindow(this, w, h) < 0 ) {
10529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				return(-1);
10539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
10549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
10559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSetWindowAttributes swa;
10569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			swa.background_pixel = 0;
10589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			swa.border_pixel = 0;
10599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			swa.colormap = SDL_XColorMap;
10609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_Window = XCreateWindow(SDL_Display, WMwindow,
10619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                           	0, 0, w, h, 0, depth,
10629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                           	InputOutput, SDL_Visual,
10639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                           	CWBackPixel | CWBorderPixel
10649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                           	| CWColormap, &swa);
10659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
10669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Only manage our input if we own the window */
10679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XSelectInput(SDL_Display, SDL_Window,
10689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					( EnterWindowMask | LeaveWindowMask
10699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					| ButtonPressMask | ButtonReleaseMask
10709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					| PointerMotionMask | ExposureMask ));
10719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Create the graphics context here, once we have a window */
10739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( flags & SDL_OPENGL ) {
10749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( X11_GL_CreateContext(this) < 0 ) {
10759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return(-1);
10769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
10779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			screen->flags |= SDL_OPENGL;
10789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
10799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
10809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XGCValues gcv;
10819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		gcv.graphics_exposures = False;
10839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_GC = XCreateGC(SDL_Display, SDL_Window,
10849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		                   GCGraphicsExposures, &gcv);
10859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( ! SDL_GC ) {
10869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_SetError("Couldn't create graphics context");
10879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return(-1);
10889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
10899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set our colormaps when not setting a GL mode */
10929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( ! (flags & SDL_OPENGL) ) {
10939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap);
10949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if( !SDL_windowid ) {
10959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap);
10969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		    XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap);
10979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
10989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if 0 /* This is an experiment - are the graphics faster now? - nope. */
11019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_getenv("SDL_VIDEO_X11_BACKINGSTORE") )
11029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
11039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Cache the window in the server, when possible */
11049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
11059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Screen *xscreen;
11069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XSetWindowAttributes a;
11079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen);
11099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		a.backing_store = DoesBackingStore(xscreen);
11109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( a.backing_store != NotUseful ) {
11119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XChangeWindowAttributes(SDL_Display, SDL_Window,
11129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			                        CWBackingStore, &a);
11139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Map them both and go fullscreen, if requested */
11179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( ! SDL_windowid ) {
11189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XMapWindow(SDL_Display, SDL_Window);
11199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XMapWindow(SDL_Display, WMwindow);
11209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_WaitMapped(this, WMwindow);
11219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( flags & SDL_FULLSCREEN ) {
11229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			screen->flags |= SDL_FULLSCREEN;
11239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			X11_EnterFullScreen(this);
11249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
11259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			screen->flags &= ~SDL_FULLSCREEN;
11269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(0);
11309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
11319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_ResizeWindow(_THIS,
11339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_Surface *screen, int w, int h, Uint32 flags)
11349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( ! SDL_windowid ) {
11369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Resize the window manager window */
11379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_SetSizeHints(this, w, h, flags);
11389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		window_w = w;
11399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		window_h = h;
11409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XResizeWindow(SDL_Display, WMwindow, w, h);
11419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Resize the fullscreen and display windows */
11439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( flags & SDL_FULLSCREEN ) {
11449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( screen->flags & SDL_FULLSCREEN ) {
11459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				X11_ResizeFullScreen(this);
11469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			} else {
11479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				screen->flags |= SDL_FULLSCREEN;
11489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				X11_EnterFullScreen(this);
11499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
11509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
11519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ( screen->flags & SDL_FULLSCREEN ) {
11529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				screen->flags &= ~SDL_FULLSCREEN;
11539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				X11_LeaveFullScreen(this);
11549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
11559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XResizeWindow(SDL_Display, SDL_Window, w, h);
11579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(0);
11599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
11609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallSDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current,
11629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				int width, int height, int bpp, Uint32 flags)
11639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Uint32 saved_flags;
11659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Lock the event thread, in multi-threading environments */
11679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Lock_EventThread();
11689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Check the combination of flags we were passed */
11709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( flags & SDL_FULLSCREEN ) {
11719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Clear fullscreen flag if not supported */
11729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_windowid ) {
11739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			flags &= ~SDL_FULLSCREEN;
11749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Flush any delayed updates */
11789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSync(GFX_Display, False);
11799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set up the X11 window */
11819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	saved_flags = current->flags;
11829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( (SDL_Window) && ((saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL))
11839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	      && (bpp == current->format->BitsPerPixel)
11849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) {
11859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (X11_ResizeWindow(this, current, width, height, flags) < 0) {
11869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			current = NULL;
11879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			goto done;
11889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_PendingConfigureNotifyWidth = width;
11909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_PendingConfigureNotifyHeight = height;
11919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
11929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) {
11939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			current = NULL;
11949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			goto done;
11959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Update the internal keyboard state */
11999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	X11_SetKeyboardState(SDL_Display, NULL);
12009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* When the window is first mapped, ignore non-modifier keys */
12029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( !current->w && !current->h ) {
12039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Uint8 *keys = SDL_GetKeyState(NULL);
12049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int i;
12059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for ( i = 0; i < SDLK_LAST; ++i ) {
12069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			switch (i) {
12079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_NUMLOCK:
12089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_CAPSLOCK:
12099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_LCTRL:
12109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_RCTRL:
12119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_LSHIFT:
12129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_RSHIFT:
12139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_LALT:
12149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_RALT:
12159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_LMETA:
12169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_RMETA:
12179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    case SDLK_MODE:
12189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
12199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			    default:
12209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				keys[i] = SDL_RELEASED;
12219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
12229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
12239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
12249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set up the new mode framebuffer */
12279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( ((current->w != width) || (current->h != height)) ||
12289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) {
12299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		current->w = width;
12309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		current->h = height;
12319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		current->pitch = SDL_CalculatePitch(current);
12329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (X11_ResizeImage(this, current, flags) < 0) {
12339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			current = NULL;
12349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			goto done;
12359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
12369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Clear these flags and set them only if they are in the new set. */
12399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	current->flags &= ~(SDL_RESIZABLE|SDL_NOFRAME);
12409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME));
12419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  done:
12439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Release the event thread */
12449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSync(SDL_Display, False);
12459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Unlock_EventThread();
12469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* We're done! */
12489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(current);
12499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int X11_ToggleFullScreen(_THIS, int on)
12529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Uint32 event_thread;
12549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Don't switch if we don't own the window */
12569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_windowid ) {
12579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return(0);
12589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Don't lock if we are the event thread */
12619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	event_thread = SDL_EventThreadID();
12629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( event_thread && (SDL_ThreadID() == event_thread) ) {
12639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		event_thread = 0;
12649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( event_thread ) {
12669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Lock_EventThread();
12679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( on ) {
12699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		this->screen->flags |= SDL_FULLSCREEN;
12709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_EnterFullScreen(this);
12719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
12729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		this->screen->flags &= ~SDL_FULLSCREEN;
12739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_LeaveFullScreen(this);
12749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	X11_RefreshDisplay(this);
12769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( event_thread ) {
12779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Unlock_EventThread();
12789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_ResetKeyboard();
12809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(1);
12819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Update the current mouse state and position */
12849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void X11_UpdateMouse(_THIS)
12859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Window u1; int u2;
12879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Window current_win;
12889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int x, y;
12899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int mask;
12909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Lock the event thread, in multi-threading environments */
12929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Lock_EventThread();
12939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( XQueryPointer(SDL_Display, SDL_Window, &u1, &current_win,
12949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	                   &u2, &u2, &x, &y, &mask) ) {
12959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( (x >= 0) && (x < SDL_VideoSurface->w) &&
12969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		     (y >= 0) && (y < SDL_VideoSurface->h) ) {
12979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
12989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_PrivateMouseMotion(0, 0, x, y);
12999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
13009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
13019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
13029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Unlock_EventThread();
13049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* simple colour distance metric. Supposed to be better than a plain
13079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   Euclidian distance anyway. */
13089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define COLOUR_FACTOR 3
13099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LIGHT_FACTOR 1
13109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define COLOUR_DIST(r1, g1, b1, r2, g2, b2)				\
13119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	(COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2))	\
13129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 + LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2)))
13139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void allocate_nearest(_THIS, SDL_Color *colors,
13159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			     SDL_Color *want, int nwant)
13169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
13179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/*
13189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * There is no way to know which ones to choose from, so we retrieve
13199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * the entire colormap and try the nearest possible, until we find one
13209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * that is shared.
13219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 */
13229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XColor all[256];
13239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int i;
13249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(i = 0; i < 256; i++)
13259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		all[i].pixel = i;
13269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/*
13279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * XQueryColors sets the flags in the XColor struct, so we use
13289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 * that to keep track of which colours are available
13299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	 */
13309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XQueryColors(GFX_Display, SDL_XColorMap, all, 256);
13319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for(i = 0; i < nwant; i++) {
13339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XColor *c;
13349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int j;
13359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int best = 0;
13369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int mindist = 0x7fffffff;
13379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int ri = want[i].r;
13389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int gi = want[i].g;
13399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int bi = want[i].b;
13409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for(j = 0; j < 256; j++) {
13419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			int rj, gj, bj, d2;
13429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if(!all[j].flags)
13439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				continue;	/* unavailable colour cell */
13449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			rj = all[j].red >> 8;
13459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			gj = all[j].green >> 8;
13469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			bj = all[j].blue >> 8;
13479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj);
13489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if(d2 < mindist) {
13499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				mindist = d2;
13509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				best = j;
13519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
13529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
13539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(SDL_XPixels[best])
13549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			continue; /* already allocated, waste no more time */
13559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		c = all + best;
13569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(XAllocColor(GFX_Display, SDL_XColorMap, c)) {
13579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* got it */
13589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			colors[c->pixel].r = c->red >> 8;
13599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			colors[c->pixel].g = c->green >> 8;
13609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			colors[c->pixel].b = c->blue >> 8;
13619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			++SDL_XPixels[c->pixel];
13629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		} else {
13639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/*
13649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 * The colour couldn't be allocated, probably being
13659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 * owned as a r/w cell by another client. Flag it as
13669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 * unavailable and try again. The termination of the
13679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 * loop is guaranteed since at least black and white
13689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 * are always there.
13699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 */
13709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			c->flags = 0;
13719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			i--;
13729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
13739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
13779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
13789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int nrej = 0;
13799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Check to make sure we have a colormap allocated */
13819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_XPixels == NULL ) {
13829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return(0);
13839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
13859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        /* private writable colormap: just set the colours we need */
13869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        XColor  *xcmap;
13879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int i;
13889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        xcmap = SDL_stack_alloc(XColor, ncolors);
13899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(xcmap == NULL)
13909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		        return 0;
13919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for ( i=0; i<ncolors; ++i ) {
13929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			xcmap[i].pixel = i + firstcolor;
13939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			xcmap[i].red   = (colors[i].r<<8)|colors[i].r;
13949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			xcmap[i].green = (colors[i].g<<8)|colors[i].g;
13959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			xcmap[i].blue  = (colors[i].b<<8)|colors[i].b;
13969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			xcmap[i].flags = (DoRed|DoGreen|DoBlue);
13979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
13989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
13999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XSync(GFX_Display, False);
14009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_stack_free(xcmap);
14019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} else {
14029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        /*
14039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * Shared colormap: We only allocate read-only cells, which
14049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * increases the likelyhood of colour sharing with other
14059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * clients. The pixel values will almost certainly be
14069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * different from the requested ones, so the user has to
14079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * walk the colormap and see which index got what colour.
14089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 *
14099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * We can work directly with the logical palette since it
14109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * has already been set when we get here.
14119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 */
14129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Color *want, *reject;
14139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        unsigned long *freelist;
14149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int i;
14159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int nfree = 0;
14169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		int nc = this->screen->format->palette->ncolors;
14179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        colors = this->screen->format->palette->colors;
14189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		freelist = SDL_stack_alloc(unsigned long, nc);
14199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* make sure multiple allocations of the same cell are freed */
14209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	        for(i = 0; i < ncolors; i++) {
14219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		        int pixel = firstcolor + i;
14229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		        while(SDL_XPixels[pixel]) {
14239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			        freelist[nfree++] = pixel;
14249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				--SDL_XPixels[pixel];
14259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
14269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
14279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0);
14289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_stack_free(freelist);
14299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		want = SDL_stack_alloc(SDL_Color, ncolors);
14319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		reject = SDL_stack_alloc(SDL_Color, ncolors);
14329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color));
14339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* make sure the user isn't fooled by her own wishes
14349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		   (black is safe, always available in the default colormap) */
14359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color));
14369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* now try to allocate the colours */
14389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for(i = 0; i < ncolors; i++) {
14399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		        XColor col;
14409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			col.red = want[i].r << 8;
14419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			col.green = want[i].g << 8;
14429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			col.blue = want[i].b << 8;
14439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			col.flags = DoRed | DoGreen | DoBlue;
14449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) {
14459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			        /* We got the colour, or at least the nearest
14469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   the hardware could get. */
14479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			        colors[col.pixel].r = col.red >> 8;
14489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				colors[col.pixel].g = col.green >> 8;
14499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				colors[col.pixel].b = col.blue >> 8;
14509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				++SDL_XPixels[col.pixel];
14519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			} else {
14529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/*
14539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 * no more free cells, add it to the list
14549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 * of rejected colours
14559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 */
14569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				reject[nrej++] = want[i];
14579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
14589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
14599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(nrej)
14609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			allocate_nearest(this, colors, reject, nrej);
14619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_stack_free(reject);
14629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_stack_free(want);
14639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
14649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return nrej == 0;
14659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint X11_SetGammaRamp(_THIS, Uint16 *ramp)
14689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int i, ncolors;
14709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XColor xcmap[256];
14719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* See if actually setting the gamma is supported */
14739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Visual->class != DirectColor ) {
14749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    SDL_SetError("Gamma correction not supported on this visual");
14759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    return(-1);
14769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
14779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Calculate the appropriate palette for the given gamma ramp */
14799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ncolors = SDL_Visual->map_entries;
14809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for ( i=0; i<ncolors; ++i ) {
14819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		Uint8 c = (256 * i / ncolors);
14829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c);
14839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		xcmap[i].red   = ramp[0*256+c];
14849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		xcmap[i].green = ramp[1*256+c];
14859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		xcmap[i].blue  = ramp[2*256+c];
14869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		xcmap[i].flags = (DoRed|DoGreen|DoBlue);
14879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
14889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
14899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	XSync(GFX_Display, False);
14909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(0);
14919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Note:  If we are terminated, this could be called in the middle of
14949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   another SDL video routine -- notably UpdateRects.
14959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
14969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid X11_VideoQuit(_THIS)
14979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Shutdown everything that's still up */
14999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* The event thread should be done, so we can touch SDL_Display */
15009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Display != NULL ) {
15019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Flush any delayed updates */
15029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XSync(GFX_Display, False);
15039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Close the connection with the IM server */
15059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		#ifdef X_HAVE_UTF8_STRING
15069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (SDL_IC != NULL) {
15079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XUnsetICFocus(SDL_IC);
15089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XDestroyIC(SDL_IC);
15099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_IC = NULL;
15109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (SDL_IM != NULL) {
15129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XCloseIM(SDL_IM);
15139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_IM = NULL;
15149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		#endif
15169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Start shutting down the windows */
15189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_DestroyImage(this, this->screen);
15199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_DestroyWindow(this, this->screen);
15209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_FreeVideoModes(this);
15219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_XColorMap != SDL_DisplayColormap ) {
15229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XFreeColormap(SDL_Display, SDL_XColorMap);
15239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_iconcolors ) {
15259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			unsigned long pixel;
15269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			Colormap dcmap = DefaultColormap(SDL_Display,
15279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall							 SDL_Screen);
15289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			for(pixel = 0; pixel < 256; ++pixel) {
15299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				while(SDL_iconcolors[pixel] > 0) {
15309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					XFreeColors(GFX_Display,
15319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall						    dcmap, &pixel, 1, 0);
15329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					--SDL_iconcolors[pixel];
15339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
15349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
15359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(SDL_iconcolors);
15369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_iconcolors = NULL;
15379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Restore gamma settings if they've changed */
15409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_GetAppState() & SDL_APPACTIVE ) {
15419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			X11_SwapVidModeGamma(this);
15429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Free that blank cursor */
15459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( SDL_BlankCursor != NULL ) {
15469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			this->FreeWMCursor(this, SDL_BlankCursor);
15479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_BlankCursor = NULL;
15489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Close the X11 graphics connection */
15519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( GFX_Display != NULL ) {
15529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XCloseDisplay(GFX_Display);
15539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			GFX_Display = NULL;
15549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Close the X11 display connection */
15579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		XCloseDisplay(SDL_Display);
15589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Display = NULL;
15599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Reset the X11 error handlers */
15619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( XIO_handler ) {
15629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSetIOErrorHandler(XIO_handler);
15639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( X_handler ) {
15659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			XSetErrorHandler(X_handler);
15669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
15679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Unload GL library after X11 shuts down */
15699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		X11_GL_UnloadLibrary(this);
15709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
15719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
15729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Direct screen access, no memory buffer */
15739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		this->screen->pixels = NULL;
15749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
15759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_VIDEO_DRIVER_X11_XME
15779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    XiGMiscDestroy();
15789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
15799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1581