Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
436 lines (399 loc) · 14 KB

SDL_x11wm.c

File metadata and controls

436 lines (399 loc) · 14 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
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
23
24
25
26
27
28
29
30
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "SDL_version.h"
#include "SDL_timer.h"
#include "SDL_video.h"
#include "SDL_syswm.h"
Feb 16, 2006
Feb 16, 2006
31
32
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
Apr 26, 2001
Apr 26, 2001
33
34
35
#include "SDL_x11modes_c.h"
#include "SDL_x11wm_c.h"
May 28, 2006
May 28, 2006
36
static Uint8
May 29, 2006
May 29, 2006
37
reverse_byte(Uint8 x)
Nov 7, 2001
Nov 7, 2001
38
{
May 28, 2006
May 28, 2006
39
40
41
42
x = (x & 0xaa) >> 1 | (x & 0x55) << 1;
x = (x & 0xcc) >> 2 | (x & 0x33) << 2;
x = (x & 0xf0) >> 4 | (x & 0x0f) << 4;
return x;
Nov 7, 2001
Nov 7, 2001
43
}
Apr 26, 2001
Apr 26, 2001
44
May 28, 2006
May 28, 2006
45
void
May 29, 2006
May 29, 2006
46
X11_SetIcon(_THIS, SDL_Surface * icon, Uint8 * mask)
Apr 26, 2001
Apr 26, 2001
47
{
May 28, 2006
May 28, 2006
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
SDL_Surface *sicon;
XWMHints *wmhints;
XImage *icon_image;
Pixmap icon_pixmap;
Pixmap mask_pixmap;
Window icon_window = None;
GC gc;
XGCValues GCvalues;
int i, dbpp;
SDL_Rect bounds;
Uint8 *LSBmask;
Visual *dvis;
char *p;
int masksize;
May 29, 2006
May 29, 2006
63
SDL_Lock_EventThread();
May 28, 2006
May 28, 2006
64
65
66
/* The icon must use the default visual, depth and colormap of the
screen, so it might need a conversion */
May 29, 2006
May 29, 2006
67
68
dvis = DefaultVisual(SDL_Display, SDL_Screen);
dbpp = DefaultDepth(SDL_Display, SDL_Screen);
May 28, 2006
May 28, 2006
69
70
71
72
73
74
75
76
for (i = 0; i < this->hidden->nvisuals; i++) {
if (this->hidden->visuals[i].visual == dvis) {
dbpp = this->hidden->visuals[i].bpp;
break;
}
}
/* The Visual struct is supposed to be opaque but we cheat a little */
May 29, 2006
May 29, 2006
77
78
79
80
sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
dbpp,
dvis->red_mask, dvis->green_mask,
dvis->blue_mask, 0);
May 28, 2006
May 28, 2006
81
82
83
84
85
86
87
88
89
90
if (sicon == NULL)
goto done;
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;
May 29, 2006
May 29, 2006
91
dcmap = DefaultColormap(SDL_Display, SDL_Screen);
May 28, 2006
May 28, 2006
92
93
94
95
if (icon->format->palette) {
/* The icon has a palette as well - we just have to
find those colours */
nwant = icon->format->palette->ncolors;
May 29, 2006
May 29, 2006
96
97
SDL_memcpy(want, icon->format->palette->colors,
nwant * sizeof want[0]);
May 28, 2006
May 28, 2006
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
} 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;
}
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]--;
}
}
May 29, 2006
May 29, 2006
121
XFreeColors(GFX_Display, dcmap, freelist, nfree, 0);
May 28, 2006
May 28, 2006
122
123
}
if (!SDL_iconcolors)
May 29, 2006
May 29, 2006
124
125
SDL_iconcolors = SDL_malloc(256 * sizeof *SDL_iconcolors);
SDL_memset(SDL_iconcolors, 0, 256 * sizeof *SDL_iconcolors);
May 28, 2006
May 28, 2006
126
127
/* try to allocate the colours */
May 29, 2006
May 29, 2006
128
SDL_memset(got, 0, sizeof got);
May 28, 2006
May 28, 2006
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;
May 29, 2006
May 29, 2006
136
if (XAllocColor(GFX_Display, dcmap, &c)) {
May 28, 2006
May 28, 2006
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;
May 29, 2006
May 29, 2006
150
XQueryColors(GFX_Display, dcmap, cols, 256);
May 28, 2006
May 28, 2006
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]) {
May 29, 2006
May 29, 2006
156
if (XAllocColor(GFX_Display, dcmap, cols + i)) {
May 28, 2006
May 28, 2006
157
158
159
160
161
162
163
164
165
166
167
SDL_iconcolors[i] = 1;
} else {
/* index not available */
got[i].r = 0;
got[i].g = 0;
got[i].b = 0;
}
}
}
}
May 29, 2006
May 29, 2006
168
SDL_SetColors(sicon, got, 0, 256);
May 28, 2006
May 28, 2006
169
170
171
172
173
174
}
bounds.x = 0;
bounds.y = 0;
bounds.w = icon->w;
bounds.h = icon->h;
May 29, 2006
May 29, 2006
175
if (SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0)
May 28, 2006
May 28, 2006
176
177
178
179
180
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;
May 29, 2006
May 29, 2006
181
LSBmask = SDL_malloc(masksize);
May 28, 2006
May 28, 2006
182
183
184
if (LSBmask == NULL) {
goto done;
}
May 29, 2006
May 29, 2006
185
SDL_memset(LSBmask, 0, masksize);
May 28, 2006
May 28, 2006
186
for (i = 0; i < masksize; i++)
May 29, 2006
May 29, 2006
187
188
189
190
LSBmask[i] = reverse_byte(mask[i]);
mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow,
(char *) LSBmask,
sicon->w, sicon->h, 1L, 0L, 1);
May 28, 2006
May 28, 2006
191
192
/* Transfer the image to an X11 pixmap */
May 29, 2006
May 29, 2006
193
194
195
196
197
icon_image = XCreateImage(SDL_Display,
DefaultVisual(SDL_Display, SDL_Screen),
DefaultDepth(SDL_Display, SDL_Screen),
ZPixmap, 0, sicon->pixels,
sicon->w, sicon->h, 32, 0);
May 28, 2006
May 28, 2006
198
199
icon_image->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN)
? MSBFirst : LSBFirst;
May 29, 2006
May 29, 2006
200
201
202
203
204
205
206
207
icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h,
DefaultDepth(SDL_Display, SDL_Screen));
gc = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues);
XPutImage(SDL_Display, icon_pixmap, gc, icon_image,
0, 0, 0, 0, sicon->w, sicon->h);
XFreeGC(SDL_Display, gc);
XDestroyImage(icon_image);
SDL_free(LSBmask);
May 28, 2006
May 28, 2006
208
209
210
211
212
sicon->pixels = NULL;
/* 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. */
May 29, 2006
May 29, 2006
213
p = SDL_getenv("SDL_VIDEO_X11_ICONWIN");
May 28, 2006
May 28, 2006
214
if (p && *p) {
May 29, 2006
May 29, 2006
215
216
217
218
219
icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root,
0, 0, sicon->w, sicon->h, 0,
CopyFromParent, CopyFromParent);
XSetWindowBackgroundPixmap(SDL_Display, icon_window, icon_pixmap);
XClearWindow(SDL_Display, icon_window);
May 28, 2006
May 28, 2006
220
221
222
}
/* Set the window icon to the icon pixmap (and icon window) */
May 29, 2006
May 29, 2006
223
wmhints = XAllocWMHints();
May 28, 2006
May 28, 2006
224
225
226
227
228
229
230
wmhints->flags = (IconPixmapHint | IconMaskHint);
wmhints->icon_pixmap = icon_pixmap;
wmhints->icon_mask = mask_pixmap;
if (icon_window != None) {
wmhints->flags |= IconWindowHint;
wmhints->icon_window = icon_window;
}
May 29, 2006
May 29, 2006
231
232
233
XSetWMHints(SDL_Display, WMwindow, wmhints);
XFree(wmhints);
XSync(SDL_Display, False);
Apr 26, 2001
Apr 26, 2001
234
235
done:
May 29, 2006
May 29, 2006
236
237
SDL_Unlock_EventThread();
SDL_FreeSurface(sicon);
Apr 26, 2001
Apr 26, 2001
238
239
}
May 28, 2006
May 28, 2006
240
void
May 29, 2006
May 29, 2006
241
X11_SetCaptionNoLock(_THIS, const char *title, const char *icon)
Apr 26, 2001
Apr 26, 2001
242
{
May 28, 2006
May 28, 2006
243
244
XTextProperty titleprop, iconprop;
Status status;
Mar 20, 2006
Mar 20, 2006
245
246
#ifdef X_HAVE_UTF8_STRING
May 28, 2006
May 28, 2006
247
248
249
250
251
Atom _NET_WM_NAME;
Atom _NET_WM_ICON_NAME;
/* Look up some useful Atoms */
if (SDL_X11_HAVE_UTF8) {
May 29, 2006
May 29, 2006
252
_NET_WM_NAME = XInternAtom(SDL_Display, "_NET_WM_NAME", False);
May 28, 2006
May 28, 2006
253
_NET_WM_ICON_NAME =
May 29, 2006
May 29, 2006
254
XInternAtom(SDL_Display, "_NET_WM_ICON_NAME", False);
May 28, 2006
May 28, 2006
255
}
Mar 20, 2006
Mar 20, 2006
256
#endif
Apr 26, 2001
Apr 26, 2001
257
May 28, 2006
May 28, 2006
258
if (title != NULL) {
May 29, 2006
May 29, 2006
259
char *title_latin1 = SDL_iconv_utf8_latin1((char *) title);
May 28, 2006
May 28, 2006
260
if (!title_latin1) {
May 29, 2006
May 29, 2006
261
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
262
263
return;
}
May 29, 2006
May 29, 2006
264
265
status = XStringListToTextProperty(&title_latin1, 1, &titleprop);
SDL_free(title_latin1);
May 28, 2006
May 28, 2006
266
if (status) {
May 29, 2006
May 29, 2006
267
268
XSetTextProperty(SDL_Display, WMwindow, &titleprop, XA_WM_NAME);
XFree(titleprop.value);
May 28, 2006
May 28, 2006
269
}
Jul 25, 2004
Jul 25, 2004
270
#ifdef X_HAVE_UTF8_STRING
May 28, 2006
May 28, 2006
271
if (SDL_X11_HAVE_UTF8) {
May 29, 2006
May 29, 2006
272
273
274
275
status = Xutf8TextListToTextProperty(SDL_Display,
(char **) &title, 1,
XUTF8StringStyle,
&titleprop);
May 28, 2006
May 28, 2006
276
if (status == Success) {
May 29, 2006
May 29, 2006
277
278
279
XSetTextProperty(SDL_Display, WMwindow, &titleprop,
_NET_WM_NAME);
XFree(titleprop.value);
May 28, 2006
May 28, 2006
280
281
}
}
Mar 20, 2006
Mar 20, 2006
282
#endif
May 28, 2006
May 28, 2006
283
284
}
if (icon != NULL) {
May 29, 2006
May 29, 2006
285
char *icon_latin1 = SDL_iconv_utf8_latin1((char *) icon);
May 28, 2006
May 28, 2006
286
if (!icon_latin1) {
May 29, 2006
May 29, 2006
287
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
288
289
return;
}
May 29, 2006
May 29, 2006
290
291
status = XStringListToTextProperty(&icon_latin1, 1, &iconprop);
SDL_free(icon_latin1);
May 28, 2006
May 28, 2006
292
if (status) {
May 29, 2006
May 29, 2006
293
294
295
XSetTextProperty(SDL_Display, WMwindow, &iconprop,
XA_WM_ICON_NAME);
XFree(iconprop.value);
May 28, 2006
May 28, 2006
296
}
Jul 25, 2004
Jul 25, 2004
297
#ifdef X_HAVE_UTF8_STRING
May 28, 2006
May 28, 2006
298
if (SDL_X11_HAVE_UTF8) {
May 29, 2006
May 29, 2006
299
300
301
status = Xutf8TextListToTextProperty(SDL_Display,
(char **) &icon, 1,
XUTF8StringStyle, &iconprop);
May 28, 2006
May 28, 2006
302
if (status == Success) {
May 29, 2006
May 29, 2006
303
304
305
XSetTextProperty(SDL_Display, WMwindow, &iconprop,
_NET_WM_ICON_NAME);
XFree(iconprop.value);
May 28, 2006
May 28, 2006
306
307
}
}
Mar 20, 2006
Mar 20, 2006
308
#endif
May 28, 2006
May 28, 2006
309
}
May 29, 2006
May 29, 2006
310
XSync(SDL_Display, False);
May 17, 2006
May 17, 2006
311
}
Apr 26, 2001
Apr 26, 2001
312
May 28, 2006
May 28, 2006
313
void
May 29, 2006
May 29, 2006
314
X11_SetCaption(_THIS, const char *title, const char *icon)
May 17, 2006
May 17, 2006
315
{
May 29, 2006
May 29, 2006
316
317
318
SDL_Lock_EventThread();
X11_SetCaptionNoLock(this, title, icon);
SDL_Unlock_EventThread();
Apr 26, 2001
Apr 26, 2001
319
320
321
}
/* Iconify the window */
May 28, 2006
May 28, 2006
322
int
May 29, 2006
May 29, 2006
323
X11_IconifyWindow(_THIS)
Apr 26, 2001
Apr 26, 2001
324
{
May 28, 2006
May 28, 2006
325
int result;
Apr 26, 2001
Apr 26, 2001
326
May 29, 2006
May 29, 2006
327
328
329
330
SDL_Lock_EventThread();
result = XIconifyWindow(SDL_Display, WMwindow, SDL_Screen);
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
May 28, 2006
May 28, 2006
331
return (result);
Apr 26, 2001
Apr 26, 2001
332
333
}
May 28, 2006
May 28, 2006
334
SDL_GrabMode
May 29, 2006
May 29, 2006
335
X11_GrabInputNoLock(_THIS, SDL_GrabMode mode)
Apr 26, 2001
Apr 26, 2001
336
{
May 28, 2006
May 28, 2006
337
338
339
340
341
342
343
344
345
int result;
if (SDL_VideoSurface == NULL) {
return (SDL_GRAB_OFF);
}
if (!SDL_Window) {
return (mode); /* Will be set later on mode switch */
}
if (mode == SDL_GRAB_OFF) {
May 29, 2006
May 29, 2006
346
347
XUngrabPointer(SDL_Display, CurrentTime);
XUngrabKeyboard(SDL_Display, CurrentTime);
May 28, 2006
May 28, 2006
348
349
350
} else {
if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
/* Unbind the mouse from the fullscreen window */
May 29, 2006
May 29, 2006
351
XUngrabPointer(SDL_Display, CurrentTime);
May 28, 2006
May 28, 2006
352
353
354
355
}
/* Try to grab the mouse */
#if 0 /* We'll wait here until we actually grab, otherwise behavior undefined */
for (numtries = 0; numtries < 10; ++numtries) {
Jul 9, 2001
Jul 9, 2001
356
#else
May 28, 2006
May 28, 2006
357
for (;;) {
Jul 9, 2001
Jul 9, 2001
358
#endif
May 29, 2006
May 29, 2006
359
360
361
result = XGrabPointer(SDL_Display, SDL_Window, True, 0,
GrabModeAsync, GrabModeAsync,
SDL_Window, None, CurrentTime);
May 28, 2006
May 28, 2006
362
363
364
if (result == GrabSuccess) {
break;
}
May 29, 2006
May 29, 2006
365
SDL_Delay(100);
May 28, 2006
May 28, 2006
366
367
368
369
370
}
if (result != GrabSuccess) {
/* Uh, oh, what do we do here? */ ;
}
/* Now grab the keyboard */
May 29, 2006
May 29, 2006
371
372
XGrabKeyboard(SDL_Display, WMwindow, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
May 28, 2006
May 28, 2006
373
374
375
/* Raise the window if we grab the mouse */
if (!(SDL_VideoSurface->flags & SDL_FULLSCREEN))
May 29, 2006
May 29, 2006
376
XRaiseWindow(SDL_Display, WMwindow);
May 28, 2006
May 28, 2006
377
378
/* Make sure we register input focus */
May 29, 2006
May 29, 2006
379
SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
May 28, 2006
May 28, 2006
380
}
May 29, 2006
May 29, 2006
381
XSync(SDL_Display, False);
May 28, 2006
May 28, 2006
382
383
return (mode);
Apr 26, 2001
Apr 26, 2001
384
385
}
May 28, 2006
May 28, 2006
386
SDL_GrabMode
May 29, 2006
May 29, 2006
387
X11_GrabInput(_THIS, SDL_GrabMode mode)
Apr 26, 2001
Apr 26, 2001
388
{
May 29, 2006
May 29, 2006
389
390
391
SDL_Lock_EventThread();
mode = X11_GrabInputNoLock(this, mode);
SDL_Unlock_EventThread();
Apr 26, 2001
Apr 26, 2001
392
May 28, 2006
May 28, 2006
393
return (mode);
Apr 26, 2001
Apr 26, 2001
394
395
396
397
398
}
/* If 'info' is the right version, this function fills it and returns 1.
Otherwise, in case of a version mismatch, it returns -1.
*/
May 28, 2006
May 28, 2006
399
static void
May 29, 2006
May 29, 2006
400
lock_display(void)
Apr 26, 2001
Apr 26, 2001
401
{
May 29, 2006
May 29, 2006
402
SDL_Lock_EventThread();
Apr 26, 2001
Apr 26, 2001
403
}
May 28, 2006
May 28, 2006
404
static void
May 29, 2006
May 29, 2006
405
unlock_display(void)
Apr 26, 2001
Apr 26, 2001
406
{
May 28, 2006
May 28, 2006
407
408
/* Make sure any X11 transactions are completed */
SDL_VideoDevice *this = current_video;
May 29, 2006
May 29, 2006
409
410
XSync(SDL_Display, False);
SDL_Unlock_EventThread();
Apr 26, 2001
Apr 26, 2001
411
}
May 28, 2006
May 28, 2006
412
413
int
May 29, 2006
May 29, 2006
414
X11_GetWMInfo(_THIS, SDL_SysWMinfo * info)
Apr 26, 2001
Apr 26, 2001
415
{
May 28, 2006
May 28, 2006
416
417
418
419
if (info->version.major <= SDL_MAJOR_VERSION) {
info->subsystem = SDL_SYSWM_X11;
info->info.x11.display = SDL_Display;
info->info.x11.window = SDL_Window;
May 29, 2006
May 29, 2006
420
421
422
if (SDL_VERSIONNUM(info->version.major,
info->version.minor,
info->version.patch) >= 1002) {
May 28, 2006
May 28, 2006
423
424
425
426
427
428
429
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 {
May 29, 2006
May 29, 2006
430
431
SDL_SetError("Application not compiled with SDL %d.%d\n",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
May 28, 2006
May 28, 2006
432
433
return (-1);
}
Apr 26, 2001
Apr 26, 2001
434
}
May 28, 2006
May 28, 2006
435
436
/* vi: set ts=4 sw=4 expandtab: */