Mercurial > sdl-ios-xcode
comparison src/video/x11/SDL_x11wm.c @ 236:3f09f52ac2cc
Fixed X11 icon color allocation (thanks Mattias!)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 07 Nov 2001 17:59:07 +0000 |
parents | 1b387dc653d0 |
children | 7c09c9e3b0c7 |
comparison
equal
deleted
inserted
replaced
235:dde0af58db4b | 236:3f09f52ac2cc |
---|---|
38 #include "SDL_events_c.h" | 38 #include "SDL_events_c.h" |
39 #include "SDL_pixels_c.h" | 39 #include "SDL_pixels_c.h" |
40 #include "SDL_x11modes_c.h" | 40 #include "SDL_x11modes_c.h" |
41 #include "SDL_x11wm_c.h" | 41 #include "SDL_x11wm_c.h" |
42 | 42 |
43 /* This is necessary for working properly with Enlightenment, etc. */ | 43 static Uint8 reverse_byte(Uint8 x) |
44 #define USE_ICON_WINDOW | 44 { |
45 x = (x & 0xaa) >> 1 | (x & 0x55) << 1; | |
46 x = (x & 0xcc) >> 2 | (x & 0x33) << 2; | |
47 x = (x & 0xf0) >> 4 | (x & 0x0f) << 4; | |
48 return x; | |
49 } | |
45 | 50 |
46 void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) | 51 void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) |
47 { | 52 { |
48 SDL_Surface *sicon; | 53 SDL_Surface *sicon; |
49 XWMHints *wmhints; | 54 XWMHints *wmhints; |
50 XImage *icon_image; | 55 XImage *icon_image; |
51 Pixmap icon_pixmap; | 56 Pixmap icon_pixmap; |
52 Pixmap mask_pixmap; | 57 Pixmap mask_pixmap; |
53 #ifdef USE_ICON_WINDOW | 58 Window icon_window = None; |
54 Window icon_window; | 59 GC gc; |
55 #endif | |
56 GC GC; | |
57 XGCValues GCvalues; | 60 XGCValues GCvalues; |
58 int i, b, dbpp; | 61 int i, dbpp; |
59 SDL_Rect bounds; | 62 SDL_Rect bounds; |
60 Uint8 *LSBmask, *color_tried; | 63 Uint8 *LSBmask; |
61 Visual *dvis; | 64 Visual *dvis; |
62 | 65 char *p; |
63 /* Lock the event thread, in multi-threading environments */ | 66 int masksize; |
67 | |
64 SDL_Lock_EventThread(); | 68 SDL_Lock_EventThread(); |
65 | 69 |
66 /* The icon must use the default visual, depth and colormap of the | 70 /* The icon must use the default visual, depth and colormap of the |
67 screen, so it might need a conversion */ | 71 screen, so it might need a conversion */ |
72 dvis = DefaultVisual(SDL_Display, SDL_Screen); | |
68 dbpp = DefaultDepth(SDL_Display, SDL_Screen); | 73 dbpp = DefaultDepth(SDL_Display, SDL_Screen); |
69 switch(dbpp) { | 74 for(i = 0; i < this->hidden->nvisuals; i++) { |
70 case 15: | 75 if(this->hidden->visuals[i].visual == dvis) { |
71 dbpp = 16; break; | 76 dbpp = this->hidden->visuals[i].bpp; |
72 case 24: | 77 break; |
73 dbpp = 32; break; | 78 } |
74 } | 79 } |
75 dvis = DefaultVisual(SDL_Display, SDL_Screen); | |
76 | 80 |
77 /* The Visual struct is supposed to be opaque but we cheat a little */ | 81 /* The Visual struct is supposed to be opaque but we cheat a little */ |
78 sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, | 82 sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, |
79 dbpp, | 83 dbpp, |
80 dvis->red_mask, dvis->green_mask, | 84 dvis->red_mask, dvis->green_mask, |
81 dvis->blue_mask, 0); | 85 dvis->blue_mask, 0); |
82 | 86 if ( sicon == NULL ) |
83 if ( sicon == NULL ) { | |
84 goto done; | 87 goto done; |
85 } | 88 |
86 /* If we already have allocated colours from the default colormap, | 89 if(dbpp == 8) { |
87 copy them */ | 90 /* Default visual is 8bit; we need to allocate colours from |
88 if(SDL_Visual == dvis && SDL_XColorMap == SDL_DisplayColormap | 91 the default colormap */ |
89 && this->screen->format->palette && sicon->format->palette) { | 92 SDL_Color want[256], got[256]; |
90 memcpy(sicon->format->palette->colors, | 93 int nwant; |
91 this->screen->format->palette->colors, | 94 Colormap dcmap; |
92 this->screen->format->palette->ncolors * sizeof(SDL_Color)); | 95 int missing; |
96 dcmap = DefaultColormap(SDL_Display, SDL_Screen); | |
97 if(icon->format->palette) { | |
98 /* The icon has a palette as well - we just have to | |
99 find those colours */ | |
100 nwant = icon->format->palette->ncolors; | |
101 memcpy(want, icon->format->palette->colors, | |
102 nwant * sizeof want[0]); | |
103 } else { | |
104 /* try the standard 6x6x6 cube for lack of better | |
105 ideas */ | |
106 int r, g, b, i; | |
107 for(r = i = 0; r < 256; r += 0x33) | |
108 for(g = 0; g < 256; g += 0x33) | |
109 for(b = 0; b < 256; b += 0x33, i++) { | |
110 want[i].r = r; | |
111 want[i].g = g; | |
112 want[i].b = b; | |
113 } | |
114 nwant = 216; | |
115 } | |
116 if(SDL_iconcolors) { | |
117 /* free already allocated colours first */ | |
118 unsigned long freelist[512]; | |
119 int nfree = 0; | |
120 for(i = 0; i < 256; i++) { | |
121 while(SDL_iconcolors[i]) { | |
122 freelist[nfree++] = i; | |
123 SDL_iconcolors[i]--; | |
124 } | |
125 } | |
126 XFreeColors(GFX_Display, dcmap, freelist, nfree, 0); | |
127 } | |
128 if(!SDL_iconcolors) | |
129 SDL_iconcolors = malloc(256 * sizeof *SDL_iconcolors); | |
130 memset(SDL_iconcolors, 0, 256 * sizeof *SDL_iconcolors); | |
131 | |
132 /* try to allocate the colours */ | |
133 memset(got, 0, sizeof got); | |
134 missing = 0; | |
135 for(i = 0; i < nwant; i++) { | |
136 XColor c; | |
137 c.red = want[i].r << 8; | |
138 c.green = want[i].g << 8; | |
139 c.blue = want[i].b << 8; | |
140 c.flags = DoRed | DoGreen | DoBlue; | |
141 if(XAllocColor(GFX_Display, dcmap, &c)) { | |
142 /* got the colour */ | |
143 SDL_iconcolors[c.pixel]++; | |
144 got[c.pixel] = want[i]; | |
145 } else { | |
146 missing = 1; | |
147 } | |
148 } | |
149 if(missing) { | |
150 /* Some colours were apparently missing, so we just | |
151 allocate all the rest as well */ | |
152 XColor cols[256]; | |
153 for(i = 0; i < 256; i++) | |
154 cols[i].pixel = i; | |
155 XQueryColors(GFX_Display, dcmap, cols, 256); | |
156 for(i = 0; i < 256; i++) { | |
157 got[i].r = cols[i].red >> 8; | |
158 got[i].g = cols[i].green >> 8; | |
159 got[i].b = cols[i].blue >> 8; | |
160 if(!SDL_iconcolors[i]) { | |
161 if(XAllocColor(GFX_Display, dcmap, | |
162 cols + i)) { | |
163 SDL_iconcolors[i] = 1; | |
164 } else { | |
165 /* index not available */ | |
166 got[i].r = 0; | |
167 got[i].g = 0; | |
168 got[i].b = 0; | |
169 } | |
170 } | |
171 } | |
172 } | |
173 | |
174 SDL_SetColors(sicon, got, 0, 256); | |
93 } | 175 } |
94 | 176 |
95 bounds.x = 0; | 177 bounds.x = 0; |
96 bounds.y = 0; | 178 bounds.y = 0; |
97 bounds.w = icon->w; | 179 bounds.w = icon->w; |
98 bounds.h = icon->h; | 180 bounds.h = icon->h; |
99 if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) | 181 if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) |
100 goto done; | 182 goto done; |
101 | 183 |
102 /* Lock down the colors used in the colormap */ | 184 /* We need the mask as given, except in LSBfirst format instead of |
103 color_tried = NULL; | 185 MSBfirst. Reverse the bits in each byte. */ |
104 if ( sicon->format->BitsPerPixel == 8 ) { | 186 masksize = ((sicon->w + 7) >> 3) * sicon->h; |
105 SDL_Palette *palette; | 187 LSBmask = malloc(masksize); |
106 Uint8 *p; | |
107 XColor wanted; | |
108 | |
109 palette = sicon->format->palette; | |
110 color_tried = malloc(palette->ncolors); | |
111 if ( color_tried == NULL ) { | |
112 goto done; | |
113 } | |
114 if ( SDL_iconcolors != NULL ) { | |
115 free(SDL_iconcolors); | |
116 } | |
117 SDL_iconcolors = malloc(palette->ncolors | |
118 * sizeof(*SDL_iconcolors)); | |
119 if ( SDL_iconcolors == NULL ) { | |
120 free(color_tried); | |
121 goto done; | |
122 } | |
123 memset(color_tried, 0, palette->ncolors); | |
124 memset(SDL_iconcolors, 0, | |
125 palette->ncolors * sizeof(*SDL_iconcolors)); | |
126 | |
127 p = (Uint8 *)sicon->pixels; | |
128 for ( i = sicon->w*sicon->h; i > 0; --i, ++p ) { | |
129 if ( ! color_tried[*p] ) { | |
130 wanted.pixel = *p; | |
131 wanted.red = (palette->colors[*p].r<<8); | |
132 wanted.green = (palette->colors[*p].g<<8); | |
133 wanted.blue = (palette->colors[*p].b<<8); | |
134 wanted.flags = (DoRed|DoGreen|DoBlue); | |
135 if (XAllocColor(SDL_Display, | |
136 SDL_DisplayColormap, &wanted)) { | |
137 ++SDL_iconcolors[wanted.pixel]; | |
138 } | |
139 color_tried[*p] = 1; | |
140 } | |
141 } | |
142 } | |
143 if ( color_tried != NULL ) { | |
144 free(color_tried); | |
145 } | |
146 | |
147 /* Translate mask data to LSB order and set the icon mask */ | |
148 i = (sicon->w/8)*sicon->h; | |
149 LSBmask = (Uint8 *)malloc(i); | |
150 if ( LSBmask == NULL ) { | 188 if ( LSBmask == NULL ) { |
151 goto done; | 189 goto done; |
152 } | 190 } |
153 memset(LSBmask, 0, i); | 191 memset(LSBmask, 0, masksize); |
154 while ( --i >= 0 ) { | 192 for(i = 0; i < masksize; i++) |
155 for ( b=0; b<8; ++b ) | 193 LSBmask[i] = reverse_byte(mask[i]); |
156 LSBmask[i] |= (((mask[i]>>b)&0x01)<<(7-b)); | |
157 } | |
158 mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow, | 194 mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow, |
159 (char *)LSBmask, sicon->w, sicon->h, 1L, 0L, 1); | 195 (char *)LSBmask, |
196 sicon->w, sicon->h, | |
197 1L, 0L, 1); | |
160 | 198 |
161 /* Transfer the image to an X11 pixmap */ | 199 /* Transfer the image to an X11 pixmap */ |
162 icon_image = XCreateImage(SDL_Display, | 200 icon_image = XCreateImage(SDL_Display, |
163 DefaultVisual(SDL_Display, SDL_Screen), | 201 DefaultVisual(SDL_Display, SDL_Screen), |
164 DefaultDepth(SDL_Display, SDL_Screen), | 202 DefaultDepth(SDL_Display, SDL_Screen), |
165 ZPixmap, 0, (char *)sicon->pixels, sicon->w, sicon->h, | 203 ZPixmap, 0, sicon->pixels, |
166 ((sicon->format)->BytesPerPixel == 3) ? 32 : | 204 sicon->w, sicon->h, |
167 (sicon->format)->BytesPerPixel*8, 0); | 205 32, 0); |
168 icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h, | 206 icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h, |
169 DefaultDepth(SDL_Display, SDL_Screen)); | 207 DefaultDepth(SDL_Display, SDL_Screen)); |
170 GC = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues); | 208 gc = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues); |
171 XPutImage(SDL_Display, icon_pixmap, GC, icon_image, | 209 XPutImage(SDL_Display, icon_pixmap, gc, icon_image, |
172 0, 0, 0, 0, sicon->w, sicon->h); | 210 0, 0, 0, 0, sicon->w, sicon->h); |
173 XFreeGC(SDL_Display, GC); | 211 XFreeGC(SDL_Display, gc); |
174 XDestroyImage(icon_image); | 212 XDestroyImage(icon_image); |
175 free(LSBmask); | 213 free(LSBmask); |
176 sicon->pixels = NULL; | 214 sicon->pixels = NULL; |
177 | 215 |
178 #ifdef USE_ICON_WINDOW | 216 /* Some buggy window managers (some versions of Enlightenment, it |
179 /* Create an icon window and set the pixmap as its background */ | 217 seems) need an icon window *and* icon pixmap to work properly, while |
180 icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root, | 218 it screws up others. The default is only to use a pixmap. */ |
181 0, 0, sicon->w, sicon->h, 0, | 219 p = getenv("SDL_VIDEO_X11_ICONWIN"); |
182 CopyFromParent, CopyFromParent); | 220 if(p && *p) { |
183 XSetWindowBackgroundPixmap(SDL_Display, icon_window, icon_pixmap); | 221 icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root, |
184 XClearWindow(SDL_Display, icon_window); | 222 0, 0, sicon->w, sicon->h, 0, |
185 #endif | 223 CopyFromParent, |
224 CopyFromParent); | |
225 XSetWindowBackgroundPixmap(SDL_Display, icon_window, | |
226 icon_pixmap); | |
227 XClearWindow(SDL_Display, icon_window); | |
228 } | |
186 | 229 |
187 /* Set the window icon to the icon pixmap (and icon window) */ | 230 /* Set the window icon to the icon pixmap (and icon window) */ |
188 wmhints = XAllocWMHints(); | 231 wmhints = XAllocWMHints(); |
189 wmhints->flags = (IconPixmapHint | IconMaskHint); | 232 wmhints->flags = (IconPixmapHint | IconMaskHint); |
190 wmhints->icon_pixmap = icon_pixmap; | 233 wmhints->icon_pixmap = icon_pixmap; |
191 wmhints->icon_mask = mask_pixmap; | 234 wmhints->icon_mask = mask_pixmap; |
192 #ifdef USE_ICON_WINDOW | 235 if(icon_window != None) { |
193 wmhints->flags |= IconWindowHint; | 236 wmhints->flags |= IconWindowHint; |
194 wmhints->icon_window = icon_window; | 237 wmhints->icon_window = icon_window; |
195 #endif | 238 } |
196 XSetWMHints(SDL_Display, WMwindow, wmhints); | 239 XSetWMHints(SDL_Display, WMwindow, wmhints); |
197 XFree(wmhints); | 240 XFree(wmhints); |
198 XSync(SDL_Display, False); | 241 XSync(SDL_Display, False); |
199 | 242 |
200 done: | 243 done: |
201 SDL_Unlock_EventThread(); | 244 SDL_Unlock_EventThread(); |
202 if ( sicon != NULL ) { | 245 SDL_FreeSurface(sicon); |
203 SDL_FreeSurface(sicon); | |
204 } | |
205 return; | |
206 } | 246 } |
207 | 247 |
208 void X11_SetCaption(_THIS, const char *title, const char *icon) | 248 void X11_SetCaption(_THIS, const char *title, const char *icon) |
209 { | 249 { |
210 XTextProperty titleprop, iconprop; | 250 XTextProperty titleprop, iconprop; |
239 return(result); | 279 return(result); |
240 } | 280 } |
241 | 281 |
242 SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode) | 282 SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode) |
243 { | 283 { |
244 int numtries, result; | 284 int result; |
245 | 285 |
246 if ( this->screen == NULL ) { | 286 if ( this->screen == NULL ) { |
247 return(SDL_GRAB_OFF); | 287 return(SDL_GRAB_OFF); |
248 } | 288 } |
249 if ( ! SDL_Window ) { | 289 if ( ! SDL_Window ) { |