SDL  2.0
SDL_x11window.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_X11
24 
25 #include "SDL_assert.h"
26 #include "SDL_hints.h"
27 #include "../SDL_sysvideo.h"
28 #include "../SDL_pixels_c.h"
29 #include "../../events/SDL_keyboard_c.h"
30 #include "../../events/SDL_mouse_c.h"
31 
32 #include "SDL_x11video.h"
33 #include "SDL_x11mouse.h"
34 #include "SDL_x11shape.h"
35 #include "SDL_x11xinput2.h"
36 
37 #if SDL_VIDEO_OPENGL_EGL
38 #include "SDL_x11opengles.h"
39 #endif
40 
41 #include "SDL_timer.h"
42 #include "SDL_syswm.h"
43 #include "SDL_assert.h"
44 
45 #define _NET_WM_STATE_REMOVE 0l
46 #define _NET_WM_STATE_ADD 1l
47 #define _NET_WM_STATE_TOGGLE 2l
48 
49 static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
50 {
51  return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
52 }
53 static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
54 {
55  return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
56 }
57 
58 /*
59 static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
60 {
61  return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
62 }
63 static Bool
64 X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS)
65 {
66  Uint32 start = SDL_GetTicks();
67 
68  while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) {
69  if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) {
70  return False;
71  }
72  }
73  return True;
74 }
75 */
76 
77 static SDL_bool
78 X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
79 {
81  return (data->fswindow != 0);
82 }
83 
84 static SDL_bool
85 X11_IsWindowMapped(_THIS, SDL_Window * window)
86 {
87  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
88  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
89  XWindowAttributes attr;
90 
91  X11_XGetWindowAttributes(videodata->display, data->xwindow, &attr);
92  if (attr.map_state != IsUnmapped) {
93  return SDL_TRUE;
94  } else {
95  return SDL_FALSE;
96  }
97 }
98 
99 #if 0
100 static SDL_bool
101 X11_IsActionAllowed(SDL_Window *window, Atom action)
102 {
103  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
104  Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
105  Atom type;
106  Display *display = data->videodata->display;
107  int form;
108  unsigned long remain;
109  unsigned long len, i;
110  Atom *list;
111  SDL_bool ret = SDL_FALSE;
112 
113  if (X11_XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
114  {
115  for (i=0; i<len; ++i)
116  {
117  if (list[i] == action) {
118  ret = SDL_TRUE;
119  break;
120  }
121  }
122  X11_XFree(list);
123  }
124  return ret;
125 }
126 #endif /* 0 */
127 
128 void
129 X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
130 {
131  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
132  Display *display = videodata->display;
133  Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
134  /* Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN; */
135  Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
136  Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
137  Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
138  Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
139  Atom atoms[5];
140  int count = 0;
141 
142  /* The window manager sets this property, we shouldn't set it.
143  If we did, this would indicate to the window manager that we don't
144  actually want to be mapped during X11_XMapRaised(), which would be bad.
145  *
146  if (flags & SDL_WINDOW_HIDDEN) {
147  atoms[count++] = _NET_WM_STATE_HIDDEN;
148  }
149  */
150  if (flags & SDL_WINDOW_INPUT_FOCUS) {
151  atoms[count++] = _NET_WM_STATE_FOCUSED;
152  }
153  if (flags & SDL_WINDOW_MAXIMIZED) {
154  atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
155  atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
156  }
157  if (flags & SDL_WINDOW_FULLSCREEN) {
158  atoms[count++] = _NET_WM_STATE_FULLSCREEN;
159  }
160  if (count > 0) {
161  X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
162  PropModeReplace, (unsigned char *)atoms, count);
163  } else {
164  X11_XDeleteProperty(display, xwindow, _NET_WM_STATE);
165  }
166 }
167 
168 Uint32
169 X11_GetNetWMState(_THIS, Window xwindow)
170 {
171  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
172  Display *display = videodata->display;
173  Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
174  Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
175  Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
176  Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
177  Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
178  Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
179  Atom actualType;
180  int actualFormat;
181  unsigned long i, numItems, bytesAfter;
182  unsigned char *propertyValue = NULL;
183  long maxLength = 1024;
184  Uint32 flags = 0;
185 
186  if (X11_XGetWindowProperty(display, xwindow, _NET_WM_STATE,
187  0l, maxLength, False, XA_ATOM, &actualType,
188  &actualFormat, &numItems, &bytesAfter,
189  &propertyValue) == Success) {
190  Atom *atoms = (Atom *) propertyValue;
191  int maximized = 0;
192  int fullscreen = 0;
193 
194  for (i = 0; i < numItems; ++i) {
195  if (atoms[i] == _NET_WM_STATE_HIDDEN) {
196  flags |= SDL_WINDOW_HIDDEN;
197  } else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
198  flags |= SDL_WINDOW_INPUT_FOCUS;
199  } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
200  maximized |= 1;
201  } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
202  maximized |= 2;
203  } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
204  fullscreen = 1;
205  }
206  }
207  if (maximized == 3) {
208  flags |= SDL_WINDOW_MAXIMIZED;
209  } else if (fullscreen == 1) {
210  flags |= SDL_WINDOW_FULLSCREEN;
211  }
212  X11_XFree(propertyValue);
213  }
214 
215  /* FIXME, check the size hints for resizable */
216  /* flags |= SDL_WINDOW_RESIZABLE; */
217 
218  return flags;
219 }
220 
221 static int
222 SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
223 {
224  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
225  SDL_WindowData *data;
226  int numwindows = videodata->numwindows;
227  int windowlistlength = videodata->windowlistlength;
228  SDL_WindowData **windowlist = videodata->windowlist;
229 
230  /* Allocate the window data */
231  data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
232  if (!data) {
233  return SDL_OutOfMemory();
234  }
235  data->window = window;
236  data->xwindow = w;
237 #ifdef X_HAVE_UTF8_STRING
238  if (SDL_X11_HAVE_UTF8 && videodata->im) {
239  data->ic =
240  X11_XCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
241  XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
242  NULL);
243  }
244 #endif
245  data->created = created;
246  data->videodata = videodata;
247 
248  /* Associate the data with the window */
249 
250  if (numwindows < windowlistlength) {
251  windowlist[numwindows] = data;
252  videodata->numwindows++;
253  } else {
254  windowlist =
255  (SDL_WindowData **) SDL_realloc(windowlist,
256  (numwindows +
257  1) * sizeof(*windowlist));
258  if (!windowlist) {
259  SDL_free(data);
260  return SDL_OutOfMemory();
261  }
262  windowlist[numwindows] = data;
263  videodata->numwindows++;
264  videodata->windowlistlength++;
265  videodata->windowlist = windowlist;
266  }
267 
268  /* Fill in the SDL window with the window data */
269  {
270  XWindowAttributes attrib;
271 
272  X11_XGetWindowAttributes(data->videodata->display, w, &attrib);
273  window->x = attrib.x;
274  window->y = attrib.y;
275  window->w = attrib.width;
276  window->h = attrib.height;
277  if (attrib.map_state != IsUnmapped) {
278  window->flags |= SDL_WINDOW_SHOWN;
279  } else {
280  window->flags &= ~SDL_WINDOW_SHOWN;
281  }
282  data->visual = attrib.visual;
283  data->colormap = attrib.colormap;
284  }
285 
286  window->flags |= X11_GetNetWMState(_this, w);
287 
288  {
289  Window FocalWindow;
290  int RevertTo=0;
291  X11_XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
292  if (FocalWindow==w)
293  {
294  window->flags |= SDL_WINDOW_INPUT_FOCUS;
295  }
296 
297  if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
299  }
300 
301  if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
302  /* Tell x11 to clip mouse */
303  }
304  }
305 
306  /* All done! */
307  window->driverdata = data;
308  return 0;
309 }
310 
311 static void
312 SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
313 {
314  /*
315  * this code used to check for KWM_WIN_DECORATION, but KDE hasn't
316  * supported it for years and years. It now respects _MOTIF_WM_HINTS.
317  * Gnome is similar: just use the Motif atom.
318  */
319 
320  Atom WM_HINTS = X11_XInternAtom(display, "_MOTIF_WM_HINTS", True);
321  if (WM_HINTS != None) {
322  /* Hints used by Motif compliant window managers */
323  struct
324  {
325  unsigned long flags;
326  unsigned long functions;
327  unsigned long decorations;
328  long input_mode;
329  unsigned long status;
330  } MWMHints = {
331  (1L << 1), 0, border ? 1 : 0, 0, 0
332  };
333 
334  X11_XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
335  PropModeReplace, (unsigned char *) &MWMHints,
336  sizeof(MWMHints) / sizeof(long));
337  } else { /* set the transient hints instead, if necessary */
338  X11_XSetTransientForHint(display, window, RootWindow(display, screen));
339  }
340 }
341 
342 int
344 {
346  SDL_DisplayData *displaydata =
348  SDL_WindowData *windowdata;
349  Display *display = data->display;
350  int screen = displaydata->screen;
351  Visual *visual;
352  int depth;
353  XSetWindowAttributes xattr;
354  Window w;
355  XSizeHints *sizehints;
356  XWMHints *wmhints;
357  XClassHint *classhints;
358  const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
359  Atom _NET_WM_BYPASS_COMPOSITOR;
360  Atom _NET_WM_WINDOW_TYPE;
361  Atom _NET_WM_WINDOW_TYPE_NORMAL;
362  Atom _NET_WM_PID;
363  Atom XdndAware, xdnd_version = 5;
364  long fevent = 0;
365 
366 #if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_EGL
367  if ((window->flags & SDL_WINDOW_OPENGL) &&
368  !SDL_getenv("SDL_VIDEO_X11_VISUALID")) {
369  XVisualInfo *vinfo = NULL;
370 
371 #if SDL_VIDEO_OPENGL_EGL
374  && ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile )
375 #endif
376  ) {
377  vinfo = X11_GLES_GetVisual(_this, display, screen);
378  } else
379 #endif
380  {
381 #if SDL_VIDEO_OPENGL_GLX
382  vinfo = X11_GL_GetVisual(_this, display, screen);
383 #endif
384  }
385 
386  if (!vinfo) {
387  return -1;
388  }
389  visual = vinfo->visual;
390  depth = vinfo->depth;
391  X11_XFree(vinfo);
392  } else
393 #endif
394  {
395  visual = displaydata->visual;
396  depth = displaydata->depth;
397  }
398 
399  xattr.override_redirect = False;
400  xattr.background_pixmap = None;
401  xattr.border_pixel = 0;
402 
403  if (visual->class == DirectColor) {
404  XColor *colorcells;
405  int i;
406  int ncolors;
407  int rmax, gmax, bmax;
408  int rmask, gmask, bmask;
409  int rshift, gshift, bshift;
410 
411  xattr.colormap =
412  X11_XCreateColormap(display, RootWindow(display, screen),
413  visual, AllocAll);
414 
415  /* If we can't create a colormap, then we must die */
416  if (!xattr.colormap) {
417  return SDL_SetError("Could not create writable colormap");
418  }
419 
420  /* OK, we got a colormap, now fill it in as best as we can */
421  colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
422  if (!colorcells) {
423  return SDL_OutOfMemory();
424  }
425  ncolors = visual->map_entries;
426  rmax = 0xffff;
427  gmax = 0xffff;
428  bmax = 0xffff;
429 
430  rshift = 0;
431  rmask = visual->red_mask;
432  while (0 == (rmask & 1)) {
433  rshift++;
434  rmask >>= 1;
435  }
436 
437  gshift = 0;
438  gmask = visual->green_mask;
439  while (0 == (gmask & 1)) {
440  gshift++;
441  gmask >>= 1;
442  }
443 
444  bshift = 0;
445  bmask = visual->blue_mask;
446  while (0 == (bmask & 1)) {
447  bshift++;
448  bmask >>= 1;
449  }
450 
451  /* build the color table pixel values */
452  for (i = 0; i < ncolors; i++) {
453  Uint32 red = (rmax * i) / (ncolors - 1);
454  Uint32 green = (gmax * i) / (ncolors - 1);
455  Uint32 blue = (bmax * i) / (ncolors - 1);
456 
457  Uint32 rbits = (rmask * i) / (ncolors - 1);
458  Uint32 gbits = (gmask * i) / (ncolors - 1);
459  Uint32 bbits = (bmask * i) / (ncolors - 1);
460 
461  Uint32 pix =
462  (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
463 
464  colorcells[i].pixel = pix;
465 
466  colorcells[i].red = red;
467  colorcells[i].green = green;
468  colorcells[i].blue = blue;
469 
470  colorcells[i].flags = DoRed | DoGreen | DoBlue;
471  }
472 
473  X11_XStoreColors(display, xattr.colormap, colorcells, ncolors);
474 
475  SDL_free(colorcells);
476  } else {
477  xattr.colormap =
478  X11_XCreateColormap(display, RootWindow(display, screen),
479  visual, AllocNone);
480  }
481 
482  w = X11_XCreateWindow(display, RootWindow(display, screen),
483  window->x, window->y, window->w, window->h,
484  0, depth, InputOutput, visual,
485  (CWOverrideRedirect | CWBackPixmap | CWBorderPixel |
486  CWColormap), &xattr);
487  if (!w) {
488  return SDL_SetError("Couldn't create window");
489  }
490 
491  SetWindowBordered(display, screen, w,
492  (window->flags & SDL_WINDOW_BORDERLESS) == 0);
493 
494  sizehints = X11_XAllocSizeHints();
495  /* Setup the normal size hints */
496  sizehints->flags = 0;
497  if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
498  sizehints->min_width = sizehints->max_width = window->w;
499  sizehints->min_height = sizehints->max_height = window->h;
500  sizehints->flags |= (PMaxSize | PMinSize);
501  }
502  sizehints->x = window->x;
503  sizehints->y = window->y;
504  sizehints->flags |= USPosition;
505 
506  /* Setup the input hints so we get keyboard input */
507  wmhints = X11_XAllocWMHints();
508  wmhints->input = True;
509  wmhints->flags = InputHint;
510 
511  /* Setup the class hints so we can get an icon (AfterStep) */
512  classhints = X11_XAllocClassHint();
513  classhints->res_name = data->classname;
514  classhints->res_class = data->classname;
515 
516  /* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
517  X11_XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
518 
519  X11_XFree(sizehints);
520  X11_XFree(wmhints);
521  X11_XFree(classhints);
522  /* Set the PID related to the window for the given hostname, if possible */
523  if (data->pid > 0) {
524  _NET_WM_PID = X11_XInternAtom(display, "_NET_WM_PID", False);
525  X11_XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
526  (unsigned char *)&data->pid, 1);
527  }
528 
529  /* Set the window manager state */
530  X11_SetNetWMState(_this, w, window->flags);
531 
532  /* Let the window manager know we're a "normal" window */
533  _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
534  _NET_WM_WINDOW_TYPE_NORMAL = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
535  X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
536  PropModeReplace,
537  (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
538 
539  _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
540  X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
541  PropModeReplace,
542  (unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
543 
544  {
545  Atom protocols[2];
546  int proto_count = 0;
547  const char *ping_hint;
548 
549  protocols[proto_count] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
550  proto_count++;
551 
553  /* Default to using ping if there is no hint */
554  if (!ping_hint || SDL_atoi(ping_hint)) {
555  protocols[proto_count] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
556  proto_count++;
557  }
558 
559  SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
560 
561  X11_XSetWMProtocols(display, w, protocols, proto_count);
562  }
563 
564  if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
565  X11_XDestroyWindow(display, w);
566  return -1;
567  }
568  windowdata = (SDL_WindowData *) window->driverdata;
569 
571  if ((window->flags & SDL_WINDOW_OPENGL) &&
573 #if SDL_VIDEO_OPENGL_GLX
574  && ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile )
575 #endif
576  ) {
577 #if SDL_VIDEO_OPENGL_EGL
578  if (!_this->egl_data) {
579  X11_XDestroyWindow(display, w);
580  return -1;
581  }
582 
583  /* Create the GLES window surface */
584  windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) w);
585 
586  if (windowdata->egl_surface == EGL_NO_SURFACE) {
587  X11_XDestroyWindow(display, w);
588  return SDL_SetError("Could not create GLES window surface");
589  }
590 #else
591  return SDL_SetError("Could not create GLES window surface (no EGL support available)");
592 #endif /* SDL_VIDEO_OPENGL_EGL */
593  }
594 #endif
595 
596 
597 #ifdef X_HAVE_UTF8_STRING
598  if (SDL_X11_HAVE_UTF8 && windowdata->ic) {
599  X11_XGetICValues(windowdata->ic, XNFilterEvents, &fevent, NULL);
600  }
601 #endif
602 
603  X11_Xinput2SelectTouch(_this, window);
604 
605  X11_XSelectInput(display, w,
606  (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
607  ExposureMask | ButtonPressMask | ButtonReleaseMask |
608  PointerMotionMask | KeyPressMask | KeyReleaseMask |
609  PropertyChangeMask | StructureNotifyMask |
610  KeymapStateMask | fevent));
611 
612  XdndAware = X11_XInternAtom(display, "XdndAware", False);
613  X11_XChangeProperty(display, w, XdndAware, XA_ATOM, 32,
614  PropModeReplace,
615  (unsigned char*)&xdnd_version, 1);
616 
617  X11_XFlush(display);
618 
619  return 0;
620 }
621 
622 int
623 X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
624 {
625  Window w = (Window) data;
626 
627  window->title = X11_GetWindowTitle(_this, w);
628 
629  if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
630  return -1;
631  }
632  return 0;
633 }
634 
635 char *
636 X11_GetWindowTitle(_THIS, Window xwindow)
637 {
639  Display *display = data->display;
640  int status, real_format;
641  Atom real_type;
642  unsigned long items_read, items_left;
643  unsigned char *propdata;
644  char *title = NULL;
645 
646  status = X11_XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
647  0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
648  &items_read, &items_left, &propdata);
649  if (status == Success && propdata) {
650  title = SDL_strdup(SDL_static_cast(char*, propdata));
651  X11_XFree(propdata);
652  } else {
653  status = X11_XGetWindowProperty(display, xwindow, XA_WM_NAME,
654  0L, 8192L, False, XA_STRING, &real_type, &real_format,
655  &items_read, &items_left, &propdata);
656  if (status == Success && propdata) {
657  title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
658  X11_XFree(propdata);
659  } else {
660  title = SDL_strdup("");
661  }
662  }
663  return title;
664 }
665 
666 void
668 {
669  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
670  Display *display = data->videodata->display;
671  XTextProperty titleprop;
672  Status status;
673  const char *title = window->title ? window->title : "";
674  char *title_locale = NULL;
675 
676 #ifdef X_HAVE_UTF8_STRING
677  Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
678 #endif
679 
680  title_locale = SDL_iconv_utf8_locale(title);
681  if (!title_locale) {
682  SDL_OutOfMemory();
683  return;
684  }
685 
686  status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
687  SDL_free(title_locale);
688  if (status) {
689  X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
690  X11_XFree(titleprop.value);
691  }
692 #ifdef X_HAVE_UTF8_STRING
693  if (SDL_X11_HAVE_UTF8) {
694  status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1,
695  XUTF8StringStyle, &titleprop);
696  if (status == Success) {
697  X11_XSetTextProperty(display, data->xwindow, &titleprop,
698  _NET_WM_NAME);
699  X11_XFree(titleprop.value);
700  }
701  }
702 #endif
703 
704  X11_XFlush(display);
705 }
706 
707 void
709 {
710  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
711  Display *display = data->videodata->display;
712  Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
713 
714  if (icon) {
715  int propsize;
716  long *propdata;
717 
718  /* Set the _NET_WM_ICON property */
720  propsize = 2 + (icon->w * icon->h);
721  propdata = SDL_malloc(propsize * sizeof(long));
722  if (propdata) {
723  int x, y;
724  Uint32 *src;
725  long *dst;
726 
727  propdata[0] = icon->w;
728  propdata[1] = icon->h;
729  dst = &propdata[2];
730  for (y = 0; y < icon->h; ++y) {
731  src = (Uint32*)((Uint8*)icon->pixels + y * icon->pitch);
732  for (x = 0; x < icon->w; ++x) {
733  *dst++ = *src++;
734  }
735  }
736  X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
737  32, PropModeReplace, (unsigned char *) propdata,
738  propsize);
739  }
740  SDL_free(propdata);
741  } else {
742  X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
743  }
744  X11_XFlush(display);
745 }
746 
747 void
749 {
750  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
751  Display *display = data->videodata->display;
752 
753  X11_XMoveWindow(display, data->xwindow, window->x, window->y);
754  X11_XFlush(display);
755 }
756 
757 void
759 {
760  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
761  Display *display = data->videodata->display;
762 
763  if (window->flags & SDL_WINDOW_RESIZABLE) {
764  XSizeHints *sizehints = X11_XAllocSizeHints();
765  long userhints;
766 
767  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
768 
769  sizehints->min_width = window->min_w;
770  sizehints->min_height = window->min_h;
771  sizehints->flags |= PMinSize;
772 
773  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
774 
775  X11_XFree(sizehints);
776 
777  /* See comment in X11_SetWindowSize. */
778  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
779  X11_XMoveWindow(display, data->xwindow, window->x, window->y);
780  X11_XRaiseWindow(display, data->xwindow);
781  }
782 
783  X11_XFlush(display);
784 }
785 
786 void
788 {
789  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
790  Display *display = data->videodata->display;
791 
792  if (window->flags & SDL_WINDOW_RESIZABLE) {
793  XSizeHints *sizehints = X11_XAllocSizeHints();
794  long userhints;
795 
796  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
797 
798  sizehints->max_width = window->max_w;
799  sizehints->max_height = window->max_h;
800  sizehints->flags |= PMaxSize;
801 
802  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
803 
804  X11_XFree(sizehints);
805 
806  /* See comment in X11_SetWindowSize. */
807  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
808  X11_XMoveWindow(display, data->xwindow, window->x, window->y);
809  X11_XRaiseWindow(display, data->xwindow);
810  }
811 
812  X11_XFlush(display);
813 }
814 
815 void
817 {
818  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
819  Display *display = data->videodata->display;
820 
821  if (SDL_IsShapedWindow(window)) {
822  X11_ResizeWindowShape(window);
823  }
824  if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
825  /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus
826  we must set the size hints to adjust the window size. */
827  XSizeHints *sizehints = X11_XAllocSizeHints();
828  long userhints;
829 
830  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
831 
832  sizehints->min_width = sizehints->max_width = window->w;
833  sizehints->min_height = sizehints->max_height = window->h;
834  sizehints->flags |= PMinSize | PMaxSize;
835 
836  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
837 
838  X11_XFree(sizehints);
839 
840  /* From Pierre-Loup:
841  WMs each have their little quirks with that. When you change the
842  size hints, they get a ConfigureNotify event with the
843  WM_NORMAL_SIZE_HINTS Atom. They all save the hints then, but they
844  don't all resize the window right away to enforce the new hints.
845 
846  Some of them resize only after:
847  - A user-initiated move or resize
848  - A code-initiated move or resize
849  - Hiding & showing window (Unmap & map)
850 
851  The following move & resize seems to help a lot of WMs that didn't
852  properly update after the hints were changed. We don't do a
853  hide/show, because there are supposedly subtle problems with doing so
854  and transitioning from windowed to fullscreen in Unity.
855  */
856  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
857  X11_XMoveWindow(display, data->xwindow, window->x, window->y);
858  X11_XRaiseWindow(display, data->xwindow);
859  } else {
860  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
861  }
862 
863  X11_XFlush(display);
864 }
865 
866 void
867 X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
868 {
869  const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
870  const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
871  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
872  SDL_DisplayData *displaydata =
874  Display *display = data->videodata->display;
875  XEvent event;
876 
877  SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
878  X11_XFlush(display);
879 
880  if (visible) {
881  XWindowAttributes attr;
882  do {
883  X11_XSync(display, False);
884  X11_XGetWindowAttributes(display, data->xwindow, &attr);
885  } while (attr.map_state != IsViewable);
886 
887  if (focused) {
888  X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
889  }
890  }
891 
892  /* make sure these don't make it to the real event queue if they fired here. */
893  X11_XSync(display, False);
894  X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
895  X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
896 }
897 
898 void
900 {
901  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
902  Display *display = data->videodata->display;
903  XEvent event;
904 
905  if (!X11_IsWindowMapped(_this, window)) {
906  X11_XMapRaised(display, data->xwindow);
907  /* Blocking wait for "MapNotify" event.
908  * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type,
909  * and XCheckTypedWindowEvent doesn't block */
910  X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
911  X11_XFlush(display);
912  }
913 
914  if (!data->videodata->net_wm) {
915  /* no WM means no FocusIn event, which confuses us. Force it. */
916  X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
917  X11_XFlush(display);
918  }
919 }
920 
921 void
923 {
924  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
926  Display *display = data->videodata->display;
927  XEvent event;
928 
929  if (X11_IsWindowMapped(_this, window)) {
930  X11_XWithdrawWindow(display, data->xwindow, displaydata->screen);
931  /* Blocking wait for "UnmapNotify" event */
932  X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
933  X11_XFlush(display);
934  }
935 }
936 
937 static void
938 SetWindowActive(_THIS, SDL_Window * window)
939 {
940  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
941  SDL_DisplayData *displaydata =
943  Display *display = data->videodata->display;
944  Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
945 
946  if (X11_IsWindowMapped(_this, window)) {
947  XEvent e;
948 
949  SDL_zero(e);
950  e.xany.type = ClientMessage;
951  e.xclient.message_type = _NET_ACTIVE_WINDOW;
952  e.xclient.format = 32;
953  e.xclient.window = data->xwindow;
954  e.xclient.data.l[0] = 1; /* source indication. 1 = application */
955  e.xclient.data.l[1] = CurrentTime;
956  e.xclient.data.l[2] = 0;
957 
958  X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
959  SubstructureNotifyMask | SubstructureRedirectMask, &e);
960 
961  X11_XFlush(display);
962  }
963 }
964 
965 void
967 {
968  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
969  Display *display = data->videodata->display;
970 
971  X11_XRaiseWindow(display, data->xwindow);
972  SetWindowActive(_this, window);
973  X11_XFlush(display);
974 }
975 
976 static void
977 SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
978 {
979  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
980  SDL_DisplayData *displaydata =
982  Display *display = data->videodata->display;
983  Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
984  Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
985  Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
986 
987  if (maximized) {
988  window->flags |= SDL_WINDOW_MAXIMIZED;
989  } else {
990  window->flags &= ~SDL_WINDOW_MAXIMIZED;
991  }
992 
993  if (X11_IsWindowMapped(_this, window)) {
994  XEvent e;
995 
996  SDL_zero(e);
997  e.xany.type = ClientMessage;
998  e.xclient.message_type = _NET_WM_STATE;
999  e.xclient.format = 32;
1000  e.xclient.window = data->xwindow;
1001  e.xclient.data.l[0] =
1002  maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
1003  e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
1004  e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
1005  e.xclient.data.l[3] = 0l;
1006 
1007  X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
1008  SubstructureNotifyMask | SubstructureRedirectMask, &e);
1009  } else {
1010  X11_SetNetWMState(_this, data->xwindow, window->flags);
1011  }
1012  X11_XFlush(display);
1013 }
1014 
1015 void
1017 {
1018  SetWindowMaximized(_this, window, SDL_TRUE);
1019 }
1020 
1021 void
1023 {
1024  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1025  SDL_DisplayData *displaydata =
1027  Display *display = data->videodata->display;
1028 
1029  X11_XIconifyWindow(display, data->xwindow, displaydata->screen);
1030  X11_XFlush(display);
1031 }
1032 
1033 void
1035 {
1036  SetWindowMaximized(_this, window, SDL_FALSE);
1037  X11_ShowWindow(_this, window);
1038  SetWindowActive(_this, window);
1039 }
1040 
1041 /* This asks the Window Manager to handle fullscreen for us. Most don't do it right, though. */
1042 static void
1043 X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
1044 {
1045  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1046  SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
1047  Display *display = data->videodata->display;
1048  Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
1049  Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
1050 
1051  if (X11_IsWindowMapped(_this, window)) {
1052  XEvent e;
1053 
1054  if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
1055  /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
1056  can be resized to the fullscreen resolution (or reset so we're not resizable again) */
1057  XSizeHints *sizehints = X11_XAllocSizeHints();
1058  long flags = 0;
1059  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
1060  /* set the resize flags on */
1061  if (fullscreen) {
1062  /* we are going fullscreen so turn the flags off */
1063  sizehints->flags &= ~(PMinSize | PMaxSize);
1064  } else {
1065  /* Reset the min/max width height to make the window non-resizable again */
1066  sizehints->flags |= PMinSize | PMaxSize;
1067  sizehints->min_width = sizehints->max_width = window->windowed.w;
1068  sizehints->min_height = sizehints->max_height = window->windowed.h;
1069  }
1070  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
1071  X11_XFree(sizehints);
1072  }
1073 
1074  SDL_zero(e);
1075  e.xany.type = ClientMessage;
1076  e.xclient.message_type = _NET_WM_STATE;
1077  e.xclient.format = 32;
1078  e.xclient.window = data->xwindow;
1079  e.xclient.data.l[0] =
1080  fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
1081  e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
1082  e.xclient.data.l[3] = 0l;
1083 
1084  X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
1085  SubstructureNotifyMask | SubstructureRedirectMask, &e);
1086  } else {
1087  Uint32 flags;
1088 
1089  flags = window->flags;
1090  if (fullscreen) {
1091  flags |= SDL_WINDOW_FULLSCREEN;
1092  } else {
1093  flags &= ~SDL_WINDOW_FULLSCREEN;
1094  }
1095  X11_SetNetWMState(_this, data->xwindow, flags);
1096  }
1097 
1098  if (data->visual->class == DirectColor) {
1099  if ( fullscreen ) {
1100  X11_XInstallColormap(display, data->colormap);
1101  } else {
1102  X11_XUninstallColormap(display, data->colormap);
1103  }
1104  }
1105 
1106  X11_XFlush(display);
1107 }
1108 
1109 /* This handles fullscreen itself, outside the Window Manager. */
1110 static void
1111 X11_BeginWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
1112 {
1113  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1114  SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
1115  Visual *visual = data->visual;
1116  Display *display = data->videodata->display;
1117  const int screen = displaydata->screen;
1118  Window root = RootWindow(display, screen);
1119  const int def_vis = (visual == DefaultVisual(display, screen));
1120  unsigned long xattrmask = 0;
1121  XSetWindowAttributes xattr;
1122  XEvent ev;
1123  SDL_Rect rect;
1124 
1125  if ( data->fswindow ) {
1126  return; /* already fullscreen, I hope. */
1127  }
1128 
1129  X11_GetDisplayBounds(_this, _display, &rect);
1130 
1131  SDL_zero(xattr);
1132  xattr.override_redirect = True;
1133  xattrmask |= CWOverrideRedirect;
1134  xattr.background_pixel = def_vis ? BlackPixel(display, screen) : 0;
1135  xattrmask |= CWBackPixel;
1136  xattr.border_pixel = 0;
1137  xattrmask |= CWBorderPixel;
1138  xattr.colormap = data->colormap;
1139  xattrmask |= CWColormap;
1140 
1141  data->fswindow = X11_XCreateWindow(display, root,
1142  rect.x, rect.y, rect.w, rect.h, 0,
1143  displaydata->depth, InputOutput,
1144  visual, xattrmask, &xattr);
1145 
1146  X11_XSelectInput(display, data->fswindow, StructureNotifyMask);
1147  X11_XSetWindowBackground(display, data->fswindow, 0);
1148  X11_XInstallColormap(display, data->colormap);
1149  X11_XClearWindow(display, data->fswindow);
1150  X11_XMapRaised(display, data->fswindow);
1151 
1152  /* Make sure the fswindow is in view by warping mouse to the corner */
1153  X11_XUngrabPointer(display, CurrentTime);
1154  X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
1155 
1156  /* Wait to be mapped, filter Unmap event out if it arrives. */
1157  X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
1158  X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
1159 
1160 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
1161  if ( displaydata->use_vidmode ) {
1162  X11_XF86VidModeLockModeSwitch(display, screen, True);
1163  }
1164 #endif
1165 
1166  SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
1167 
1168  /* Center actual window within our cover-the-screen window. */
1169  X11_XReparentWindow(display, data->xwindow, data->fswindow,
1170  (rect.w - window->w) / 2, (rect.h - window->h) / 2);
1171 
1172  /* Move the mouse to the upper left to make sure it's on-screen */
1173  X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
1174 
1175  /* Center mouse in the fullscreen window. */
1176  rect.x += (rect.w / 2);
1177  rect.y += (rect.h / 2);
1178  X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
1179 
1180  /* Wait to be mapped, filter Unmap event out if it arrives. */
1181  X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
1182  X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
1183 
1184  SDL_UpdateWindowGrab(window);
1185 }
1186 
1187 static void
1188 X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
1189 {
1190  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1191  SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
1192  Display *display = data->videodata->display;
1193  const int screen = displaydata->screen;
1194  Window root = RootWindow(display, screen);
1195  Window fswindow = data->fswindow;
1196  XEvent ev;
1197 
1198  if (!data->fswindow) {
1199  return; /* already not fullscreen, I hope. */
1200  }
1201 
1202  data->fswindow = None;
1203 
1204 #if SDL_VIDEO_DRIVER_X11_VIDMODE
1205  if ( displaydata->use_vidmode ) {
1206  X11_XF86VidModeLockModeSwitch(display, screen, False);
1207  }
1208 #endif
1209 
1210  SDL_UpdateWindowGrab(window);
1211 
1212  X11_XReparentWindow(display, data->xwindow, root, window->x, window->y);
1213 
1214  /* flush these events so they don't confuse normal event handling */
1215  X11_XSync(display, False);
1216  X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
1217  X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
1218 
1219  SetWindowBordered(display, screen, data->xwindow,
1220  (window->flags & SDL_WINDOW_BORDERLESS) == 0);
1221 
1222  X11_XWithdrawWindow(display, fswindow, screen);
1223 
1224  /* Wait to be unmapped. */
1225  X11_XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
1226  X11_XDestroyWindow(display, fswindow);
1227 }
1228 
1229 
1230 void
1231 X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
1232 {
1233  /* !!! FIXME: SDL_Hint? */
1234  SDL_bool legacy = SDL_FALSE;
1235  const char *env = SDL_getenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN");
1236  if (env) {
1237  legacy = SDL_atoi(env);
1238  } else {
1239  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1240  SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
1241  if ( displaydata->use_vidmode ) {
1242  legacy = SDL_TRUE; /* the new stuff only works with XRandR. */
1243  } else if ( !videodata->net_wm ) {
1244  legacy = SDL_TRUE; /* The window manager doesn't support it */
1245  } else {
1246  /* !!! FIXME: look at the window manager name, and blacklist certain ones? */
1247  /* http://stackoverflow.com/questions/758648/find-the-name-of-the-x-window-manager */
1248  legacy = SDL_FALSE; /* try the new way. */
1249  }
1250  }
1251 
1252  if (legacy) {
1253  if (fullscreen) {
1254  X11_BeginWindowFullscreenLegacy(_this, window, _display);
1255  } else {
1256  X11_EndWindowFullscreenLegacy(_this, window, _display);
1257  }
1258  } else {
1259  X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen);
1260  }
1261 }
1262 
1263 
1264 int
1265 X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
1266 {
1267  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1268  Display *display = data->videodata->display;
1269  Visual *visual = data->visual;
1270  Colormap colormap = data->colormap;
1271  XColor *colorcells;
1272  int ncolors;
1273  int rmask, gmask, bmask;
1274  int rshift, gshift, bshift;
1275  int i;
1276 
1277  if (visual->class != DirectColor) {
1278  return SDL_SetError("Window doesn't have DirectColor visual");
1279  }
1280 
1281  ncolors = visual->map_entries;
1282  colorcells = SDL_malloc(ncolors * sizeof(XColor));
1283  if (!colorcells) {
1284  return SDL_OutOfMemory();
1285  }
1286 
1287  rshift = 0;
1288  rmask = visual->red_mask;
1289  while (0 == (rmask & 1)) {
1290  rshift++;
1291  rmask >>= 1;
1292  }
1293 
1294  gshift = 0;
1295  gmask = visual->green_mask;
1296  while (0 == (gmask & 1)) {
1297  gshift++;
1298  gmask >>= 1;
1299  }
1300 
1301  bshift = 0;
1302  bmask = visual->blue_mask;
1303  while (0 == (bmask & 1)) {
1304  bshift++;
1305  bmask >>= 1;
1306  }
1307 
1308  /* build the color table pixel values */
1309  for (i = 0; i < ncolors; i++) {
1310  Uint32 rbits = (rmask * i) / (ncolors - 1);
1311  Uint32 gbits = (gmask * i) / (ncolors - 1);
1312  Uint32 bbits = (bmask * i) / (ncolors - 1);
1313  Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
1314 
1315  colorcells[i].pixel = pix;
1316 
1317  colorcells[i].red = ramp[(0 * 256) + i];
1318  colorcells[i].green = ramp[(1 * 256) + i];
1319  colorcells[i].blue = ramp[(2 * 256) + i];
1320 
1321  colorcells[i].flags = DoRed | DoGreen | DoBlue;
1322  }
1323 
1324  X11_XStoreColors(display, colormap, colorcells, ncolors);
1325  X11_XFlush(display);
1326  SDL_free(colorcells);
1327 
1328  return 0;
1329 }
1330 
1331 void
1332 X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
1333 {
1334  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1335  Display *display = data->videodata->display;
1336  SDL_bool oldstyle_fullscreen;
1337  SDL_bool grab_keyboard;
1338  const char *hint;
1339 
1340  /* ICCCM2.0-compliant window managers can handle fullscreen windows
1341  If we're using XVidMode to change resolution we need to confine
1342  the cursor so we don't pan around the virtual desktop.
1343  */
1344  oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
1345 
1346  if (oldstyle_fullscreen || grabbed) {
1347  /* Try to grab the mouse */
1348  for (;;) {
1349  int result =
1350  X11_XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
1351  GrabModeAsync, data->xwindow, None, CurrentTime);
1352  if (result == GrabSuccess) {
1353  break;
1354  }
1355  SDL_Delay(50);
1356  }
1357 
1358  /* Raise the window if we grab the mouse */
1359  X11_XRaiseWindow(display, data->xwindow);
1360 
1361  /* Now grab the keyboard */
1363  if (hint && SDL_atoi(hint)) {
1364  grab_keyboard = SDL_TRUE;
1365  } else {
1366  /* We need to do this with the old style override_redirect
1367  fullscreen window otherwise we won't get keyboard focus.
1368  */
1369  grab_keyboard = oldstyle_fullscreen;
1370  }
1371  if (grab_keyboard) {
1372  X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
1373  GrabModeAsync, CurrentTime);
1374  }
1375  } else {
1376  X11_XUngrabPointer(display, CurrentTime);
1377  X11_XUngrabKeyboard(display, CurrentTime);
1378  }
1379  X11_XSync(display, False);
1380 }
1381 
1382 void
1384 {
1385  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1386 
1387  if (data) {
1388  SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
1389  Display *display = videodata->display;
1390  int numwindows = videodata->numwindows;
1391  SDL_WindowData **windowlist = videodata->windowlist;
1392  int i;
1393 
1394  if (windowlist) {
1395  for (i = 0; i < numwindows; ++i) {
1396  if (windowlist[i] && (windowlist[i]->window == window)) {
1397  windowlist[i] = windowlist[numwindows - 1];
1398  windowlist[numwindows - 1] = NULL;
1399  videodata->numwindows--;
1400  break;
1401  }
1402  }
1403  }
1404 #ifdef X_HAVE_UTF8_STRING
1405  if (data->ic) {
1406  X11_XDestroyIC(data->ic);
1407  }
1408 #endif
1409  if (data->created) {
1410  X11_XDestroyWindow(display, data->xwindow);
1411  X11_XFlush(display);
1412  }
1413  SDL_free(data);
1414  }
1415  window->driverdata = NULL;
1416 }
1417 
1418 SDL_bool
1420 {
1421  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1422  Display *display = data->videodata->display;
1423 
1424  if (info->version.major == SDL_MAJOR_VERSION &&
1425  info->version.minor == SDL_MINOR_VERSION) {
1426  info->subsystem = SDL_SYSWM_X11;
1427  info->info.x11.display = display;
1428  info->info.x11.window = data->xwindow;
1429  return SDL_TRUE;
1430  } else {
1431  SDL_SetError("Application not compiled with SDL %d.%d\n",
1433  return SDL_FALSE;
1434  }
1435 }
1436 
1437 int
1439 {
1440  return 0; /* just succeed, the real work is done elsewhere. */
1441 }
1442 
1443 #endif /* SDL_VIDEO_DRIVER_X11 */
1444 
1445 /* vi: set ts=4 sw=4 expandtab: */
void SDL_UpdateWindowGrab(SDL_Window *window)
Definition: SDL_video.c:2227
GLenum GLenum dst
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
Atom _NET_WM_STATE_FULLSCREEN
Definition: SDL_x11video.h:96
int X11_ResizeWindowShape(SDL_Window *window)
Atom _NET_WM_ALLOWED_ACTIONS
Definition: SDL_x11video.h:97
void X11_SetWindowTitle(_THIS, SDL_Window *window)
#define SDL_IsShapedWindow
Visual * visual
Definition: SDL_x11window.h:48
GLuint64EXT * result
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
Uint32 X11_GetNetWMState(_THIS, Window xwindow)
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
#define SDL_VIDEO_OPENGL_GLX
Atom _NET_WM_STATE_MAXIMIZED_VERT
Definition: SDL_x11video.h:94
Colormap colormap
Definition: SDL_x11window.h:49
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display dpy)
Definition: SDL_x11sym.h:36
SDL_Rect rect
Definition: testrelative.c:27
struct wl_display * display
SDL_Window * window
int windowlistlength
Definition: SDL_x11video.h:83
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
#define SDL_GetHint
SDL_version version
Definition: SDL_syswm.h:183
Uint8 major
Definition: SDL_version.h:53
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:82
#define SDL_VIDEO_OPENGL_ES
Definition: SDL_config.h:327
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:184
void X11_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
void X11_MinimizeWindow(_THIS, SDL_Window *window)
SDL_Window * window
void X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
#define SDL_realloc
SDL_Rect windowed
Definition: SDL_sysvideo.h:85
GLenum GLsizei len
#define SDL_VIDEO_OPENGL_ES2
Definition: SDL_config.h:328
void X11_MaximizeWindow(_THIS, SDL_Window *window)
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:333
#define SDL_HINT_GRAB_KEYBOARD
A variable controlling whether grabbing input grabs the keyboard.
Definition: SDL_hints.h:233
const GLubyte GLuint red
Definition: SDL_glfuncs.h:78
int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay *sdl_display, SDL_Rect *rect)
Atom _NET_WM_STATE
Definition: SDL_x11video.h:91
GLsizei maxLength
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_bool
Definition: SDL_stdinc.h:126
struct SDL_VideoDevice::@29 gl_config
#define SDL_iconv_utf8_locale(S)
Definition: SDL_stdinc.h:482
char * classname
Definition: SDL_x11video.h:77
Atom _NET_WM_STATE_HIDDEN
Definition: SDL_x11video.h:92
#define SDL_HINT_VIDEO_X11_NET_WM_PING
A variable controlling whether the X11 _NET_WM_PING protocol should be supported. ...
Definition: SDL_hints.h:200
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
Atom _NET_ACTIVE_WINDOW
Definition: SDL_x11video.h:103
Atom WM_DELETE_WINDOW
Definition: SDL_x11video.h:90
void * SDL_calloc(size_t nmemb, size_t size)
int X11_CreateWindow(_THIS, SDL_Window *window)
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
void * pixels
Definition: SDL_surface.h:75
int X11_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
#define _THIS
struct SDL_VideoData * videodata
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
struct _cl_event * event
void SDL_free(void *mem)
int X11_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
#define SDL_static_cast(type, expression)
Definition: SDL_stdinc.h:109
void X11_RestoreWindow(_THIS, SDL_Window *window)
Uint8 minor
Definition: SDL_version.h:54
GLbyte GLbyte blue
#define SDL_zero(x)
Definition: SDL_stdinc.h:355
char * title
Definition: SDL_sysvideo.h:75
int x
Definition: SDL_rect.h:66
void X11_ShowWindow(_THIS, SDL_Window *window)
void X11_DestroyWindow(_THIS, SDL_Window *window)
int w
Definition: SDL_rect.h:67
struct SDL_SysWMinfo::@18::@19 x11
#define SDL_atoi
#define SDL_Delay
GLenum GLenum GLsizei const GLuint GLboolean enabled
#define SDL_getenv
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
#define SDL_assert(condition)
Definition: SDL_assert.h:167
void X11_SetWindowMinimumSize(_THIS, SDL_Window *window)
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_PixelFormat * format
Definition: SDL_surface.h:72
GLint GLint GLsizei GLsizei GLsizei depth
Definition: SDL_opengl.h:1565
Atom _NET_WM_STATE_MAXIMIZED_HORZ
Definition: SDL_x11video.h:95
#define SDL_SetError
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1039
int h
Definition: SDL_rect.h:67
#define SDL_strdup
The type used to identify a window.
Definition: SDL_sysvideo.h:71
Atom _NET_WM_STATE_FOCUSED
Definition: SDL_x11video.h:93
void X11_RaiseWindow(_THIS, SDL_Window *window)
#define SDL_iconv_string
SDL_bool net_wm
Definition: SDL_x11video.h:86
void X11_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
char * X11_GetWindowTitle(_THIS, Window xwindow)
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: SDL_opengl.h:1565
GLbyte green
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
union SDL_SysWMinfo::@18 info
GLbitfield flags
#define SDL_malloc
GLubyte GLubyte GLubyte GLubyte w
void * driverdata
Definition: SDL_sysvideo.h:106
void X11_SetWindowSize(_THIS, SDL_Window *window)
Uint32 flags
Definition: SDL_sysvideo.h:81
GLenum src
void X11_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
void X11_HideWindow(_THIS, SDL_Window *window)
SDL_Renderer * screen
void X11_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
int y
Definition: SDL_rect.h:66
EGLSurface egl_surface
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
void X11_SetWindowMaximumSize(_THIS, SDL_Window *window)
void X11_Xinput2SelectTouch(_THIS, SDL_Window *window)
void X11_SetWindowPosition(_THIS, SDL_Window *window)