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 
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_log.h"
44 
45 #define _NET_WM_STATE_REMOVE 0l
46 #define _NET_WM_STATE_ADD 1l
47 
48 static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
49 {
50  return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
51 }
52 static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
53 {
54  return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
55 }
56 
57 /*
58 static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
59 {
60  return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
61 }
62 static Bool
63 X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS)
64 {
65  Uint32 start = SDL_GetTicks();
66 
67  while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) {
68  if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) {
69  return False;
70  }
71  }
72  return True;
73 }
74 */
75 
76 static SDL_bool
77 X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
78 {
80  return (data->fswindow != 0);
81 }
82 
83 static SDL_bool
84 X11_IsWindowMapped(_THIS, SDL_Window * window)
85 {
86  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
87  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
88  XWindowAttributes attr;
89 
90  X11_XGetWindowAttributes(videodata->display, data->xwindow, &attr);
91  if (attr.map_state != IsUnmapped) {
92  return SDL_TRUE;
93  } else {
94  return SDL_FALSE;
95  }
96 }
97 
98 #if 0
99 static SDL_bool
100 X11_IsActionAllowed(SDL_Window *window, Atom action)
101 {
102  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
103  Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
104  Atom type;
105  Display *display = data->videodata->display;
106  int form;
107  unsigned long remain;
108  unsigned long len, i;
109  Atom *list;
110  SDL_bool ret = SDL_FALSE;
111 
112  if (X11_XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
113  {
114  for (i=0; i<len; ++i)
115  {
116  if (list[i] == action) {
117  ret = SDL_TRUE;
118  break;
119  }
120  }
121  X11_XFree(list);
122  }
123  return ret;
124 }
125 #endif /* 0 */
126 
127 void
128 X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
129 {
130  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
131  Display *display = videodata->display;
132  /* !!! FIXME: just dereference videodata below instead of copying to locals. */
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 _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
140  Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
141  Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
142  Atom atoms[16];
143  int count = 0;
144 
145  /* The window manager sets this property, we shouldn't set it.
146  If we did, this would indicate to the window manager that we don't
147  actually want to be mapped during X11_XMapRaised(), which would be bad.
148  *
149  if (flags & SDL_WINDOW_HIDDEN) {
150  atoms[count++] = _NET_WM_STATE_HIDDEN;
151  }
152  */
153 
154  if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
155  atoms[count++] = _NET_WM_STATE_ABOVE;
156  }
157  if (flags & SDL_WINDOW_SKIP_TASKBAR) {
158  atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR;
159  atoms[count++] = _NET_WM_STATE_SKIP_PAGER;
160  }
161  if (flags & SDL_WINDOW_INPUT_FOCUS) {
162  atoms[count++] = _NET_WM_STATE_FOCUSED;
163  }
164  if (flags & SDL_WINDOW_MAXIMIZED) {
165  atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
166  atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
167  }
168  if (flags & SDL_WINDOW_FULLSCREEN) {
169  atoms[count++] = _NET_WM_STATE_FULLSCREEN;
170  }
171 
172  SDL_assert(count <= SDL_arraysize(atoms));
173 
174  if (count > 0) {
175  X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
176  PropModeReplace, (unsigned char *)atoms, count);
177  } else {
178  X11_XDeleteProperty(display, xwindow, _NET_WM_STATE);
179  }
180 }
181 
182 Uint32
183 X11_GetNetWMState(_THIS, Window xwindow)
184 {
185  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
186  Display *display = videodata->display;
187  Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
188  Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
189  Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
190  Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
191  Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
192  Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
193  Atom actualType;
194  int actualFormat;
195  unsigned long i, numItems, bytesAfter;
196  unsigned char *propertyValue = NULL;
197  long maxLength = 1024;
198  Uint32 flags = 0;
199 
200  if (X11_XGetWindowProperty(display, xwindow, _NET_WM_STATE,
201  0l, maxLength, False, XA_ATOM, &actualType,
202  &actualFormat, &numItems, &bytesAfter,
203  &propertyValue) == Success) {
204  Atom *atoms = (Atom *) propertyValue;
205  int maximized = 0;
206  int fullscreen = 0;
207 
208  for (i = 0; i < numItems; ++i) {
209  if (atoms[i] == _NET_WM_STATE_HIDDEN) {
210  flags |= SDL_WINDOW_HIDDEN;
211  } else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
212  flags |= SDL_WINDOW_INPUT_FOCUS;
213  } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
214  maximized |= 1;
215  } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
216  maximized |= 2;
217  } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
218  fullscreen = 1;
219  }
220  }
221  if (maximized == 3) {
222  flags |= SDL_WINDOW_MAXIMIZED;
223  }
224 
225  if (fullscreen == 1) {
226  flags |= SDL_WINDOW_FULLSCREEN;
227  }
228 
229  /* If the window is unmapped, numItems will be zero and _NET_WM_STATE_HIDDEN
230  * will not be set. Do an additional check to see if the window is unmapped
231  * and mark it as SDL_WINDOW_HIDDEN if it is.
232  */
233  {
234  XWindowAttributes attr;
235  SDL_memset(&attr,0,sizeof(attr));
236  X11_XGetWindowAttributes(videodata->display, xwindow, &attr);
237  if (attr.map_state == IsUnmapped) {
238  flags |= SDL_WINDOW_HIDDEN;
239  }
240  }
241  X11_XFree(propertyValue);
242  }
243 
244  /* FIXME, check the size hints for resizable */
245  /* flags |= SDL_WINDOW_RESIZABLE; */
246 
247  return flags;
248 }
249 
250 static int
251 SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
252 {
253  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
254  SDL_WindowData *data;
255  int numwindows = videodata->numwindows;
256  int windowlistlength = videodata->windowlistlength;
257  SDL_WindowData **windowlist = videodata->windowlist;
258 
259  /* Allocate the window data */
260  data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
261  if (!data) {
262  return SDL_OutOfMemory();
263  }
264  data->window = window;
265  data->xwindow = w;
266 #ifdef X_HAVE_UTF8_STRING
267  if (SDL_X11_HAVE_UTF8 && videodata->im) {
268  data->ic =
269  X11_XCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
270  XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
271  NULL);
272  }
273 #endif
274  data->created = created;
275  data->videodata = videodata;
276 
277  /* Associate the data with the window */
278 
279  if (numwindows < windowlistlength) {
280  windowlist[numwindows] = data;
281  videodata->numwindows++;
282  } else {
283  windowlist =
284  (SDL_WindowData **) SDL_realloc(windowlist,
285  (numwindows +
286  1) * sizeof(*windowlist));
287  if (!windowlist) {
288  SDL_free(data);
289  return SDL_OutOfMemory();
290  }
291  windowlist[numwindows] = data;
292  videodata->numwindows++;
293  videodata->windowlistlength++;
294  videodata->windowlist = windowlist;
295  }
296 
297  /* Fill in the SDL window with the window data */
298  {
299  XWindowAttributes attrib;
300 
301  X11_XGetWindowAttributes(data->videodata->display, w, &attrib);
302  window->x = attrib.x;
303  window->y = attrib.y;
304  window->w = attrib.width;
305  window->h = attrib.height;
306  if (attrib.map_state != IsUnmapped) {
307  window->flags |= SDL_WINDOW_SHOWN;
308  } else {
309  window->flags &= ~SDL_WINDOW_SHOWN;
310  }
311  data->visual = attrib.visual;
312  data->colormap = attrib.colormap;
313  }
314 
315  window->flags |= X11_GetNetWMState(_this, w);
316 
317  {
318  Window FocalWindow;
319  int RevertTo=0;
320  X11_XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
321  if (FocalWindow==w)
322  {
323  window->flags |= SDL_WINDOW_INPUT_FOCUS;
324  }
325 
326  if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
328  }
329 
330  if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
331  /* Tell x11 to clip mouse */
332  }
333  }
334 
335  /* All done! */
336  window->driverdata = data;
337  return 0;
338 }
339 
340 static void
341 SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
342 {
343  /*
344  * this code used to check for KWM_WIN_DECORATION, but KDE hasn't
345  * supported it for years and years. It now respects _MOTIF_WM_HINTS.
346  * Gnome is similar: just use the Motif atom.
347  */
348 
349  Atom WM_HINTS = X11_XInternAtom(display, "_MOTIF_WM_HINTS", True);
350  if (WM_HINTS != None) {
351  /* Hints used by Motif compliant window managers */
352  struct
353  {
354  unsigned long flags;
355  unsigned long functions;
356  unsigned long decorations;
357  long input_mode;
358  unsigned long status;
359  } MWMHints = {
360  (1L << 1), 0, border ? 1 : 0, 0, 0
361  };
362 
363  X11_XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
364  PropModeReplace, (unsigned char *) &MWMHints,
365  sizeof(MWMHints) / sizeof(long));
366  } else { /* set the transient hints instead, if necessary */
367  X11_XSetTransientForHint(display, window, RootWindow(display, screen));
368  }
369 }
370 
371 int
373 {
375  SDL_DisplayData *displaydata =
377  SDL_WindowData *windowdata;
378  Display *display = data->display;
379  int screen = displaydata->screen;
380  Visual *visual;
381  int depth;
382  XSetWindowAttributes xattr;
383  Window w;
384  XSizeHints *sizehints;
385  XWMHints *wmhints;
386  XClassHint *classhints;
387  Atom _NET_WM_BYPASS_COMPOSITOR;
388  Atom _NET_WM_WINDOW_TYPE;
389  Atom wintype;
390  const char *wintype_name = NULL;
391  long compositor = 1;
392  Atom _NET_WM_PID;
393  Atom XdndAware, xdnd_version = 5;
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  XdndAware = X11_XInternAtom(display, "XdndAware", False);
655  X11_XChangeProperty(display, w, XdndAware, XA_ATOM, 32,
656  PropModeReplace,
657  (unsigned char*)&xdnd_version, 1);
658 
659  X11_XFlush(display);
660 
661  return 0;
662 }
663 
664 int
665 X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
666 {
667  Window w = (Window) data;
668 
669  window->title = X11_GetWindowTitle(_this, w);
670 
671  if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
672  return -1;
673  }
674  return 0;
675 }
676 
677 char *
678 X11_GetWindowTitle(_THIS, Window xwindow)
679 {
681  Display *display = data->display;
682  int status, real_format;
683  Atom real_type;
684  unsigned long items_read, items_left;
685  unsigned char *propdata;
686  char *title = NULL;
687 
688  status = X11_XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
689  0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
690  &items_read, &items_left, &propdata);
691  if (status == Success && propdata) {
692  title = SDL_strdup(SDL_static_cast(char*, propdata));
693  X11_XFree(propdata);
694  } else {
695  status = X11_XGetWindowProperty(display, xwindow, XA_WM_NAME,
696  0L, 8192L, False, XA_STRING, &real_type, &real_format,
697  &items_read, &items_left, &propdata);
698  if (status == Success && propdata) {
699  title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
700  X11_XFree(propdata);
701  } else {
702  title = SDL_strdup("");
703  }
704  }
705  return title;
706 }
707 
708 void
710 {
711  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
712  Display *display = data->videodata->display;
713  XTextProperty titleprop;
714  Status status;
715  const char *title = window->title ? window->title : "";
716  char *title_locale = NULL;
717 
718 #ifdef X_HAVE_UTF8_STRING
719  Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
720 #endif
721 
722  title_locale = SDL_iconv_utf8_locale(title);
723  if (!title_locale) {
724  SDL_OutOfMemory();
725  return;
726  }
727 
728  status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
729  SDL_free(title_locale);
730  if (status) {
731  X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
732  X11_XFree(titleprop.value);
733  }
734 #ifdef X_HAVE_UTF8_STRING
735  if (SDL_X11_HAVE_UTF8) {
736  status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1,
737  XUTF8StringStyle, &titleprop);
738  if (status == Success) {
739  X11_XSetTextProperty(display, data->xwindow, &titleprop,
740  _NET_WM_NAME);
741  X11_XFree(titleprop.value);
742  }
743  }
744 #endif
745 
746  X11_XFlush(display);
747 }
748 
749 void
751 {
752  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
753  Display *display = data->videodata->display;
754  Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
755 
756  if (icon) {
757  int propsize;
758  long *propdata;
759 
760  /* Set the _NET_WM_ICON property */
762  propsize = 2 + (icon->w * icon->h);
763  propdata = SDL_malloc(propsize * sizeof(long));
764  if (propdata) {
765  int x, y;
766  Uint32 *src;
767  long *dst;
768 
769  propdata[0] = icon->w;
770  propdata[1] = icon->h;
771  dst = &propdata[2];
772  for (y = 0; y < icon->h; ++y) {
773  src = (Uint32*)((Uint8*)icon->pixels + y * icon->pitch);
774  for (x = 0; x < icon->w; ++x) {
775  *dst++ = *src++;
776  }
777  }
778  X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
779  32, PropModeReplace, (unsigned char *) propdata,
780  propsize);
781  }
782  SDL_free(propdata);
783  } else {
784  X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
785  }
786  X11_XFlush(display);
787 }
788 
789 void
791 {
792  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
793  Display *display = data->videodata->display;
794 
795  X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
796  X11_XFlush(display);
797 }
798 
799 void
801 {
802  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
803  Display *display = data->videodata->display;
804 
805  if (window->flags & SDL_WINDOW_RESIZABLE) {
806  XSizeHints *sizehints = X11_XAllocSizeHints();
807  long userhints;
808 
809  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
810 
811  sizehints->min_width = window->min_w;
812  sizehints->min_height = window->min_h;
813  sizehints->flags |= PMinSize;
814 
815  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
816 
817  X11_XFree(sizehints);
818 
819  /* See comment in X11_SetWindowSize. */
820  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
821  X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
822  X11_XRaiseWindow(display, data->xwindow);
823  }
824 
825  X11_XFlush(display);
826 }
827 
828 void
830 {
831  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
832  Display *display = data->videodata->display;
833 
834  if (window->flags & SDL_WINDOW_RESIZABLE) {
835  XSizeHints *sizehints = X11_XAllocSizeHints();
836  long userhints;
837 
838  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
839 
840  sizehints->max_width = window->max_w;
841  sizehints->max_height = window->max_h;
842  sizehints->flags |= PMaxSize;
843 
844  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
845 
846  X11_XFree(sizehints);
847 
848  /* See comment in X11_SetWindowSize. */
849  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
850  X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
851  X11_XRaiseWindow(display, data->xwindow);
852  }
853 
854  X11_XFlush(display);
855 }
856 
857 void
859 {
860  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
861  Display *display = data->videodata->display;
862 
863  if (SDL_IsShapedWindow(window)) {
864  X11_ResizeWindowShape(window);
865  }
866  if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
867  /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus
868  we must set the size hints to adjust the window size. */
869  XSizeHints *sizehints = X11_XAllocSizeHints();
870  long userhints;
871 
872  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
873 
874  sizehints->min_width = sizehints->max_width = window->w;
875  sizehints->min_height = sizehints->max_height = window->h;
876  sizehints->flags |= PMinSize | PMaxSize;
877 
878  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
879 
880  X11_XFree(sizehints);
881 
882  /* From Pierre-Loup:
883  WMs each have their little quirks with that. When you change the
884  size hints, they get a ConfigureNotify event with the
885  WM_NORMAL_SIZE_HINTS Atom. They all save the hints then, but they
886  don't all resize the window right away to enforce the new hints.
887 
888  Some of them resize only after:
889  - A user-initiated move or resize
890  - A code-initiated move or resize
891  - Hiding & showing window (Unmap & map)
892 
893  The following move & resize seems to help a lot of WMs that didn't
894  properly update after the hints were changed. We don't do a
895  hide/show, because there are supposedly subtle problems with doing so
896  and transitioning from windowed to fullscreen in Unity.
897  */
898  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
899  X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
900  X11_XRaiseWindow(display, data->xwindow);
901  } else {
902  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
903  }
904 
905  X11_XFlush(display);
906 }
907 
908 int
909 X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
910 {
911  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
912 
913  *left = data->border_left;
914  *right = data->border_right;
915  *top = data->border_top;
916  *bottom = data->border_bottom;
917 
918  return 0;
919 }
920 
921 int
922 X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
923 {
924  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
925  Display *display = data->videodata->display;
926  Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
927 
928  if (opacity == 1.0f) {
929  X11_XDeleteProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY);
930  } else {
931  const Uint32 FullyOpaque = 0xFFFFFFFF;
932  const long alpha = (long) ((double)opacity * (double)FullyOpaque);
933  X11_XChangeProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
934  PropModeReplace, (unsigned char *)&alpha, 1);
935  }
936 
937  return 0;
938 }
939 
940 int
941 X11_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Window * parent_window) {
942  SDL_WindowData *data = (SDL_WindowData *) modal_window->driverdata;
943  SDL_WindowData *parent_data = (SDL_WindowData *) parent_window->driverdata;
944  Display *display = data->videodata->display;
945 
946  X11_XSetTransientForHint(display, data->xwindow, parent_data->xwindow);
947  return 0;
948 }
949 
950 int
952 {
953  if (X11_IsWindowMapped(_this, window)) {
954  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
955  Display *display = data->videodata->display;
956  X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
957  X11_XFlush(display);
958  return 0;
959  }
960  return -1;
961 }
962 
963 void
964 X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
965 {
966  const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
967  const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
968  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
969  SDL_DisplayData *displaydata =
971  Display *display = data->videodata->display;
972  XEvent event;
973 
974  SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
975  X11_XFlush(display);
976 
977  if (visible) {
978  XWindowAttributes attr;
979  do {
980  X11_XSync(display, False);
981  X11_XGetWindowAttributes(display, data->xwindow, &attr);
982  } while (attr.map_state != IsViewable);
983 
984  if (focused) {
985  X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
986  }
987  }
988 
989  /* make sure these don't make it to the real event queue if they fired here. */
990  X11_XSync(display, False);
991  X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
992  X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
993 }
994 
995 void
996 X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
997 {
998  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
999  Display *display = data->videodata->display;
1000 
1001  XSizeHints *sizehints = X11_XAllocSizeHints();
1002  long userhints;
1003 
1004  X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
1005 
1006  if (resizable) {
1007  /* FIXME: Is there a better way to get max window size from X? -flibit */
1008  const int maxsize = 0x7FFFFFFF;
1009  sizehints->min_width = window->min_w;
1010  sizehints->min_height = window->min_h;
1011  sizehints->max_width = (window->max_w == 0) ? maxsize : window->max_w;
1012  sizehints->max_height = (window->max_h == 0) ? maxsize : window->max_h;
1013  } else {
1014  sizehints->min_width = window->w;
1015  sizehints->min_height = window->h;
1016  sizehints->max_width = window->w;
1017  sizehints->max_height = window->h;
1018  }
1019  sizehints->flags |= PMinSize | PMaxSize;
1020 
1021  X11_XSetWMNormalHints(display, data->xwindow, sizehints);
1022 
1023  X11_XFree(sizehints);
1024 
1025  /* See comment in X11_SetWindowSize. */
1026  X11_XResizeWindow(display, data->xwindow, window->w, window->h);
1027  X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
1028  X11_XRaiseWindow(display, data->xwindow);
1029 
1030  X11_XFlush(display);
1031 }
1032 
1033 void
1034 X11_ShowWindow(_THIS, SDL_Window * window)
1035 {
1036  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1037  Display *display = data->videodata->display;
1038  XEvent event;
1039 
1040  if (!X11_IsWindowMapped(_this, window)) {
1041  X11_XMapRaised(display, data->xwindow);
1042  /* Blocking wait for "MapNotify" event.
1043  * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type,
1044  * and XCheckTypedWindowEvent doesn't block */
1045  if(!(window->flags & SDL_WINDOW_FOREIGN))
1046  X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
1047  X11_XFlush(display);
1048  }
1049 
1050  if (!data->videodata->net_wm) {
1051  /* no WM means no FocusIn event, which confuses us. Force it. */
1052  X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
1053  X11_XFlush(display);
1054  }
1055 }
1056 
1057 void
1058 X11_HideWindow(_THIS, SDL_Window * window)
1059 {
1060  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1062  Display *display = data->videodata->display;
1063  XEvent event;
1064 
1065  if (X11_IsWindowMapped(_this, window)) {
1066  X11_XWithdrawWindow(display, data->xwindow, displaydata->screen);
1067  /* Blocking wait for "UnmapNotify" event */
1068  if(!(window->flags & SDL_WINDOW_FOREIGN))
1069  X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
1070  X11_XFlush(display);
1071  }
1072 }
1073 
1074 static void
1075 SetWindowActive(_THIS, SDL_Window * window)
1076 {
1077  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1078  SDL_DisplayData *displaydata =
1080  Display *display = data->videodata->display;
1081  Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
1082 
1083  if (X11_IsWindowMapped(_this, window)) {
1084  XEvent e;
1085 
1086  /*printf("SDL Window %p: sending _NET_ACTIVE_WINDOW with timestamp %lu\n", window, data->user_time);*/
1087 
1088  SDL_zero(e);
1089  e.xany.type = ClientMessage;
1090  e.xclient.message_type = _NET_ACTIVE_WINDOW;
1091  e.xclient.format = 32;
1092  e.xclient.window = data->xwindow;
1093  e.xclient.data.l[0] = 1; /* source indication. 1 = application */
1094  e.xclient.data.l[1] = data->user_time;
1095  e.xclient.data.l[2] = 0;
1096 
1097  X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
1098  SubstructureNotifyMask | SubstructureRedirectMask, &e);
1099 
1100  X11_XFlush(display);
1101  }
1102 }
1103 
1104 void
1105 X11_RaiseWindow(_THIS, SDL_Window * window)
1106 {
1107  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1108  Display *display = data->videodata->display;
1109 
1110  X11_XRaiseWindow(display, data->xwindow);
1111  SetWindowActive(_this, window);
1112  X11_XFlush(display);
1113 }
1114 
1115 static void
1116 SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
1117 {
1118  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1119  SDL_DisplayData *displaydata =
1121  Display *display = data->videodata->display;
1122  Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
1123  Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
1124  Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
1125 
1126  if (maximized) {
1127  window->flags |= SDL_WINDOW_MAXIMIZED;
1128  } else {
1129  window->flags &= ~SDL_WINDOW_MAXIMIZED;
1130  }
1131 
1132  if (X11_IsWindowMapped(_this, window)) {
1133  XEvent e;
1134 
1135  SDL_zero(e);
1136  e.xany.type = ClientMessage;
1137  e.xclient.message_type = _NET_WM_STATE;
1138  e.xclient.format = 32;
1139  e.xclient.window = data->xwindow;
1140  e.xclient.data.l[0] =
1141  maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
1142  e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
1143  e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
1144  e.xclient.data.l[3] = 0l;
1145 
1146  X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
1147  SubstructureNotifyMask | SubstructureRedirectMask, &e);
1148  } else {
1149  X11_SetNetWMState(_this, data->xwindow, window->flags);
1150  }
1151  X11_XFlush(display);
1152 }
1153 
1154 void
1156 {
1157  SetWindowMaximized(_this, window, SDL_TRUE);
1158 }
1159 
1160 void
1162 {
1163  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1164  SDL_DisplayData *displaydata =
1166  Display *display = data->videodata->display;
1167 
1168  X11_XIconifyWindow(display, data->xwindow, displaydata->screen);
1169  X11_XFlush(display);
1170 }
1171 
1172 void
1174 {
1175  SetWindowMaximized(_this, window, SDL_FALSE);
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 #endif /* SDL_VIDEO_DRIVER_X11 */
1608 
1609 /* vi: set ts=4 sw=4 expandtab: */
void SDL_UpdateWindowGrab(SDL_Window *window)
Definition: SDL_video.c:2427
#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
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)
uint32_t Uint32
Definition: SDL_stdinc.h:181
#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:366
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:378
#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
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:560
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)
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:157
#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:116
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:370
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:139
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:1073
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
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
uint16_t Uint16
Definition: SDL_stdinc.h:169
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
union SDL_SysWMinfo::@18 info
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
#define SDL_malloc
struct SDL_VideoDevice::@34 gl_config
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)