Skip to content

Latest commit

 

History

History
389 lines (355 loc) · 10.6 KB

SDL_x11wm.c

File metadata and controls

389 lines (355 loc) · 10.6 KB
 
Apr 26, 2001
Apr 26, 2001
1
2
/*
SDL - Simple DirectMedia Layer
Feb 1, 2006
Feb 1, 2006
3
Copyright (C) 1997-2006 Sam Lantinga
Apr 26, 2001
Apr 26, 2001
4
5
This library is free software; you can redistribute it and/or
Feb 1, 2006
Feb 1, 2006
6
modify it under the terms of the GNU Lesser General Public
Apr 26, 2001
Apr 26, 2001
7
License as published by the Free Software Foundation; either
Feb 1, 2006
Feb 1, 2006
8
version 2.1 of the License, or (at your option) any later version.
Apr 26, 2001
Apr 26, 2001
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Feb 1, 2006
Feb 1, 2006
13
Lesser General Public License for more details.
Apr 26, 2001
Apr 26, 2001
14
Feb 1, 2006
Feb 1, 2006
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Apr 26, 2001
Apr 26, 2001
18
19
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Apr 26, 2001
Apr 26, 2001
21
22
23
24
25
26
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "SDL_version.h"
Feb 7, 2006
Feb 7, 2006
27
28
#include "SDL_stdlib.h"
#include "SDL_string.h"
Apr 26, 2001
Apr 26, 2001
29
30
31
32
33
34
35
36
37
#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_video.h"
#include "SDL_syswm.h"
#include "SDL_events_c.h"
#include "SDL_pixels_c.h"
#include "SDL_x11modes_c.h"
#include "SDL_x11wm_c.h"
Nov 7, 2001
Nov 7, 2001
38
39
40
41
42
43
44
static Uint8 reverse_byte(Uint8 x)
{
x = (x & 0xaa) >> 1 | (x & 0x55) << 1;
x = (x & 0xcc) >> 2 | (x & 0x33) << 2;
x = (x & 0xf0) >> 4 | (x & 0x0f) << 4;
return x;
}
Apr 26, 2001
Apr 26, 2001
45
46
47
48
49
50
51
52
void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
{
SDL_Surface *sicon;
XWMHints *wmhints;
XImage *icon_image;
Pixmap icon_pixmap;
Pixmap mask_pixmap;
Nov 7, 2001
Nov 7, 2001
53
54
Window icon_window = None;
GC gc;
Apr 26, 2001
Apr 26, 2001
55
XGCValues GCvalues;
Nov 7, 2001
Nov 7, 2001
56
int i, dbpp;
Apr 26, 2001
Apr 26, 2001
57
SDL_Rect bounds;
Nov 7, 2001
Nov 7, 2001
58
Uint8 *LSBmask;
Apr 26, 2001
Apr 26, 2001
59
Visual *dvis;
Nov 7, 2001
Nov 7, 2001
60
61
char *p;
int masksize;
Apr 26, 2001
Apr 26, 2001
62
63
64
65
66
SDL_Lock_EventThread();
/* The icon must use the default visual, depth and colormap of the
screen, so it might need a conversion */
Nov 7, 2001
Nov 7, 2001
67
dvis = DefaultVisual(SDL_Display, SDL_Screen);
Apr 26, 2001
Apr 26, 2001
68
dbpp = DefaultDepth(SDL_Display, SDL_Screen);
Nov 7, 2001
Nov 7, 2001
69
70
71
72
73
for(i = 0; i < this->hidden->nvisuals; i++) {
if(this->hidden->visuals[i].visual == dvis) {
dbpp = this->hidden->visuals[i].bpp;
break;
}
Apr 26, 2001
Apr 26, 2001
74
75
76
77
78
79
80
}
/* The Visual struct is supposed to be opaque but we cheat a little */
sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
dbpp,
dvis->red_mask, dvis->green_mask,
dvis->blue_mask, 0);
Nov 7, 2001
Nov 7, 2001
81
if ( sicon == NULL )
Apr 26, 2001
Apr 26, 2001
82
83
goto done;
Nov 7, 2001
Nov 7, 2001
84
85
86
87
88
89
90
91
92
93
94
95
if(dbpp == 8) {
/* Default visual is 8bit; we need to allocate colours from
the default colormap */
SDL_Color want[256], got[256];
int nwant;
Colormap dcmap;
int missing;
dcmap = DefaultColormap(SDL_Display, SDL_Screen);
if(icon->format->palette) {
/* The icon has a palette as well - we just have to
find those colours */
nwant = icon->format->palette->ncolors;
Feb 7, 2006
Feb 7, 2006
96
SDL_memcpy(want, icon->format->palette->colors,
Nov 7, 2001
Nov 7, 2001
97
98
99
100
101
102
103
104
105
106
107
108
109
nwant * sizeof want[0]);
} else {
/* try the standard 6x6x6 cube for lack of better
ideas */
int r, g, b, i;
for(r = i = 0; r < 256; r += 0x33)
for(g = 0; g < 256; g += 0x33)
for(b = 0; b < 256; b += 0x33, i++) {
want[i].r = r;
want[i].g = g;
want[i].b = b;
}
nwant = 216;
Apr 26, 2001
Apr 26, 2001
110
}
Nov 7, 2001
Nov 7, 2001
111
112
113
114
115
116
117
118
119
120
if(SDL_iconcolors) {
/* free already allocated colours first */
unsigned long freelist[512];
int nfree = 0;
for(i = 0; i < 256; i++) {
while(SDL_iconcolors[i]) {
freelist[nfree++] = i;
SDL_iconcolors[i]--;
}
}
Nov 5, 2005
Nov 5, 2005
121
pXFreeColors(GFX_Display, dcmap, freelist, nfree, 0);
Apr 26, 2001
Apr 26, 2001
122
}
Nov 7, 2001
Nov 7, 2001
123
if(!SDL_iconcolors)
Feb 7, 2006
Feb 7, 2006
124
125
SDL_iconcolors = SDL_malloc(256 * sizeof *SDL_iconcolors);
SDL_memset(SDL_iconcolors, 0, 256 * sizeof *SDL_iconcolors);
Apr 26, 2001
Apr 26, 2001
126
Nov 7, 2001
Nov 7, 2001
127
/* try to allocate the colours */
Feb 7, 2006
Feb 7, 2006
128
SDL_memset(got, 0, sizeof got);
Nov 7, 2001
Nov 7, 2001
129
130
131
132
133
134
135
missing = 0;
for(i = 0; i < nwant; i++) {
XColor c;
c.red = want[i].r << 8;
c.green = want[i].g << 8;
c.blue = want[i].b << 8;
c.flags = DoRed | DoGreen | DoBlue;
Nov 5, 2005
Nov 5, 2005
136
if(pXAllocColor(GFX_Display, dcmap, &c)) {
Nov 7, 2001
Nov 7, 2001
137
138
139
140
141
142
143
144
145
146
147
148
149
/* got the colour */
SDL_iconcolors[c.pixel]++;
got[c.pixel] = want[i];
} else {
missing = 1;
}
}
if(missing) {
/* Some colours were apparently missing, so we just
allocate all the rest as well */
XColor cols[256];
for(i = 0; i < 256; i++)
cols[i].pixel = i;
Nov 5, 2005
Nov 5, 2005
150
pXQueryColors(GFX_Display, dcmap, cols, 256);
Nov 7, 2001
Nov 7, 2001
151
152
153
154
155
for(i = 0; i < 256; i++) {
got[i].r = cols[i].red >> 8;
got[i].g = cols[i].green >> 8;
got[i].b = cols[i].blue >> 8;
if(!SDL_iconcolors[i]) {
Nov 5, 2005
Nov 5, 2005
156
if(pXAllocColor(GFX_Display, dcmap,
Nov 7, 2001
Nov 7, 2001
157
158
159
160
161
162
163
164
cols + i)) {
SDL_iconcolors[i] = 1;
} else {
/* index not available */
got[i].r = 0;
got[i].g = 0;
got[i].b = 0;
}
Apr 26, 2001
Apr 26, 2001
165
166
167
}
}
}
Nov 7, 2001
Nov 7, 2001
168
169
SDL_SetColors(sicon, got, 0, 256);
Apr 26, 2001
Apr 26, 2001
170
171
}
Nov 7, 2001
Nov 7, 2001
172
173
174
175
176
177
178
179
180
181
bounds.x = 0;
bounds.y = 0;
bounds.w = icon->w;
bounds.h = icon->h;
if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 )
goto done;
/* We need the mask as given, except in LSBfirst format instead of
MSBfirst. Reverse the bits in each byte. */
masksize = ((sicon->w + 7) >> 3) * sicon->h;
Feb 7, 2006
Feb 7, 2006
182
LSBmask = SDL_malloc(masksize);
Apr 26, 2001
Apr 26, 2001
183
184
185
if ( LSBmask == NULL ) {
goto done;
}
Feb 7, 2006
Feb 7, 2006
186
SDL_memset(LSBmask, 0, masksize);
Nov 7, 2001
Nov 7, 2001
187
188
for(i = 0; i < masksize; i++)
LSBmask[i] = reverse_byte(mask[i]);
Nov 5, 2005
Nov 5, 2005
189
mask_pixmap = pXCreatePixmapFromBitmapData(SDL_Display, WMwindow,
Nov 7, 2001
Nov 7, 2001
190
191
192
(char *)LSBmask,
sicon->w, sicon->h,
1L, 0L, 1);
Apr 26, 2001
Apr 26, 2001
193
194
/* Transfer the image to an X11 pixmap */
Nov 5, 2005
Nov 5, 2005
195
icon_image = pXCreateImage(SDL_Display,
Nov 7, 2001
Nov 7, 2001
196
197
198
199
200
DefaultVisual(SDL_Display, SDL_Screen),
DefaultDepth(SDL_Display, SDL_Screen),
ZPixmap, 0, sicon->pixels,
sicon->w, sicon->h,
32, 0);
Nov 27, 2001
Nov 27, 2001
201
202
icon_image->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN)
? MSBFirst : LSBFirst;
Nov 5, 2005
Nov 5, 2005
203
icon_pixmap = pXCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h,
Nov 7, 2001
Nov 7, 2001
204
DefaultDepth(SDL_Display, SDL_Screen));
Nov 5, 2005
Nov 5, 2005
205
206
gc = pXCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues);
pXPutImage(SDL_Display, icon_pixmap, gc, icon_image,
Nov 7, 2001
Nov 7, 2001
207
0, 0, 0, 0, sicon->w, sicon->h);
Nov 5, 2005
Nov 5, 2005
208
209
pXFreeGC(SDL_Display, gc);
pXDestroyImage(icon_image);
Feb 7, 2006
Feb 7, 2006
210
SDL_free(LSBmask);
Apr 26, 2001
Apr 26, 2001
211
212
sicon->pixels = NULL;
Nov 7, 2001
Nov 7, 2001
213
214
215
/* Some buggy window managers (some versions of Enlightenment, it
seems) need an icon window *and* icon pixmap to work properly, while
it screws up others. The default is only to use a pixmap. */
Feb 7, 2006
Feb 7, 2006
216
p = SDL_getenv("SDL_VIDEO_X11_ICONWIN");
Nov 7, 2001
Nov 7, 2001
217
if(p && *p) {
Nov 5, 2005
Nov 5, 2005
218
icon_window = pXCreateSimpleWindow(SDL_Display, SDL_Root,
Nov 7, 2001
Nov 7, 2001
219
220
221
0, 0, sicon->w, sicon->h, 0,
CopyFromParent,
CopyFromParent);
Nov 5, 2005
Nov 5, 2005
222
pXSetWindowBackgroundPixmap(SDL_Display, icon_window,
Nov 7, 2001
Nov 7, 2001
223
icon_pixmap);
Nov 5, 2005
Nov 5, 2005
224
pXClearWindow(SDL_Display, icon_window);
Nov 7, 2001
Nov 7, 2001
225
}
Apr 26, 2001
Apr 26, 2001
226
227
/* Set the window icon to the icon pixmap (and icon window) */
Nov 5, 2005
Nov 5, 2005
228
wmhints = pXAllocWMHints();
Apr 26, 2001
Apr 26, 2001
229
230
231
wmhints->flags = (IconPixmapHint | IconMaskHint);
wmhints->icon_pixmap = icon_pixmap;
wmhints->icon_mask = mask_pixmap;
Nov 7, 2001
Nov 7, 2001
232
233
234
235
if(icon_window != None) {
wmhints->flags |= IconWindowHint;
wmhints->icon_window = icon_window;
}
Nov 5, 2005
Nov 5, 2005
236
237
238
pXSetWMHints(SDL_Display, WMwindow, wmhints);
pXFree(wmhints);
pXSync(SDL_Display, False);
Apr 26, 2001
Apr 26, 2001
239
240
241
done:
SDL_Unlock_EventThread();
Nov 7, 2001
Nov 7, 2001
242
SDL_FreeSurface(sicon);
Apr 26, 2001
Apr 26, 2001
243
244
245
246
247
248
249
250
251
252
}
void X11_SetCaption(_THIS, const char *title, const char *icon)
{
XTextProperty titleprop, iconprop;
/* Lock the event thread, in multi-threading environments */
SDL_Lock_EventThread();
if ( title != NULL ) {
Sep 11, 2004
Sep 11, 2004
253
int error = XLocaleNotSupported;
Jul 25, 2004
Jul 25, 2004
254
#ifdef X_HAVE_UTF8_STRING
Nov 5, 2005
Nov 5, 2005
255
error = pXutf8TextListToTextProperty(SDL_Display,
Sep 11, 2004
Sep 11, 2004
256
257
(char **)&title, 1, XUTF8StringStyle,
&titleprop);
Jul 25, 2004
Jul 25, 2004
258
#endif
Sep 11, 2004
Sep 11, 2004
259
if ( error != Success ) {
Nov 5, 2005
Nov 5, 2005
260
pXStringListToTextProperty((char **)&title, 1,
Sep 11, 2004
Sep 11, 2004
261
262
&titleprop);
}
Nov 5, 2005
Nov 5, 2005
263
264
pXSetWMName(SDL_Display, WMwindow, &titleprop);
pXFree(titleprop.value);
Apr 26, 2001
Apr 26, 2001
265
266
}
if ( icon != NULL ) {
Sep 11, 2004
Sep 11, 2004
267
int error = XLocaleNotSupported;
Jul 25, 2004
Jul 25, 2004
268
#ifdef X_HAVE_UTF8_STRING
Nov 5, 2005
Nov 5, 2005
269
error = pXutf8TextListToTextProperty(SDL_Display,
Sep 11, 2004
Sep 11, 2004
270
(char **)&icon, 1, XUTF8StringStyle, &iconprop);
Jul 25, 2004
Jul 25, 2004
271
#endif
Sep 11, 2004
Sep 11, 2004
272
if ( error != Success ) {
Nov 5, 2005
Nov 5, 2005
273
pXStringListToTextProperty((char **)&icon, 1, &iconprop);
Sep 11, 2004
Sep 11, 2004
274
}
Nov 5, 2005
Nov 5, 2005
275
276
pXSetWMIconName(SDL_Display, WMwindow, &iconprop);
pXFree(iconprop.value);
Apr 26, 2001
Apr 26, 2001
277
}
Nov 5, 2005
Nov 5, 2005
278
pXSync(SDL_Display, False);
Apr 26, 2001
Apr 26, 2001
279
280
281
282
283
284
285
286
287
288
SDL_Unlock_EventThread();
}
/* Iconify the window */
int X11_IconifyWindow(_THIS)
{
int result;
SDL_Lock_EventThread();
Nov 5, 2005
Nov 5, 2005
289
290
result = pXIconifyWindow(SDL_Display, WMwindow, SDL_Screen);
pXSync(SDL_Display, False);
Apr 26, 2001
Apr 26, 2001
291
292
293
294
295
296
SDL_Unlock_EventThread();
return(result);
}
SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode)
{
Nov 7, 2001
Nov 7, 2001
297
int result;
Apr 26, 2001
Apr 26, 2001
298
299
300
301
302
303
304
305
if ( this->screen == NULL ) {
return(SDL_GRAB_OFF);
}
if ( ! SDL_Window ) {
return(mode); /* Will be set later on mode switch */
}
if ( mode == SDL_GRAB_OFF ) {
Nov 5, 2005
Nov 5, 2005
306
307
pXUngrabPointer(SDL_Display, CurrentTime);
pXUngrabKeyboard(SDL_Display, CurrentTime);
Apr 26, 2001
Apr 26, 2001
308
309
310
} else {
if ( this->screen->flags & SDL_FULLSCREEN ) {
/* Unbind the mouse from the fullscreen window */
Nov 5, 2005
Nov 5, 2005
311
pXUngrabPointer(SDL_Display, CurrentTime);
Apr 26, 2001
Apr 26, 2001
312
313
}
/* Try to grab the mouse */
Jul 9, 2001
Jul 9, 2001
314
#if 0 /* We'll wait here until we actually grab, otherwise behavior undefined */
Apr 26, 2001
Apr 26, 2001
315
for ( numtries = 0; numtries < 10; ++numtries ) {
Jul 9, 2001
Jul 9, 2001
316
317
318
#else
while ( 1 ) {
#endif
Nov 5, 2005
Nov 5, 2005
319
result = pXGrabPointer(SDL_Display, SDL_Window, True, 0,
Apr 26, 2001
Apr 26, 2001
320
321
GrabModeAsync, GrabModeAsync,
SDL_Window, None, CurrentTime);
Jul 7, 2001
Jul 7, 2001
322
if ( result == GrabSuccess ) {
Apr 26, 2001
Apr 26, 2001
323
324
325
326
break;
}
SDL_Delay(100);
}
Jul 7, 2001
Jul 7, 2001
327
328
329
if ( result != GrabSuccess ) {
/* Uh, oh, what do we do here? */ ;
}
Jul 9, 2001
Jul 9, 2001
330
/* Now grab the keyboard */
Nov 5, 2005
Nov 5, 2005
331
pXGrabKeyboard(SDL_Display, WMwindow, True,
Jul 7, 2001
Jul 7, 2001
332
GrabModeAsync, GrabModeAsync, CurrentTime);
Apr 26, 2001
Apr 26, 2001
333
334
335
/* Raise the window if we grab the mouse */
if ( !(this->screen->flags & SDL_FULLSCREEN) )
Nov 5, 2005
Nov 5, 2005
336
pXRaiseWindow(SDL_Display, WMwindow);
Jul 9, 2001
Jul 9, 2001
337
338
339
/* Make sure we register input focus */
SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
Apr 26, 2001
Apr 26, 2001
340
}
Nov 5, 2005
Nov 5, 2005
341
pXSync(SDL_Display, False);
Apr 26, 2001
Apr 26, 2001
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
return(mode);
}
SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode)
{
SDL_Lock_EventThread();
mode = X11_GrabInputNoLock(this, mode);
SDL_Unlock_EventThread();
return(mode);
}
/* If 'info' is the right version, this function fills it and returns 1.
Otherwise, in case of a version mismatch, it returns -1.
*/
static void lock_display(void)
{
SDL_Lock_EventThread();
}
static void unlock_display(void)
{
/* Make sure any X11 transactions are completed */
SDL_VideoDevice *this = current_video;
Nov 5, 2005
Nov 5, 2005
366
pXSync(SDL_Display, False);
Apr 26, 2001
Apr 26, 2001
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
SDL_Unlock_EventThread();
}
int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info)
{
if ( info->version.major <= SDL_MAJOR_VERSION ) {
info->subsystem = SDL_SYSWM_X11;
info->info.x11.display = SDL_Display;
info->info.x11.window = SDL_Window;
if ( SDL_VERSIONNUM(info->version.major,
info->version.minor,
info->version.patch) >= 1002 ) {
info->info.x11.fswindow = FSwindow;
info->info.x11.wmwindow = WMwindow;
}
info->info.x11.lock_func = lock_display;
info->info.x11.unlock_func = unlock_display;
return(1);
} else {
SDL_SetError("Application not compiled with SDL %d.%d\n",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return(-1);
}
}