diff options
author | Franklin Wei <git@fwei.tk> | 2018-02-07 20:04:46 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2018-03-12 20:52:01 -0400 |
commit | 6039eb05ba6d82ef56f2868c96654c552d117bf9 (patch) | |
tree | 9db7016bcbf66cfdf7b9bc998d84c6eaff9c8378 /apps/plugins/sdl/src/video/x11/SDL_x11video.c | |
parent | ef373c03b96b0be08babca581d9f10bccfd4931f (diff) | |
download | rockbox-6039eb05ba6d82ef56f2868c96654c552d117bf9.tar.gz rockbox-6039eb05ba6d82ef56f2868c96654c552d117bf9.zip |
sdl: remove non-rockbox drivers
We never use any of these other drivers, so having them around just takes
up space.
Change-Id: Iced812162df1fef3fd55522b7e700acb6c3bcd41
Diffstat (limited to 'apps/plugins/sdl/src/video/x11/SDL_x11video.c')
-rw-r--r-- | apps/plugins/sdl/src/video/x11/SDL_x11video.c | 1571 |
1 files changed, 0 insertions, 1571 deletions
diff --git a/apps/plugins/sdl/src/video/x11/SDL_x11video.c b/apps/plugins/sdl/src/video/x11/SDL_x11video.c deleted file mode 100644 index f7d80732c0..0000000000 --- a/apps/plugins/sdl/src/video/x11/SDL_x11video.c +++ /dev/null | |||
@@ -1,1571 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* X11 based SDL video driver implementation. | ||
25 | Note: This implementation does not currently need X11 thread locking, | ||
26 | since the event thread uses a separate X connection and any | ||
27 | additional locking necessary is handled internally. However, | ||
28 | if full locking is neccessary, take a look at XInitThreads(). | ||
29 | */ | ||
30 | |||
31 | #include <unistd.h> | ||
32 | #include <sys/ioctl.h> | ||
33 | #ifdef MTRR_SUPPORT | ||
34 | #include <asm/mtrr.h> | ||
35 | #include <sys/fcntl.h> | ||
36 | #endif | ||
37 | |||
38 | #include "SDL_endian.h" | ||
39 | #include "SDL_timer.h" | ||
40 | #include "SDL_thread.h" | ||
41 | #include "SDL_video.h" | ||
42 | #include "SDL_mouse.h" | ||
43 | #include "../SDL_sysvideo.h" | ||
44 | #include "../SDL_pixels_c.h" | ||
45 | #include "../../events/SDL_events_c.h" | ||
46 | #include "SDL_x11video.h" | ||
47 | #include "SDL_x11wm_c.h" | ||
48 | #include "SDL_x11mouse_c.h" | ||
49 | #include "SDL_x11events_c.h" | ||
50 | #include "SDL_x11modes_c.h" | ||
51 | #include "SDL_x11image_c.h" | ||
52 | #include "SDL_x11yuv_c.h" | ||
53 | #include "SDL_x11gl_c.h" | ||
54 | #include "SDL_x11gamma_c.h" | ||
55 | #include "../blank_cursor.h" | ||
56 | |||
57 | #ifdef X_HAVE_UTF8_STRING | ||
58 | #include <locale.h> | ||
59 | #endif | ||
60 | |||
61 | /* Initialization/Query functions */ | ||
62 | static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat); | ||
63 | static SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | ||
64 | static int X11_ToggleFullScreen(_THIS, int on); | ||
65 | static void X11_UpdateMouse(_THIS); | ||
66 | static int X11_SetColors(_THIS, int firstcolor, int ncolors, | ||
67 | SDL_Color *colors); | ||
68 | static int X11_SetGammaRamp(_THIS, Uint16 *ramp); | ||
69 | static void X11_VideoQuit(_THIS); | ||
70 | |||
71 | |||
72 | /* X11 driver bootstrap functions */ | ||
73 | |||
74 | static int X11_Available(void) | ||
75 | { | ||
76 | Display *display = NULL; | ||
77 | if ( SDL_X11_LoadSymbols() ) { | ||
78 | display = XOpenDisplay(NULL); | ||
79 | if ( display != NULL ) { | ||
80 | XCloseDisplay(display); | ||
81 | } | ||
82 | SDL_X11_UnloadSymbols(); | ||
83 | } | ||
84 | return(display != NULL); | ||
85 | } | ||
86 | |||
87 | static void X11_DeleteDevice(SDL_VideoDevice *device) | ||
88 | { | ||
89 | if ( device ) { | ||
90 | if ( device->hidden ) { | ||
91 | SDL_free(device->hidden); | ||
92 | } | ||
93 | if ( device->gl_data ) { | ||
94 | SDL_free(device->gl_data); | ||
95 | } | ||
96 | SDL_free(device); | ||
97 | SDL_X11_UnloadSymbols(); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static SDL_VideoDevice *X11_CreateDevice(int devindex) | ||
102 | { | ||
103 | SDL_VideoDevice *device = NULL; | ||
104 | |||
105 | if ( SDL_X11_LoadSymbols() ) { | ||
106 | /* Initialize all variables that we clean on shutdown */ | ||
107 | device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); | ||
108 | if ( device ) { | ||
109 | SDL_memset(device, 0, (sizeof *device)); | ||
110 | device->hidden = (struct SDL_PrivateVideoData *) | ||
111 | SDL_malloc((sizeof *device->hidden)); | ||
112 | device->gl_data = (struct SDL_PrivateGLData *) | ||
113 | SDL_malloc((sizeof *device->gl_data)); | ||
114 | } | ||
115 | if ( (device == NULL) || (device->hidden == NULL) || | ||
116 | (device->gl_data == NULL) ) { | ||
117 | SDL_OutOfMemory(); | ||
118 | X11_DeleteDevice(device); /* calls SDL_X11_UnloadSymbols(). */ | ||
119 | return(0); | ||
120 | } | ||
121 | SDL_memset(device->hidden, 0, (sizeof *device->hidden)); | ||
122 | SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); | ||
123 | |||
124 | #if SDL_VIDEO_OPENGL_GLX | ||
125 | device->gl_data->swap_interval = -1; | ||
126 | #endif | ||
127 | |||
128 | /* Set the driver flags */ | ||
129 | device->handles_any_size = 1; | ||
130 | |||
131 | /* Set the function pointers */ | ||
132 | device->VideoInit = X11_VideoInit; | ||
133 | device->ListModes = X11_ListModes; | ||
134 | device->SetVideoMode = X11_SetVideoMode; | ||
135 | device->ToggleFullScreen = X11_ToggleFullScreen; | ||
136 | device->UpdateMouse = X11_UpdateMouse; | ||
137 | #if SDL_VIDEO_DRIVER_X11_XV | ||
138 | device->CreateYUVOverlay = X11_CreateYUVOverlay; | ||
139 | #endif | ||
140 | device->SetColors = X11_SetColors; | ||
141 | device->UpdateRects = NULL; | ||
142 | device->VideoQuit = X11_VideoQuit; | ||
143 | device->AllocHWSurface = X11_AllocHWSurface; | ||
144 | device->CheckHWBlit = NULL; | ||
145 | device->FillHWRect = NULL; | ||
146 | device->SetHWColorKey = NULL; | ||
147 | device->SetHWAlpha = NULL; | ||
148 | device->LockHWSurface = X11_LockHWSurface; | ||
149 | device->UnlockHWSurface = X11_UnlockHWSurface; | ||
150 | device->FlipHWSurface = X11_FlipHWSurface; | ||
151 | device->FreeHWSurface = X11_FreeHWSurface; | ||
152 | device->SetGamma = X11_SetVidModeGamma; | ||
153 | device->GetGamma = X11_GetVidModeGamma; | ||
154 | device->SetGammaRamp = X11_SetGammaRamp; | ||
155 | device->GetGammaRamp = NULL; | ||
156 | #if SDL_VIDEO_OPENGL_GLX | ||
157 | device->GL_LoadLibrary = X11_GL_LoadLibrary; | ||
158 | device->GL_GetProcAddress = X11_GL_GetProcAddress; | ||
159 | device->GL_GetAttribute = X11_GL_GetAttribute; | ||
160 | device->GL_MakeCurrent = X11_GL_MakeCurrent; | ||
161 | device->GL_SwapBuffers = X11_GL_SwapBuffers; | ||
162 | #endif | ||
163 | device->SetCaption = X11_SetCaption; | ||
164 | device->SetIcon = X11_SetIcon; | ||
165 | device->IconifyWindow = X11_IconifyWindow; | ||
166 | device->GrabInput = X11_GrabInput; | ||
167 | device->GetWMInfo = X11_GetWMInfo; | ||
168 | device->FreeWMCursor = X11_FreeWMCursor; | ||
169 | device->CreateWMCursor = X11_CreateWMCursor; | ||
170 | device->ShowWMCursor = X11_ShowWMCursor; | ||
171 | device->WarpWMCursor = X11_WarpWMCursor; | ||
172 | device->CheckMouseMode = X11_CheckMouseMode; | ||
173 | device->InitOSKeymap = X11_InitOSKeymap; | ||
174 | device->PumpEvents = X11_PumpEvents; | ||
175 | |||
176 | device->free = X11_DeleteDevice; | ||
177 | } | ||
178 | |||
179 | return device; | ||
180 | } | ||
181 | |||
182 | VideoBootStrap X11_bootstrap = { | ||
183 | "x11", "X Window System", | ||
184 | X11_Available, X11_CreateDevice | ||
185 | }; | ||
186 | |||
187 | /* Normal X11 error handler routine */ | ||
188 | static int (*X_handler)(Display *, XErrorEvent *) = NULL; | ||
189 | static int x_errhandler(Display *d, XErrorEvent *e) | ||
190 | { | ||
191 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
192 | extern int vm_error; | ||
193 | #endif | ||
194 | #if SDL_VIDEO_DRIVER_X11_DGAMOUSE | ||
195 | extern int dga_error; | ||
196 | #endif | ||
197 | |||
198 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
199 | /* VidMode errors are non-fatal. :) */ | ||
200 | /* Are the errors offset by one from the error base? | ||
201 | e.g. the error base is 143, the code is 148, and the | ||
202 | actual error is XF86VidModeExtensionDisabled (4) ? | ||
203 | */ | ||
204 | if ( (vm_error >= 0) && | ||
205 | (((e->error_code == BadRequest)&&(e->request_code == vm_error)) || | ||
206 | ((e->error_code > vm_error) && | ||
207 | (e->error_code <= (vm_error+XF86VidModeNumberErrors)))) ) { | ||
208 | #ifdef X11_DEBUG | ||
209 | { char errmsg[1024]; | ||
210 | XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg)); | ||
211 | printf("VidMode error: %s\n", errmsg); | ||
212 | } | ||
213 | #endif | ||
214 | return(0); | ||
215 | } | ||
216 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ | ||
217 | |||
218 | #if SDL_VIDEO_DRIVER_X11_DGAMOUSE | ||
219 | /* DGA errors can be non-fatal. :) */ | ||
220 | if ( (dga_error >= 0) && | ||
221 | ((e->error_code > dga_error) && | ||
222 | (e->error_code <= (dga_error+XF86DGANumberErrors))) ) { | ||
223 | #ifdef X11_DEBUG | ||
224 | { char errmsg[1024]; | ||
225 | XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg)); | ||
226 | printf("DGA error: %s\n", errmsg); | ||
227 | } | ||
228 | #endif | ||
229 | return(0); | ||
230 | } | ||
231 | #endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ | ||
232 | |||
233 | return(X_handler(d,e)); | ||
234 | } | ||
235 | |||
236 | /* X11 I/O error handler routine */ | ||
237 | static int (*XIO_handler)(Display *) = NULL; | ||
238 | static int xio_errhandler(Display *d) | ||
239 | { | ||
240 | /* Ack! Lost X11 connection! */ | ||
241 | |||
242 | /* We will crash if we try to clean up our display */ | ||
243 | if ( SDL_VideoSurface && current_video->hidden->Ximage ) { | ||
244 | SDL_VideoSurface->pixels = NULL; | ||
245 | } | ||
246 | current_video->hidden->X11_Display = NULL; | ||
247 | |||
248 | /* Continue with the standard X11 error handler */ | ||
249 | return(XIO_handler(d)); | ||
250 | } | ||
251 | |||
252 | static int (*Xext_handler)(Display *, _Xconst char *, _Xconst char *) = NULL; | ||
253 | static int xext_errhandler(Display *d, _Xconst char *ext, _Xconst char *reason) | ||
254 | { | ||
255 | #ifdef X11_DEBUG | ||
256 | printf("Xext error inside SDL (may be harmless):\n"); | ||
257 | printf(" Extension \"%s\" %s on display \"%s\".\n", | ||
258 | ext, reason, XDisplayString(d)); | ||
259 | #endif | ||
260 | |||
261 | if (SDL_strcmp(reason, "missing") == 0) { | ||
262 | /* | ||
263 | * Since the query itself, elsewhere, can handle a missing extension | ||
264 | * and the default behaviour in Xlib is to write to stderr, which | ||
265 | * generates unnecessary bug reports, we just ignore these. | ||
266 | */ | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | /* Everything else goes to the default handler... */ | ||
271 | return Xext_handler(d, ext, reason); | ||
272 | } | ||
273 | |||
274 | /* Find out what class name we should use */ | ||
275 | static char *get_classname(char *classname, int maxlen) | ||
276 | { | ||
277 | char *spot; | ||
278 | #if defined(__LINUX__) || defined(__FREEBSD__) | ||
279 | char procfile[1024]; | ||
280 | char linkfile[1024]; | ||
281 | int linksize; | ||
282 | #endif | ||
283 | |||
284 | /* First allow environment variable override */ | ||
285 | spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS"); | ||
286 | if ( spot ) { | ||
287 | SDL_strlcpy(classname, spot, maxlen); | ||
288 | return classname; | ||
289 | } | ||
290 | |||
291 | /* Next look at the application's executable name */ | ||
292 | #if defined(__LINUX__) || defined(__FREEBSD__) | ||
293 | #if defined(__LINUX__) | ||
294 | SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid()); | ||
295 | #elif defined(__FREEBSD__) | ||
296 | SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid()); | ||
297 | #else | ||
298 | #error Where can we find the executable name? | ||
299 | #endif | ||
300 | linksize = readlink(procfile, linkfile, sizeof(linkfile)-1); | ||
301 | if ( linksize > 0 ) { | ||
302 | linkfile[linksize] = '\0'; | ||
303 | spot = SDL_strrchr(linkfile, '/'); | ||
304 | if ( spot ) { | ||
305 | SDL_strlcpy(classname, spot+1, maxlen); | ||
306 | } else { | ||
307 | SDL_strlcpy(classname, linkfile, maxlen); | ||
308 | } | ||
309 | return classname; | ||
310 | } | ||
311 | #endif /* __LINUX__ */ | ||
312 | |||
313 | /* Finally use the default we've used forever */ | ||
314 | SDL_strlcpy(classname, "SDL_App", maxlen); | ||
315 | return classname; | ||
316 | } | ||
317 | |||
318 | /* Create auxiliary (toplevel) windows with the current visual */ | ||
319 | static void create_aux_windows(_THIS) | ||
320 | { | ||
321 | int x = 0, y = 0; | ||
322 | char classname[1024]; | ||
323 | XSetWindowAttributes xattr; | ||
324 | XWMHints *hints; | ||
325 | unsigned long app_event_mask; | ||
326 | int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen)); | ||
327 | |||
328 | /* Look up some useful Atoms */ | ||
329 | WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False); | ||
330 | |||
331 | /* Don't create any extra windows if we are being managed */ | ||
332 | if ( SDL_windowid ) { | ||
333 | FSwindow = 0; | ||
334 | WMwindow = SDL_strtol(SDL_windowid, NULL, 0); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | if(FSwindow) | ||
339 | XDestroyWindow(SDL_Display, FSwindow); | ||
340 | |||
341 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
342 | if ( use_xinerama ) { | ||
343 | x = xinerama_info.x_org; | ||
344 | y = xinerama_info.y_org; | ||
345 | } | ||
346 | #endif | ||
347 | xattr.override_redirect = True; | ||
348 | xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0; | ||
349 | xattr.border_pixel = 0; | ||
350 | xattr.colormap = SDL_XColorMap; | ||
351 | |||
352 | FSwindow = XCreateWindow(SDL_Display, SDL_Root, | ||
353 | x, y, 32, 32, 0, | ||
354 | this->hidden->depth, InputOutput, SDL_Visual, | ||
355 | CWOverrideRedirect | CWBackPixel | CWBorderPixel | ||
356 | | CWColormap, | ||
357 | &xattr); | ||
358 | |||
359 | XSelectInput(SDL_Display, FSwindow, StructureNotifyMask); | ||
360 | |||
361 | /* Tell KDE to keep the fullscreen window on top */ | ||
362 | { | ||
363 | XEvent ev; | ||
364 | long mask; | ||
365 | |||
366 | SDL_memset(&ev, 0, sizeof(ev)); | ||
367 | ev.xclient.type = ClientMessage; | ||
368 | ev.xclient.window = SDL_Root; | ||
369 | ev.xclient.message_type = XInternAtom(SDL_Display, | ||
370 | "KWM_KEEP_ON_TOP", False); | ||
371 | ev.xclient.format = 32; | ||
372 | ev.xclient.data.l[0] = FSwindow; | ||
373 | ev.xclient.data.l[1] = CurrentTime; | ||
374 | mask = SubstructureRedirectMask; | ||
375 | XSendEvent(SDL_Display, SDL_Root, False, mask, &ev); | ||
376 | } | ||
377 | |||
378 | hints = NULL; | ||
379 | if(WMwindow) { | ||
380 | /* All window attributes must survive the recreation */ | ||
381 | hints = XGetWMHints(SDL_Display, WMwindow); | ||
382 | XDestroyWindow(SDL_Display, WMwindow); | ||
383 | } | ||
384 | |||
385 | /* Create the window for windowed management */ | ||
386 | /* (reusing the xattr structure above) */ | ||
387 | WMwindow = XCreateWindow(SDL_Display, SDL_Root, | ||
388 | x, y, 32, 32, 0, | ||
389 | this->hidden->depth, InputOutput, SDL_Visual, | ||
390 | CWBackPixel | CWBorderPixel | CWColormap, | ||
391 | &xattr); | ||
392 | |||
393 | /* Set the input hints so we get keyboard input */ | ||
394 | if(!hints) { | ||
395 | hints = XAllocWMHints(); | ||
396 | hints->input = True; | ||
397 | hints->flags = InputHint; | ||
398 | } | ||
399 | XSetWMHints(SDL_Display, WMwindow, hints); | ||
400 | XFree(hints); | ||
401 | X11_SetCaptionNoLock(this, this->wm_title, this->wm_icon); | ||
402 | |||
403 | app_event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | ||
404 | | PropertyChangeMask | StructureNotifyMask | KeymapStateMask; | ||
405 | XSelectInput(SDL_Display, WMwindow, app_event_mask); | ||
406 | |||
407 | /* Set the class hints so we can get an icon (AfterStep) */ | ||
408 | get_classname(classname, sizeof(classname)); | ||
409 | { | ||
410 | XClassHint *classhints; | ||
411 | classhints = XAllocClassHint(); | ||
412 | if(classhints != NULL) { | ||
413 | classhints->res_name = classname; | ||
414 | classhints->res_class = classname; | ||
415 | XSetClassHint(SDL_Display, WMwindow, classhints); | ||
416 | XFree(classhints); | ||
417 | } | ||
418 | } | ||
419 | |||
420 | { | ||
421 | pid_t pid = getpid(); | ||
422 | char hostname[256]; | ||
423 | |||
424 | if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1) { | ||
425 | Atom _NET_WM_PID = XInternAtom(SDL_Display, "_NET_WM_PID", False); | ||
426 | Atom WM_CLIENT_MACHINE = XInternAtom(SDL_Display, "WM_CLIENT_MACHINE", False); | ||
427 | |||
428 | hostname[sizeof(hostname)-1] = '\0'; | ||
429 | XChangeProperty(SDL_Display, WMwindow, _NET_WM_PID, XA_CARDINAL, 32, | ||
430 | PropModeReplace, (unsigned char *)&pid, 1); | ||
431 | XChangeProperty(SDL_Display, WMwindow, WM_CLIENT_MACHINE, XA_STRING, 8, | ||
432 | PropModeReplace, (unsigned char *)hostname, SDL_strlen(hostname)); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | /* Setup the communication with the IM server */ | ||
437 | /* create_aux_windows may be called several times against the same | ||
438 | Display. We should reuse the SDL_IM if one has been opened for | ||
439 | the Display, so we should not simply reset SDL_IM here. */ | ||
440 | |||
441 | #ifdef X_HAVE_UTF8_STRING | ||
442 | if (SDL_X11_HAVE_UTF8) { | ||
443 | /* Discard obsolete resources if any. */ | ||
444 | if (SDL_IM != NULL && SDL_Display != XDisplayOfIM(SDL_IM)) { | ||
445 | /* Just a double check. I don't think this | ||
446 | code is ever executed. */ | ||
447 | SDL_SetError("display has changed while an IM is kept"); | ||
448 | if (SDL_IC) { | ||
449 | XUnsetICFocus(SDL_IC); | ||
450 | XDestroyIC(SDL_IC); | ||
451 | SDL_IC = NULL; | ||
452 | } | ||
453 | XCloseIM(SDL_IM); | ||
454 | SDL_IM = NULL; | ||
455 | } | ||
456 | |||
457 | /* Open an input method. */ | ||
458 | if (SDL_IM == NULL) { | ||
459 | char *old_locale = NULL, *old_modifiers = NULL; | ||
460 | const char *p; | ||
461 | size_t n; | ||
462 | /* I'm not comfortable to do locale setup | ||
463 | here. However, we need C library locale | ||
464 | (and xlib modifiers) to be set based on the | ||
465 | user's preference to use XIM, and many | ||
466 | existing game programs doesn't take care of | ||
467 | users' locale preferences, so someone other | ||
468 | than the game program should do it. | ||
469 | Moreover, ones say that some game programs | ||
470 | heavily rely on the C locale behaviour, | ||
471 | e.g., strcol()'s, and we can't change the C | ||
472 | library locale. Given the situation, I | ||
473 | couldn't find better place to do the | ||
474 | job... */ | ||
475 | |||
476 | /* Save the current (application program's) | ||
477 | locale settings. */ | ||
478 | p = setlocale(LC_ALL, NULL); | ||
479 | if ( p ) { | ||
480 | n = SDL_strlen(p)+1; | ||
481 | old_locale = SDL_stack_alloc(char, n); | ||
482 | if ( old_locale ) { | ||
483 | SDL_strlcpy(old_locale, p, n); | ||
484 | } | ||
485 | } | ||
486 | p = XSetLocaleModifiers(NULL); | ||
487 | if ( p ) { | ||
488 | n = SDL_strlen(p)+1; | ||
489 | old_modifiers = SDL_stack_alloc(char, n); | ||
490 | if ( old_modifiers ) { | ||
491 | SDL_strlcpy(old_modifiers, p, n); | ||
492 | } | ||
493 | } | ||
494 | |||
495 | /* Fetch the user's preferences and open the | ||
496 | input method with them. */ | ||
497 | setlocale(LC_ALL, ""); | ||
498 | XSetLocaleModifiers(""); | ||
499 | SDL_IM = XOpenIM(SDL_Display, NULL, classname, classname); | ||
500 | |||
501 | /* Restore the application's locale settings | ||
502 | so that we don't break the application's | ||
503 | expected behaviour. */ | ||
504 | if ( old_locale ) { | ||
505 | /* We need to restore the C library | ||
506 | locale first, since the | ||
507 | interpretation of the X modifier | ||
508 | may depend on it. */ | ||
509 | setlocale(LC_ALL, old_locale); | ||
510 | SDL_stack_free(old_locale); | ||
511 | } | ||
512 | if ( old_modifiers ) { | ||
513 | XSetLocaleModifiers(old_modifiers); | ||
514 | SDL_stack_free(old_modifiers); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | /* Create a new input context for the new window just created. */ | ||
519 | if (SDL_IM == NULL) { | ||
520 | SDL_SetError("no input method could be opened"); | ||
521 | } else { | ||
522 | if (SDL_IC != NULL) { | ||
523 | /* Discard the old IC before creating new one. */ | ||
524 | XUnsetICFocus(SDL_IC); | ||
525 | XDestroyIC(SDL_IC); | ||
526 | } | ||
527 | /* Theoretically we should check the current IM supports | ||
528 | PreeditNothing+StatusNothing style (i.e., root window method) | ||
529 | before creating the IC. However, it is the bottom line method, | ||
530 | and we supports any other options. If the IM didn't support | ||
531 | root window method, the following call fails, and SDL falls | ||
532 | back to pre-XIM keyboard handling. */ | ||
533 | SDL_IC = pXCreateIC(SDL_IM, | ||
534 | XNClientWindow, WMwindow, | ||
535 | XNFocusWindow, WMwindow, | ||
536 | XNInputStyle, XIMPreeditNothing | XIMStatusNothing, | ||
537 | XNResourceName, classname, | ||
538 | XNResourceClass, classname, | ||
539 | NULL); | ||
540 | |||
541 | if (SDL_IC == NULL) { | ||
542 | SDL_SetError("no input context could be created"); | ||
543 | XCloseIM(SDL_IM); | ||
544 | SDL_IM = NULL; | ||
545 | } else { | ||
546 | /* We need to receive X events that an IM wants and to pass | ||
547 | them to the IM through XFilterEvent. The set of events may | ||
548 | vary depending on the IM implementation and the options | ||
549 | specified through various routes. Although unlikely, the | ||
550 | xlib specification allows IM to change the event requirement | ||
551 | with its own circumstances, it is safe to call SelectInput | ||
552 | whenever we re-create an IC. */ | ||
553 | unsigned long mask = 0; | ||
554 | char *ret = pXGetICValues(SDL_IC, XNFilterEvents, &mask, NULL); | ||
555 | if (ret != NULL) { | ||
556 | XUnsetICFocus(SDL_IC); | ||
557 | XDestroyIC(SDL_IC); | ||
558 | SDL_IC = NULL; | ||
559 | SDL_SetError("no input context could be created"); | ||
560 | XCloseIM(SDL_IM); | ||
561 | SDL_IM = NULL; | ||
562 | } else { | ||
563 | XSelectInput(SDL_Display, WMwindow, app_event_mask | mask); | ||
564 | XSetICFocus(SDL_IC); | ||
565 | } | ||
566 | } | ||
567 | } | ||
568 | } | ||
569 | #endif | ||
570 | |||
571 | /* Allow the window to be deleted by the window manager */ | ||
572 | XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1); | ||
573 | } | ||
574 | |||
575 | static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat) | ||
576 | { | ||
577 | const char *env; | ||
578 | char *display; | ||
579 | int i; | ||
580 | |||
581 | /* Open the X11 display */ | ||
582 | display = NULL; /* Get it from DISPLAY environment variable */ | ||
583 | |||
584 | if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) || | ||
585 | (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) { | ||
586 | local_X11 = 1; | ||
587 | } else { | ||
588 | local_X11 = 0; | ||
589 | } | ||
590 | SDL_Display = XOpenDisplay(display); | ||
591 | #if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC) | ||
592 | /* On Tru64 if linking without -lX11, it fails and you get following message. | ||
593 | * Xlib: connection to ":0.0" refused by server | ||
594 | * Xlib: XDM authorization key matches an existing client! | ||
595 | * | ||
596 | * It succeeds if retrying 1 second later | ||
597 | * or if running xhost +localhost on shell. | ||
598 | * | ||
599 | */ | ||
600 | if ( SDL_Display == NULL ) { | ||
601 | SDL_Delay(1000); | ||
602 | SDL_Display = XOpenDisplay(display); | ||
603 | } | ||
604 | #endif | ||
605 | if ( SDL_Display == NULL ) { | ||
606 | SDL_SetError("Couldn't open X11 display"); | ||
607 | return(-1); | ||
608 | } | ||
609 | #ifdef X11_DEBUG | ||
610 | XSynchronize(SDL_Display, True); | ||
611 | #endif | ||
612 | |||
613 | /* Create an alternate X display for graphics updates -- allows us | ||
614 | to do graphics updates in a separate thread from event handling. | ||
615 | Thread-safe X11 doesn't seem to exist. | ||
616 | */ | ||
617 | GFX_Display = XOpenDisplay(display); | ||
618 | if ( GFX_Display == NULL ) { | ||
619 | XCloseDisplay(SDL_Display); | ||
620 | SDL_Display = NULL; | ||
621 | SDL_SetError("Couldn't open X11 display"); | ||
622 | return(-1); | ||
623 | } | ||
624 | |||
625 | /* Set the normal X error handler */ | ||
626 | X_handler = XSetErrorHandler(x_errhandler); | ||
627 | |||
628 | /* Set the error handler if we lose the X display */ | ||
629 | XIO_handler = XSetIOErrorHandler(xio_errhandler); | ||
630 | |||
631 | /* Set the X extension error handler */ | ||
632 | Xext_handler = XSetExtensionErrorHandler(xext_errhandler); | ||
633 | |||
634 | /* use default screen (from $DISPLAY) */ | ||
635 | SDL_Screen = DefaultScreen(SDL_Display); | ||
636 | |||
637 | #ifndef NO_SHARED_MEMORY | ||
638 | /* Check for MIT shared memory extension */ | ||
639 | use_mitshm = 0; | ||
640 | if ( local_X11 ) { | ||
641 | use_mitshm = XShmQueryExtension(SDL_Display); | ||
642 | } | ||
643 | #endif /* NO_SHARED_MEMORY */ | ||
644 | |||
645 | /* Get the available video modes */ | ||
646 | if(X11_GetVideoModes(this) < 0) { | ||
647 | XCloseDisplay(GFX_Display); | ||
648 | GFX_Display = NULL; | ||
649 | XCloseDisplay(SDL_Display); | ||
650 | SDL_Display = NULL; | ||
651 | return -1; | ||
652 | } | ||
653 | |||
654 | /* Determine the current screen size */ | ||
655 | this->info.current_w = DisplayWidth(SDL_Display, SDL_Screen); | ||
656 | this->info.current_h = DisplayHeight(SDL_Display, SDL_Screen); | ||
657 | |||
658 | /* Determine the default screen depth: | ||
659 | Use the default visual (or at least one with the same depth) */ | ||
660 | SDL_DisplayColormap = DefaultColormap(SDL_Display, SDL_Screen); | ||
661 | for(i = 0; i < this->hidden->nvisuals; i++) | ||
662 | if(this->hidden->visuals[i].depth == DefaultDepth(SDL_Display, | ||
663 | SDL_Screen)) | ||
664 | break; | ||
665 | if(i == this->hidden->nvisuals) { | ||
666 | /* default visual was useless, take the deepest one instead */ | ||
667 | i = 0; | ||
668 | } | ||
669 | SDL_Visual = this->hidden->visuals[i].visual; | ||
670 | if ( SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen) ) { | ||
671 | SDL_XColorMap = SDL_DisplayColormap; | ||
672 | } else { | ||
673 | SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, | ||
674 | SDL_Visual, AllocNone); | ||
675 | } | ||
676 | this->hidden->depth = this->hidden->visuals[i].depth; | ||
677 | vformat->BitsPerPixel = this->hidden->visuals[i].bpp; | ||
678 | if ( vformat->BitsPerPixel > 8 ) { | ||
679 | vformat->Rmask = SDL_Visual->red_mask; | ||
680 | vformat->Gmask = SDL_Visual->green_mask; | ||
681 | vformat->Bmask = SDL_Visual->blue_mask; | ||
682 | } | ||
683 | if ( this->hidden->depth == 32 ) { | ||
684 | vformat->Amask = (0xFFFFFFFF & ~(vformat->Rmask|vformat->Gmask|vformat->Bmask)); | ||
685 | } | ||
686 | X11_SaveVidModeGamma(this); | ||
687 | |||
688 | /* Allow environment override of screensaver disable. */ | ||
689 | env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); | ||
690 | if ( env ) { | ||
691 | allow_screensaver = SDL_atoi(env); | ||
692 | } else { | ||
693 | #ifdef SDL_VIDEO_DISABLE_SCREENSAVER | ||
694 | allow_screensaver = 0; | ||
695 | #else | ||
696 | allow_screensaver = 1; | ||
697 | #endif | ||
698 | } | ||
699 | |||
700 | /* See if we have been passed a window to use */ | ||
701 | SDL_windowid = SDL_getenv("SDL_WINDOWID"); | ||
702 | |||
703 | /* Create the fullscreen and managed windows */ | ||
704 | create_aux_windows(this); | ||
705 | |||
706 | /* Create the blank cursor */ | ||
707 | SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask, | ||
708 | BLANK_CWIDTH, BLANK_CHEIGHT, | ||
709 | BLANK_CHOTX, BLANK_CHOTY); | ||
710 | |||
711 | /* Fill in some window manager capabilities */ | ||
712 | this->info.wm_available = 1; | ||
713 | |||
714 | /* We're done! */ | ||
715 | XFlush(SDL_Display); | ||
716 | return(0); | ||
717 | } | ||
718 | |||
719 | static void X11_DestroyWindow(_THIS, SDL_Surface *screen) | ||
720 | { | ||
721 | /* Clean up OpenGL */ | ||
722 | if ( screen ) { | ||
723 | screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT); | ||
724 | } | ||
725 | X11_GL_Shutdown(this); | ||
726 | |||
727 | if ( ! SDL_windowid ) { | ||
728 | /* Hide the managed window */ | ||
729 | if ( WMwindow ) { | ||
730 | XUnmapWindow(SDL_Display, WMwindow); | ||
731 | } | ||
732 | if ( screen && (screen->flags & SDL_FULLSCREEN) ) { | ||
733 | screen->flags &= ~SDL_FULLSCREEN; | ||
734 | X11_LeaveFullScreen(this); | ||
735 | } | ||
736 | |||
737 | /* Destroy the output window */ | ||
738 | if ( SDL_Window ) { | ||
739 | XDestroyWindow(SDL_Display, SDL_Window); | ||
740 | } | ||
741 | |||
742 | /* Free the colormap entries */ | ||
743 | if ( SDL_XPixels ) { | ||
744 | int numcolors; | ||
745 | unsigned long pixel; | ||
746 | numcolors = SDL_Visual->map_entries; | ||
747 | for ( pixel=0; pixel<numcolors; ++pixel ) { | ||
748 | while ( SDL_XPixels[pixel] > 0 ) { | ||
749 | XFreeColors(GFX_Display, | ||
750 | SDL_DisplayColormap,&pixel,1,0); | ||
751 | --SDL_XPixels[pixel]; | ||
752 | } | ||
753 | } | ||
754 | SDL_free(SDL_XPixels); | ||
755 | SDL_XPixels = NULL; | ||
756 | } | ||
757 | |||
758 | /* Free the graphics context */ | ||
759 | if ( SDL_GC ) { | ||
760 | XFreeGC(SDL_Display, SDL_GC); | ||
761 | SDL_GC = 0; | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 | static SDL_bool X11_WindowPosition(_THIS, int *x, int *y, int w, int h) | ||
767 | { | ||
768 | const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); | ||
769 | const char *center = SDL_getenv("SDL_VIDEO_CENTERED"); | ||
770 | if ( window ) { | ||
771 | if ( SDL_sscanf(window, "%d,%d", x, y) == 2 ) { | ||
772 | return SDL_TRUE; | ||
773 | } | ||
774 | if ( SDL_strcmp(window, "center") == 0 ) { | ||
775 | center = window; | ||
776 | } | ||
777 | } | ||
778 | if ( center ) { | ||
779 | *x = (DisplayWidth(SDL_Display, SDL_Screen) - w)/2; | ||
780 | *y = (DisplayHeight(SDL_Display, SDL_Screen) - h)/2; | ||
781 | return SDL_TRUE; | ||
782 | } | ||
783 | return SDL_FALSE; | ||
784 | } | ||
785 | |||
786 | static void X11_SetSizeHints(_THIS, int w, int h, Uint32 flags) | ||
787 | { | ||
788 | XSizeHints *hints; | ||
789 | |||
790 | hints = XAllocSizeHints(); | ||
791 | if ( hints ) { | ||
792 | if (!(flags & SDL_RESIZABLE)) { | ||
793 | hints->min_width = hints->max_width = w; | ||
794 | hints->min_height = hints->max_height = h; | ||
795 | hints->flags = PMaxSize | PMinSize; | ||
796 | } | ||
797 | if ( flags & SDL_FULLSCREEN ) { | ||
798 | hints->x = 0; | ||
799 | hints->y = 0; | ||
800 | hints->flags |= USPosition; | ||
801 | } else | ||
802 | /* Center it, if desired */ | ||
803 | if ( X11_WindowPosition(this, &hints->x, &hints->y, w, h) ) { | ||
804 | hints->flags |= USPosition; | ||
805 | |||
806 | /* Hints must be set before moving the window, otherwise an | ||
807 | unwanted ConfigureNotify event will be issued */ | ||
808 | XSetWMNormalHints(SDL_Display, WMwindow, hints); | ||
809 | |||
810 | XMoveWindow(SDL_Display, WMwindow, hints->x, hints->y); | ||
811 | |||
812 | /* Flush the resize event so we don't catch it later */ | ||
813 | XSync(SDL_Display, True); | ||
814 | } | ||
815 | XSetWMNormalHints(SDL_Display, WMwindow, hints); | ||
816 | XFree(hints); | ||
817 | } | ||
818 | |||
819 | /* Respect the window caption style */ | ||
820 | if ( flags & SDL_NOFRAME ) { | ||
821 | SDL_bool set; | ||
822 | Atom WM_HINTS; | ||
823 | |||
824 | /* We haven't modified the window manager hints yet */ | ||
825 | set = SDL_FALSE; | ||
826 | |||
827 | /* First try to set MWM hints */ | ||
828 | WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True); | ||
829 | if ( WM_HINTS != None ) { | ||
830 | /* Hints used by Motif compliant window managers */ | ||
831 | struct { | ||
832 | unsigned long flags; | ||
833 | unsigned long functions; | ||
834 | unsigned long decorations; | ||
835 | long input_mode; | ||
836 | unsigned long status; | ||
837 | } MWMHints = { (1L << 1), 0, 0, 0, 0 }; | ||
838 | |||
839 | XChangeProperty(SDL_Display, WMwindow, | ||
840 | WM_HINTS, WM_HINTS, 32, | ||
841 | PropModeReplace, | ||
842 | (unsigned char *)&MWMHints, | ||
843 | sizeof(MWMHints)/sizeof(long)); | ||
844 | set = SDL_TRUE; | ||
845 | } | ||
846 | /* Now try to set KWM hints */ | ||
847 | WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True); | ||
848 | if ( WM_HINTS != None ) { | ||
849 | long KWMHints = 0; | ||
850 | |||
851 | XChangeProperty(SDL_Display, WMwindow, | ||
852 | WM_HINTS, WM_HINTS, 32, | ||
853 | PropModeReplace, | ||
854 | (unsigned char *)&KWMHints, | ||
855 | sizeof(KWMHints)/sizeof(long)); | ||
856 | set = SDL_TRUE; | ||
857 | } | ||
858 | /* Now try to set GNOME hints */ | ||
859 | WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True); | ||
860 | if ( WM_HINTS != None ) { | ||
861 | long GNOMEHints = 0; | ||
862 | |||
863 | XChangeProperty(SDL_Display, WMwindow, | ||
864 | WM_HINTS, WM_HINTS, 32, | ||
865 | PropModeReplace, | ||
866 | (unsigned char *)&GNOMEHints, | ||
867 | sizeof(GNOMEHints)/sizeof(long)); | ||
868 | set = SDL_TRUE; | ||
869 | } | ||
870 | /* Finally set the transient hints if necessary */ | ||
871 | if ( ! set ) { | ||
872 | XSetTransientForHint(SDL_Display, WMwindow, SDL_Root); | ||
873 | } | ||
874 | } else { | ||
875 | SDL_bool set; | ||
876 | Atom WM_HINTS; | ||
877 | |||
878 | /* We haven't modified the window manager hints yet */ | ||
879 | set = SDL_FALSE; | ||
880 | |||
881 | /* First try to unset MWM hints */ | ||
882 | WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True); | ||
883 | if ( WM_HINTS != None ) { | ||
884 | XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); | ||
885 | set = SDL_TRUE; | ||
886 | } | ||
887 | /* Now try to unset KWM hints */ | ||
888 | WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True); | ||
889 | if ( WM_HINTS != None ) { | ||
890 | XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); | ||
891 | set = SDL_TRUE; | ||
892 | } | ||
893 | /* Now try to unset GNOME hints */ | ||
894 | WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True); | ||
895 | if ( WM_HINTS != None ) { | ||
896 | XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); | ||
897 | set = SDL_TRUE; | ||
898 | } | ||
899 | /* Finally unset the transient hints if necessary */ | ||
900 | if ( ! set ) { | ||
901 | XDeleteProperty(SDL_Display, WMwindow, XA_WM_TRANSIENT_FOR); | ||
902 | } | ||
903 | } | ||
904 | } | ||
905 | |||
906 | static int X11_CreateWindow(_THIS, SDL_Surface *screen, | ||
907 | int w, int h, int bpp, Uint32 flags) | ||
908 | { | ||
909 | int i, depth; | ||
910 | Visual *vis; | ||
911 | int vis_change; | ||
912 | Uint32 Amask; | ||
913 | |||
914 | /* If a window is already present, destroy it and start fresh */ | ||
915 | if ( SDL_Window ) { | ||
916 | X11_DestroyWindow(this, screen); | ||
917 | switch_waiting = 0; /* Prevent jump back to now-meaningless state. */ | ||
918 | } | ||
919 | |||
920 | /* See if we have been given a window id */ | ||
921 | if ( SDL_windowid ) { | ||
922 | SDL_Window = SDL_strtol(SDL_windowid, NULL, 0); | ||
923 | } else { | ||
924 | SDL_Window = 0; | ||
925 | } | ||
926 | |||
927 | /* find out which visual we are going to use */ | ||
928 | if ( flags & SDL_OPENGL ) { | ||
929 | XVisualInfo *vi; | ||
930 | |||
931 | vi = X11_GL_GetVisual(this); | ||
932 | if( !vi ) { | ||
933 | return -1; | ||
934 | } | ||
935 | vis = vi->visual; | ||
936 | depth = vi->depth; | ||
937 | } else if ( SDL_windowid ) { | ||
938 | XWindowAttributes a; | ||
939 | |||
940 | XGetWindowAttributes(SDL_Display, SDL_Window, &a); | ||
941 | vis = a.visual; | ||
942 | depth = a.depth; | ||
943 | } else { | ||
944 | for ( i = 0; i < this->hidden->nvisuals; i++ ) { | ||
945 | if ( this->hidden->visuals[i].bpp == bpp ) | ||
946 | break; | ||
947 | } | ||
948 | if ( i == this->hidden->nvisuals ) { | ||
949 | SDL_SetError("No matching visual for requested depth"); | ||
950 | return -1; /* should never happen */ | ||
951 | } | ||
952 | vis = this->hidden->visuals[i].visual; | ||
953 | depth = this->hidden->visuals[i].depth; | ||
954 | } | ||
955 | #ifdef X11_DEBUG | ||
956 | 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); | ||
957 | #endif | ||
958 | vis_change = (vis != SDL_Visual); | ||
959 | SDL_Visual = vis; | ||
960 | this->hidden->depth = depth; | ||
961 | |||
962 | /* Allocate the new pixel format for this video mode */ | ||
963 | if ( this->hidden->depth == 32 ) { | ||
964 | Amask = (0xFFFFFFFF & ~(vis->red_mask|vis->green_mask|vis->blue_mask)); | ||
965 | } else { | ||
966 | Amask = 0; | ||
967 | } | ||
968 | if ( ! SDL_ReallocFormat(screen, bpp, | ||
969 | vis->red_mask, vis->green_mask, vis->blue_mask, Amask) ) { | ||
970 | return -1; | ||
971 | } | ||
972 | |||
973 | /* Create the appropriate colormap */ | ||
974 | if ( SDL_XColorMap != SDL_DisplayColormap ) { | ||
975 | XFreeColormap(SDL_Display, SDL_XColorMap); | ||
976 | } | ||
977 | if ( SDL_Visual->class == PseudoColor ) { | ||
978 | int ncolors; | ||
979 | |||
980 | /* Allocate the pixel flags */ | ||
981 | ncolors = SDL_Visual->map_entries; | ||
982 | SDL_XPixels = SDL_malloc(ncolors * sizeof(int)); | ||
983 | if(SDL_XPixels == NULL) { | ||
984 | SDL_OutOfMemory(); | ||
985 | return -1; | ||
986 | } | ||
987 | SDL_memset(SDL_XPixels, 0, ncolors * sizeof(*SDL_XPixels)); | ||
988 | |||
989 | /* always allocate a private colormap on non-default visuals */ | ||
990 | if ( SDL_Visual != DefaultVisual(SDL_Display, SDL_Screen) ) { | ||
991 | flags |= SDL_HWPALETTE; | ||
992 | } | ||
993 | if ( flags & SDL_HWPALETTE ) { | ||
994 | screen->flags |= SDL_HWPALETTE; | ||
995 | SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, | ||
996 | SDL_Visual, AllocAll); | ||
997 | } else { | ||
998 | SDL_XColorMap = SDL_DisplayColormap; | ||
999 | } | ||
1000 | } else if ( SDL_Visual->class == DirectColor ) { | ||
1001 | |||
1002 | /* Create a colormap which we can manipulate for gamma */ | ||
1003 | SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, | ||
1004 | SDL_Visual, AllocAll); | ||
1005 | XSync(SDL_Display, False); | ||
1006 | |||
1007 | /* Initialize the colormap to the identity mapping */ | ||
1008 | SDL_GetGammaRamp(0, 0, 0); | ||
1009 | this->screen = screen; | ||
1010 | X11_SetGammaRamp(this, this->gamma); | ||
1011 | this->screen = NULL; | ||
1012 | } else { | ||
1013 | /* Create a read-only colormap for our window */ | ||
1014 | SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, | ||
1015 | SDL_Visual, AllocNone); | ||
1016 | } | ||
1017 | |||
1018 | /* Recreate the auxiliary windows, if needed (required for GL) */ | ||
1019 | if ( vis_change ) | ||
1020 | create_aux_windows(this); | ||
1021 | |||
1022 | if(screen->flags & SDL_HWPALETTE) { | ||
1023 | /* Since the full-screen window might have got a nonzero background | ||
1024 | colour (0 is white on some displays), we should reset the | ||
1025 | background to 0 here since that is what the user expects | ||
1026 | with a private colormap */ | ||
1027 | XSetWindowBackground(SDL_Display, FSwindow, 0); | ||
1028 | XClearWindow(SDL_Display, FSwindow); | ||
1029 | } | ||
1030 | |||
1031 | /* resize the (possibly new) window manager window */ | ||
1032 | if( !SDL_windowid ) { | ||
1033 | X11_SetSizeHints(this, w, h, flags); | ||
1034 | window_w = w; | ||
1035 | window_h = h; | ||
1036 | XResizeWindow(SDL_Display, WMwindow, w, h); | ||
1037 | } | ||
1038 | |||
1039 | /* Create (or use) the X11 display window */ | ||
1040 | if ( !SDL_windowid ) { | ||
1041 | if ( flags & SDL_OPENGL ) { | ||
1042 | if ( X11_GL_CreateWindow(this, w, h) < 0 ) { | ||
1043 | return(-1); | ||
1044 | } | ||
1045 | } else { | ||
1046 | XSetWindowAttributes swa; | ||
1047 | |||
1048 | swa.background_pixel = 0; | ||
1049 | swa.border_pixel = 0; | ||
1050 | swa.colormap = SDL_XColorMap; | ||
1051 | SDL_Window = XCreateWindow(SDL_Display, WMwindow, | ||
1052 | 0, 0, w, h, 0, depth, | ||
1053 | InputOutput, SDL_Visual, | ||
1054 | CWBackPixel | CWBorderPixel | ||
1055 | | CWColormap, &swa); | ||
1056 | } | ||
1057 | /* Only manage our input if we own the window */ | ||
1058 | XSelectInput(SDL_Display, SDL_Window, | ||
1059 | ( EnterWindowMask | LeaveWindowMask | ||
1060 | | ButtonPressMask | ButtonReleaseMask | ||
1061 | | PointerMotionMask | ExposureMask )); | ||
1062 | } | ||
1063 | /* Create the graphics context here, once we have a window */ | ||
1064 | if ( flags & SDL_OPENGL ) { | ||
1065 | if ( X11_GL_CreateContext(this) < 0 ) { | ||
1066 | return(-1); | ||
1067 | } else { | ||
1068 | screen->flags |= SDL_OPENGL; | ||
1069 | } | ||
1070 | } else { | ||
1071 | XGCValues gcv; | ||
1072 | |||
1073 | gcv.graphics_exposures = False; | ||
1074 | SDL_GC = XCreateGC(SDL_Display, SDL_Window, | ||
1075 | GCGraphicsExposures, &gcv); | ||
1076 | if ( ! SDL_GC ) { | ||
1077 | SDL_SetError("Couldn't create graphics context"); | ||
1078 | return(-1); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | /* Set our colormaps when not setting a GL mode */ | ||
1083 | if ( ! (flags & SDL_OPENGL) ) { | ||
1084 | XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); | ||
1085 | if( !SDL_windowid ) { | ||
1086 | XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap); | ||
1087 | XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap); | ||
1088 | } | ||
1089 | } | ||
1090 | |||
1091 | #if 0 /* This is an experiment - are the graphics faster now? - nope. */ | ||
1092 | if ( SDL_getenv("SDL_VIDEO_X11_BACKINGSTORE") ) | ||
1093 | #endif | ||
1094 | /* Cache the window in the server, when possible */ | ||
1095 | { | ||
1096 | Screen *xscreen; | ||
1097 | XSetWindowAttributes a; | ||
1098 | |||
1099 | xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen); | ||
1100 | a.backing_store = DoesBackingStore(xscreen); | ||
1101 | if ( a.backing_store != NotUseful ) { | ||
1102 | XChangeWindowAttributes(SDL_Display, SDL_Window, | ||
1103 | CWBackingStore, &a); | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | /* Map them both and go fullscreen, if requested */ | ||
1108 | if ( ! SDL_windowid ) { | ||
1109 | XMapWindow(SDL_Display, SDL_Window); | ||
1110 | XMapWindow(SDL_Display, WMwindow); | ||
1111 | X11_WaitMapped(this, WMwindow); | ||
1112 | if ( flags & SDL_FULLSCREEN ) { | ||
1113 | screen->flags |= SDL_FULLSCREEN; | ||
1114 | X11_EnterFullScreen(this); | ||
1115 | } else { | ||
1116 | screen->flags &= ~SDL_FULLSCREEN; | ||
1117 | } | ||
1118 | } | ||
1119 | |||
1120 | return(0); | ||
1121 | } | ||
1122 | |||
1123 | static int X11_ResizeWindow(_THIS, | ||
1124 | SDL_Surface *screen, int w, int h, Uint32 flags) | ||
1125 | { | ||
1126 | if ( ! SDL_windowid ) { | ||
1127 | /* Resize the window manager window */ | ||
1128 | X11_SetSizeHints(this, w, h, flags); | ||
1129 | window_w = w; | ||
1130 | window_h = h; | ||
1131 | XResizeWindow(SDL_Display, WMwindow, w, h); | ||
1132 | |||
1133 | /* Resize the fullscreen and display windows */ | ||
1134 | if ( flags & SDL_FULLSCREEN ) { | ||
1135 | if ( screen->flags & SDL_FULLSCREEN ) { | ||
1136 | X11_ResizeFullScreen(this); | ||
1137 | } else { | ||
1138 | screen->flags |= SDL_FULLSCREEN; | ||
1139 | X11_EnterFullScreen(this); | ||
1140 | } | ||
1141 | } else { | ||
1142 | if ( screen->flags & SDL_FULLSCREEN ) { | ||
1143 | screen->flags &= ~SDL_FULLSCREEN; | ||
1144 | X11_LeaveFullScreen(this); | ||
1145 | } | ||
1146 | } | ||
1147 | XResizeWindow(SDL_Display, SDL_Window, w, h); | ||
1148 | } | ||
1149 | return(0); | ||
1150 | } | ||
1151 | |||
1152 | SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, | ||
1153 | int width, int height, int bpp, Uint32 flags) | ||
1154 | { | ||
1155 | Uint32 saved_flags; | ||
1156 | |||
1157 | /* Lock the event thread, in multi-threading environments */ | ||
1158 | SDL_Lock_EventThread(); | ||
1159 | |||
1160 | /* Check the combination of flags we were passed */ | ||
1161 | if ( flags & SDL_FULLSCREEN ) { | ||
1162 | /* Clear fullscreen flag if not supported */ | ||
1163 | if ( SDL_windowid ) { | ||
1164 | flags &= ~SDL_FULLSCREEN; | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | /* Flush any delayed updates */ | ||
1169 | XSync(GFX_Display, False); | ||
1170 | |||
1171 | /* Set up the X11 window */ | ||
1172 | saved_flags = current->flags; | ||
1173 | if ( (SDL_Window) && ((saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)) | ||
1174 | && (bpp == current->format->BitsPerPixel) | ||
1175 | && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) { | ||
1176 | if (X11_ResizeWindow(this, current, width, height, flags) < 0) { | ||
1177 | current = NULL; | ||
1178 | goto done; | ||
1179 | } | ||
1180 | X11_PendingConfigureNotifyWidth = width; | ||
1181 | X11_PendingConfigureNotifyHeight = height; | ||
1182 | } else { | ||
1183 | if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) { | ||
1184 | current = NULL; | ||
1185 | goto done; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | /* Update the internal keyboard state */ | ||
1190 | X11_SetKeyboardState(SDL_Display, NULL); | ||
1191 | |||
1192 | /* When the window is first mapped, ignore non-modifier keys */ | ||
1193 | if ( !current->w && !current->h ) { | ||
1194 | Uint8 *keys = SDL_GetKeyState(NULL); | ||
1195 | int i; | ||
1196 | for ( i = 0; i < SDLK_LAST; ++i ) { | ||
1197 | switch (i) { | ||
1198 | case SDLK_NUMLOCK: | ||
1199 | case SDLK_CAPSLOCK: | ||
1200 | case SDLK_LCTRL: | ||
1201 | case SDLK_RCTRL: | ||
1202 | case SDLK_LSHIFT: | ||
1203 | case SDLK_RSHIFT: | ||
1204 | case SDLK_LALT: | ||
1205 | case SDLK_RALT: | ||
1206 | case SDLK_LMETA: | ||
1207 | case SDLK_RMETA: | ||
1208 | case SDLK_MODE: | ||
1209 | break; | ||
1210 | default: | ||
1211 | keys[i] = SDL_RELEASED; | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | } | ||
1216 | |||
1217 | /* Set up the new mode framebuffer */ | ||
1218 | if ( ((current->w != width) || (current->h != height)) || | ||
1219 | ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { | ||
1220 | current->w = width; | ||
1221 | current->h = height; | ||
1222 | current->pitch = SDL_CalculatePitch(current); | ||
1223 | if (X11_ResizeImage(this, current, flags) < 0) { | ||
1224 | current = NULL; | ||
1225 | goto done; | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1229 | /* Clear these flags and set them only if they are in the new set. */ | ||
1230 | current->flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); | ||
1231 | current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME)); | ||
1232 | |||
1233 | done: | ||
1234 | /* Release the event thread */ | ||
1235 | XSync(SDL_Display, False); | ||
1236 | SDL_Unlock_EventThread(); | ||
1237 | |||
1238 | /* We're done! */ | ||
1239 | return(current); | ||
1240 | } | ||
1241 | |||
1242 | static int X11_ToggleFullScreen(_THIS, int on) | ||
1243 | { | ||
1244 | Uint32 event_thread; | ||
1245 | |||
1246 | /* Don't switch if we don't own the window */ | ||
1247 | if ( SDL_windowid ) { | ||
1248 | return(0); | ||
1249 | } | ||
1250 | |||
1251 | /* Don't lock if we are the event thread */ | ||
1252 | event_thread = SDL_EventThreadID(); | ||
1253 | if ( event_thread && (SDL_ThreadID() == event_thread) ) { | ||
1254 | event_thread = 0; | ||
1255 | } | ||
1256 | if ( event_thread ) { | ||
1257 | SDL_Lock_EventThread(); | ||
1258 | } | ||
1259 | if ( on ) { | ||
1260 | this->screen->flags |= SDL_FULLSCREEN; | ||
1261 | X11_EnterFullScreen(this); | ||
1262 | } else { | ||
1263 | this->screen->flags &= ~SDL_FULLSCREEN; | ||
1264 | X11_LeaveFullScreen(this); | ||
1265 | } | ||
1266 | X11_RefreshDisplay(this); | ||
1267 | if ( event_thread ) { | ||
1268 | SDL_Unlock_EventThread(); | ||
1269 | } | ||
1270 | SDL_ResetKeyboard(); | ||
1271 | return(1); | ||
1272 | } | ||
1273 | |||
1274 | /* Update the current mouse state and position */ | ||
1275 | static void X11_UpdateMouse(_THIS) | ||
1276 | { | ||
1277 | Window u1; int u2; | ||
1278 | Window current_win; | ||
1279 | int x, y; | ||
1280 | unsigned int mask; | ||
1281 | |||
1282 | /* Lock the event thread, in multi-threading environments */ | ||
1283 | SDL_Lock_EventThread(); | ||
1284 | if ( XQueryPointer(SDL_Display, SDL_Window, &u1, ¤t_win, | ||
1285 | &u2, &u2, &x, &y, &mask) ) { | ||
1286 | if ( (x >= 0) && (x < SDL_VideoSurface->w) && | ||
1287 | (y >= 0) && (y < SDL_VideoSurface->h) ) { | ||
1288 | SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); | ||
1289 | SDL_PrivateMouseMotion(0, 0, x, y); | ||
1290 | } else { | ||
1291 | SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); | ||
1292 | } | ||
1293 | } | ||
1294 | SDL_Unlock_EventThread(); | ||
1295 | } | ||
1296 | |||
1297 | /* simple colour distance metric. Supposed to be better than a plain | ||
1298 | Euclidian distance anyway. */ | ||
1299 | #define COLOUR_FACTOR 3 | ||
1300 | #define LIGHT_FACTOR 1 | ||
1301 | #define COLOUR_DIST(r1, g1, b1, r2, g2, b2) \ | ||
1302 | (COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2)) \ | ||
1303 | + LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2))) | ||
1304 | |||
1305 | static void allocate_nearest(_THIS, SDL_Color *colors, | ||
1306 | SDL_Color *want, int nwant) | ||
1307 | { | ||
1308 | /* | ||
1309 | * There is no way to know which ones to choose from, so we retrieve | ||
1310 | * the entire colormap and try the nearest possible, until we find one | ||
1311 | * that is shared. | ||
1312 | */ | ||
1313 | XColor all[256]; | ||
1314 | int i; | ||
1315 | for(i = 0; i < 256; i++) | ||
1316 | all[i].pixel = i; | ||
1317 | /* | ||
1318 | * XQueryColors sets the flags in the XColor struct, so we use | ||
1319 | * that to keep track of which colours are available | ||
1320 | */ | ||
1321 | XQueryColors(GFX_Display, SDL_XColorMap, all, 256); | ||
1322 | |||
1323 | for(i = 0; i < nwant; i++) { | ||
1324 | XColor *c; | ||
1325 | int j; | ||
1326 | int best = 0; | ||
1327 | int mindist = 0x7fffffff; | ||
1328 | int ri = want[i].r; | ||
1329 | int gi = want[i].g; | ||
1330 | int bi = want[i].b; | ||
1331 | for(j = 0; j < 256; j++) { | ||
1332 | int rj, gj, bj, d2; | ||
1333 | if(!all[j].flags) | ||
1334 | continue; /* unavailable colour cell */ | ||
1335 | rj = all[j].red >> 8; | ||
1336 | gj = all[j].green >> 8; | ||
1337 | bj = all[j].blue >> 8; | ||
1338 | d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj); | ||
1339 | if(d2 < mindist) { | ||
1340 | mindist = d2; | ||
1341 | best = j; | ||
1342 | } | ||
1343 | } | ||
1344 | if(SDL_XPixels[best]) | ||
1345 | continue; /* already allocated, waste no more time */ | ||
1346 | c = all + best; | ||
1347 | if(XAllocColor(GFX_Display, SDL_XColorMap, c)) { | ||
1348 | /* got it */ | ||
1349 | colors[c->pixel].r = c->red >> 8; | ||
1350 | colors[c->pixel].g = c->green >> 8; | ||
1351 | colors[c->pixel].b = c->blue >> 8; | ||
1352 | ++SDL_XPixels[c->pixel]; | ||
1353 | } else { | ||
1354 | /* | ||
1355 | * The colour couldn't be allocated, probably being | ||
1356 | * owned as a r/w cell by another client. Flag it as | ||
1357 | * unavailable and try again. The termination of the | ||
1358 | * loop is guaranteed since at least black and white | ||
1359 | * are always there. | ||
1360 | */ | ||
1361 | c->flags = 0; | ||
1362 | i--; | ||
1363 | } | ||
1364 | } | ||
1365 | } | ||
1366 | |||
1367 | int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | ||
1368 | { | ||
1369 | int nrej = 0; | ||
1370 | |||
1371 | /* Check to make sure we have a colormap allocated */ | ||
1372 | if ( SDL_XPixels == NULL ) { | ||
1373 | return(0); | ||
1374 | } | ||
1375 | if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) { | ||
1376 | /* private writable colormap: just set the colours we need */ | ||
1377 | XColor *xcmap; | ||
1378 | int i; | ||
1379 | xcmap = SDL_stack_alloc(XColor, ncolors); | ||
1380 | if(xcmap == NULL) | ||
1381 | return 0; | ||
1382 | for ( i=0; i<ncolors; ++i ) { | ||
1383 | xcmap[i].pixel = i + firstcolor; | ||
1384 | xcmap[i].red = (colors[i].r<<8)|colors[i].r; | ||
1385 | xcmap[i].green = (colors[i].g<<8)|colors[i].g; | ||
1386 | xcmap[i].blue = (colors[i].b<<8)|colors[i].b; | ||
1387 | xcmap[i].flags = (DoRed|DoGreen|DoBlue); | ||
1388 | } | ||
1389 | XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); | ||
1390 | XSync(GFX_Display, False); | ||
1391 | SDL_stack_free(xcmap); | ||
1392 | } else { | ||
1393 | /* | ||
1394 | * Shared colormap: We only allocate read-only cells, which | ||
1395 | * increases the likelyhood of colour sharing with other | ||
1396 | * clients. The pixel values will almost certainly be | ||
1397 | * different from the requested ones, so the user has to | ||
1398 | * walk the colormap and see which index got what colour. | ||
1399 | * | ||
1400 | * We can work directly with the logical palette since it | ||
1401 | * has already been set when we get here. | ||
1402 | */ | ||
1403 | SDL_Color *want, *reject; | ||
1404 | unsigned long *freelist; | ||
1405 | int i; | ||
1406 | int nfree = 0; | ||
1407 | int nc = this->screen->format->palette->ncolors; | ||
1408 | colors = this->screen->format->palette->colors; | ||
1409 | freelist = SDL_stack_alloc(unsigned long, nc); | ||
1410 | /* make sure multiple allocations of the same cell are freed */ | ||
1411 | for(i = 0; i < ncolors; i++) { | ||
1412 | int pixel = firstcolor + i; | ||
1413 | while(SDL_XPixels[pixel]) { | ||
1414 | freelist[nfree++] = pixel; | ||
1415 | --SDL_XPixels[pixel]; | ||
1416 | } | ||
1417 | } | ||
1418 | XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0); | ||
1419 | SDL_stack_free(freelist); | ||
1420 | |||
1421 | want = SDL_stack_alloc(SDL_Color, ncolors); | ||
1422 | reject = SDL_stack_alloc(SDL_Color, ncolors); | ||
1423 | SDL_memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color)); | ||
1424 | /* make sure the user isn't fooled by her own wishes | ||
1425 | (black is safe, always available in the default colormap) */ | ||
1426 | SDL_memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color)); | ||
1427 | |||
1428 | /* now try to allocate the colours */ | ||
1429 | for(i = 0; i < ncolors; i++) { | ||
1430 | XColor col; | ||
1431 | col.red = want[i].r << 8; | ||
1432 | col.green = want[i].g << 8; | ||
1433 | col.blue = want[i].b << 8; | ||
1434 | col.flags = DoRed | DoGreen | DoBlue; | ||
1435 | if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) { | ||
1436 | /* We got the colour, or at least the nearest | ||
1437 | the hardware could get. */ | ||
1438 | colors[col.pixel].r = col.red >> 8; | ||
1439 | colors[col.pixel].g = col.green >> 8; | ||
1440 | colors[col.pixel].b = col.blue >> 8; | ||
1441 | ++SDL_XPixels[col.pixel]; | ||
1442 | } else { | ||
1443 | /* | ||
1444 | * no more free cells, add it to the list | ||
1445 | * of rejected colours | ||
1446 | */ | ||
1447 | reject[nrej++] = want[i]; | ||
1448 | } | ||
1449 | } | ||
1450 | if(nrej) | ||
1451 | allocate_nearest(this, colors, reject, nrej); | ||
1452 | SDL_stack_free(reject); | ||
1453 | SDL_stack_free(want); | ||
1454 | } | ||
1455 | return nrej == 0; | ||
1456 | } | ||
1457 | |||
1458 | int X11_SetGammaRamp(_THIS, Uint16 *ramp) | ||
1459 | { | ||
1460 | int i, ncolors; | ||
1461 | XColor xcmap[256]; | ||
1462 | |||
1463 | /* See if actually setting the gamma is supported */ | ||
1464 | if ( SDL_Visual->class != DirectColor ) { | ||
1465 | SDL_SetError("Gamma correction not supported on this visual"); | ||
1466 | return(-1); | ||
1467 | } | ||
1468 | |||
1469 | /* Calculate the appropriate palette for the given gamma ramp */ | ||
1470 | ncolors = SDL_Visual->map_entries; | ||
1471 | for ( i=0; i<ncolors; ++i ) { | ||
1472 | Uint8 c = (256 * i / ncolors); | ||
1473 | xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c); | ||
1474 | xcmap[i].red = ramp[0*256+c]; | ||
1475 | xcmap[i].green = ramp[1*256+c]; | ||
1476 | xcmap[i].blue = ramp[2*256+c]; | ||
1477 | xcmap[i].flags = (DoRed|DoGreen|DoBlue); | ||
1478 | } | ||
1479 | XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); | ||
1480 | XSync(GFX_Display, False); | ||
1481 | return(0); | ||
1482 | } | ||
1483 | |||
1484 | /* Note: If we are terminated, this could be called in the middle of | ||
1485 | another SDL video routine -- notably UpdateRects. | ||
1486 | */ | ||
1487 | void X11_VideoQuit(_THIS) | ||
1488 | { | ||
1489 | /* Shutdown everything that's still up */ | ||
1490 | /* The event thread should be done, so we can touch SDL_Display */ | ||
1491 | if ( SDL_Display != NULL ) { | ||
1492 | /* Flush any delayed updates */ | ||
1493 | XSync(GFX_Display, False); | ||
1494 | |||
1495 | /* Close the connection with the IM server */ | ||
1496 | #ifdef X_HAVE_UTF8_STRING | ||
1497 | if (SDL_IC != NULL) { | ||
1498 | XUnsetICFocus(SDL_IC); | ||
1499 | XDestroyIC(SDL_IC); | ||
1500 | SDL_IC = NULL; | ||
1501 | } | ||
1502 | if (SDL_IM != NULL) { | ||
1503 | XCloseIM(SDL_IM); | ||
1504 | SDL_IM = NULL; | ||
1505 | } | ||
1506 | #endif | ||
1507 | |||
1508 | /* Start shutting down the windows */ | ||
1509 | X11_DestroyImage(this, this->screen); | ||
1510 | X11_DestroyWindow(this, this->screen); | ||
1511 | X11_FreeVideoModes(this); | ||
1512 | if ( SDL_XColorMap != SDL_DisplayColormap ) { | ||
1513 | XFreeColormap(SDL_Display, SDL_XColorMap); | ||
1514 | } | ||
1515 | if ( SDL_iconcolors ) { | ||
1516 | unsigned long pixel; | ||
1517 | Colormap dcmap = DefaultColormap(SDL_Display, | ||
1518 | SDL_Screen); | ||
1519 | for(pixel = 0; pixel < 256; ++pixel) { | ||
1520 | while(SDL_iconcolors[pixel] > 0) { | ||
1521 | XFreeColors(GFX_Display, | ||
1522 | dcmap, &pixel, 1, 0); | ||
1523 | --SDL_iconcolors[pixel]; | ||
1524 | } | ||
1525 | } | ||
1526 | SDL_free(SDL_iconcolors); | ||
1527 | SDL_iconcolors = NULL; | ||
1528 | } | ||
1529 | |||
1530 | /* Restore gamma settings if they've changed */ | ||
1531 | if ( SDL_GetAppState() & SDL_APPACTIVE ) { | ||
1532 | X11_SwapVidModeGamma(this); | ||
1533 | } | ||
1534 | |||
1535 | /* Free that blank cursor */ | ||
1536 | if ( SDL_BlankCursor != NULL ) { | ||
1537 | this->FreeWMCursor(this, SDL_BlankCursor); | ||
1538 | SDL_BlankCursor = NULL; | ||
1539 | } | ||
1540 | |||
1541 | /* Close the X11 graphics connection */ | ||
1542 | if ( GFX_Display != NULL ) { | ||
1543 | XCloseDisplay(GFX_Display); | ||
1544 | GFX_Display = NULL; | ||
1545 | } | ||
1546 | |||
1547 | /* Close the X11 display connection */ | ||
1548 | XCloseDisplay(SDL_Display); | ||
1549 | SDL_Display = NULL; | ||
1550 | |||
1551 | /* Reset the X11 error handlers */ | ||
1552 | if ( XIO_handler ) { | ||
1553 | XSetIOErrorHandler(XIO_handler); | ||
1554 | } | ||
1555 | if ( X_handler ) { | ||
1556 | XSetErrorHandler(X_handler); | ||
1557 | } | ||
1558 | |||
1559 | /* Unload GL library after X11 shuts down */ | ||
1560 | X11_GL_UnloadLibrary(this); | ||
1561 | } | ||
1562 | if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { | ||
1563 | /* Direct screen access, no memory buffer */ | ||
1564 | this->screen->pixels = NULL; | ||
1565 | } | ||
1566 | |||
1567 | #if SDL_VIDEO_DRIVER_X11_XME | ||
1568 | XiGMiscDestroy(); | ||
1569 | #endif | ||
1570 | } | ||
1571 | |||