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