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