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