SDL  2.0
SDL_waylandwindow.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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 
22 #include "../../SDL_internal.h"
23 
24 #if SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL
25 
26 #include "../SDL_sysvideo.h"
27 #include "../../events/SDL_windowevents_c.h"
28 #include "../SDL_egl_c.h"
29 #include "SDL_waylandevents_c.h"
30 #include "SDL_waylandwindow.h"
31 #include "SDL_waylandvideo.h"
32 #include "SDL_waylandtouch.h"
33 #include "SDL_waylanddyn.h"
34 #include "SDL_hints.h"
35 
36 #include "xdg-shell-client-protocol.h"
37 #include "xdg-shell-unstable-v6-client-protocol.h"
38 #include "xdg-decoration-unstable-v1-client-protocol.h"
39 #include "org-kde-kwin-server-decoration-manager-client-protocol.h"
40 
41 static float get_window_scale_factor(SDL_Window *window) {
42  return ((SDL_WindowData*)window->driverdata)->scale_factor;
43 }
44 
45 /* On modern desktops, we probably will use the xdg-shell protocol instead
46  of wl_shell, but wl_shell might be useful on older Wayland installs that
47  don't have the newer protocol, or embedded things that don't have a full
48  window manager. */
49 
50 static void
51 handle_ping_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
52  uint32_t serial)
53 {
54  wl_shell_surface_pong(shell_surface, serial);
55 }
56 
57 static void
58 handle_configure_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
60 {
62  SDL_Window *window = wind->sdlwindow;
63 
64  /* wl_shell_surface spec states that this is a suggestion.
65  Ignore if less than or greater than max/min size. */
66 
67  if (width == 0 || height == 0) {
68  return;
69  }
70 
71  if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
72  if ((window->flags & SDL_WINDOW_RESIZABLE)) {
73  if (window->max_w > 0) {
74  width = SDL_min(width, window->max_w);
75  }
76  width = SDL_max(width, window->min_w);
77 
78  if (window->max_h > 0) {
79  height = SDL_min(height, window->max_h);
80  }
81  height = SDL_max(height, window->min_h);
82  } else {
83  return;
84  }
85  }
86 
87  wind->resize.width = width;
88  wind->resize.height = height;
89  wind->resize.pending = SDL_TRUE;
90 }
91 
92 static void
93 handle_popup_done_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface)
94 {
95 }
96 
97 static const struct wl_shell_surface_listener shell_surface_listener_wl = {
98  handle_ping_wl_shell_surface,
99  handle_configure_wl_shell_surface,
100  handle_popup_done_wl_shell_surface
101 };
102 
103 
104 
105 
106 static void
107 handle_configure_zxdg_shell_surface(void *data, struct zxdg_surface_v6 *zxdg, uint32_t serial)
108 {
110  SDL_Window *window = wind->sdlwindow;
111  struct wl_region *region;
112 
114  window->w = 0;
115  window->h = 0;
117  window->w = wind->resize.width;
118  window->h = wind->resize.height;
119 
120  wl_surface_set_buffer_scale(wind->surface, get_window_scale_factor(window));
121  WAYLAND_wl_egl_window_resize(wind->egl_window, window->w * get_window_scale_factor(window), window->h * get_window_scale_factor(window), 0, 0);
122 
123  zxdg_surface_v6_ack_configure(zxdg, serial);
124 
125  region = wl_compositor_create_region(wind->waylandData->compositor);
126  wl_region_add(region, 0, 0, window->w, window->h);
127  wl_surface_set_opaque_region(wind->surface, region);
128  wl_region_destroy(region);
129 
131  } else {
132  wind->resize.pending = SDL_TRUE;
133  wind->resize.configure = SDL_TRUE;
134  wind->resize.serial = serial;
135  }
136 }
137 
138 static const struct zxdg_surface_v6_listener shell_surface_listener_zxdg = {
139  handle_configure_zxdg_shell_surface
140 };
141 
142 
143 static void
144 handle_configure_zxdg_toplevel(void *data,
145  struct zxdg_toplevel_v6 *zxdg_toplevel_v6,
146  int32_t width,
147  int32_t height,
148  struct wl_array *states)
149 {
151  SDL_Window *window = wind->sdlwindow;
152 
153  enum zxdg_toplevel_v6_state *state;
154  SDL_bool fullscreen = SDL_FALSE;
155  wl_array_for_each(state, states) {
156  if (*state == ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN) {
157  fullscreen = SDL_TRUE;
158  }
159  }
160 
161  if (!fullscreen) {
162  if (width == 0 || height == 0) {
163  width = window->windowed.w;
164  height = window->windowed.h;
165  }
166 
167  /* zxdg_toplevel spec states that this is a suggestion.
168  Ignore if less than or greater than max/min size. */
169 
170  if ((window->flags & SDL_WINDOW_RESIZABLE)) {
171  if (window->max_w > 0) {
172  width = SDL_min(width, window->max_w);
173  }
174  width = SDL_max(width, window->min_w);
175 
176  if (window->max_h > 0) {
177  height = SDL_min(height, window->max_h);
178  }
179  height = SDL_max(height, window->min_h);
180  } else {
181  wind->resize.width = window->w;
182  wind->resize.height = window->h;
183  return;
184  }
185  }
186 
187  if (width == 0 || height == 0) {
188  wind->resize.width = window->w;
189  wind->resize.height = window->h;
190  return;
191  }
192 
193  wind->resize.width = width;
194  wind->resize.height = height;
195 }
196 
197 static void
198 handle_close_zxdg_toplevel(void *data, struct zxdg_toplevel_v6 *zxdg_toplevel_v6)
199 {
202 }
203 
204 static const struct zxdg_toplevel_v6_listener toplevel_listener_zxdg = {
205  handle_configure_zxdg_toplevel,
206  handle_close_zxdg_toplevel
207 };
208 
209 
210 
211 static void
212 handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
213 {
215  SDL_Window *window = wind->sdlwindow;
216  struct wl_region *region;
217 
219  window->w = 0;
220  window->h = 0;
222  window->w = wind->resize.width;
223  window->h = wind->resize.height;
224 
225  wl_surface_set_buffer_scale(wind->surface, get_window_scale_factor(window));
226  WAYLAND_wl_egl_window_resize(wind->egl_window, window->w * get_window_scale_factor(window), window->h * get_window_scale_factor(window), 0, 0);
227 
228  xdg_surface_ack_configure(xdg, serial);
229 
230  region = wl_compositor_create_region(wind->waylandData->compositor);
231  wl_region_add(region, 0, 0, window->w, window->h);
232  wl_surface_set_opaque_region(wind->surface, region);
233  wl_region_destroy(region);
234 
236  } else {
237  wind->resize.pending = SDL_TRUE;
238  wind->resize.configure = SDL_TRUE;
239  wind->resize.serial = serial;
240  }
241 }
242 
243 static const struct xdg_surface_listener shell_surface_listener_xdg = {
244  handle_configure_xdg_shell_surface
245 };
246 
247 
248 static void
249 handle_configure_xdg_toplevel(void *data,
250  struct xdg_toplevel *xdg_toplevel,
251  int32_t width,
252  int32_t height,
253  struct wl_array *states)
254 {
256  SDL_Window *window = wind->sdlwindow;
257 
258  enum xdg_toplevel_state *state;
259  SDL_bool fullscreen = SDL_FALSE;
260  wl_array_for_each(state, states) {
261  if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) {
262  fullscreen = SDL_TRUE;
263  }
264  }
265 
266  if (!fullscreen) {
267  if (width == 0 || height == 0) {
268  width = window->windowed.w;
269  height = window->windowed.h;
270  }
271 
272  /* xdg_toplevel spec states that this is a suggestion.
273  Ignore if less than or greater than max/min size. */
274 
275  if ((window->flags & SDL_WINDOW_RESIZABLE)) {
276  if (window->max_w > 0) {
277  width = SDL_min(width, window->max_w);
278  }
279  width = SDL_max(width, window->min_w);
280 
281  if (window->max_h > 0) {
282  height = SDL_min(height, window->max_h);
283  }
284  height = SDL_max(height, window->min_h);
285  } else {
286  wind->resize.width = window->w;
287  wind->resize.height = window->h;
288  return;
289  }
290  }
291 
292  if (width == 0 || height == 0) {
293  wind->resize.width = window->w;
294  wind->resize.height = window->h;
295  return;
296  }
297 
298  wind->resize.width = width;
299  wind->resize.height = height;
300 }
301 
302 static void
303 handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
304 {
307 }
308 
309 static const struct xdg_toplevel_listener toplevel_listener_xdg = {
310  handle_configure_xdg_toplevel,
311  handle_close_xdg_toplevel
312 };
313 
314 
315 
316 
317 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
318 static void
319 handle_onscreen_visibility(void *data,
320  struct qt_extended_surface *qt_extended_surface, int32_t visible)
321 {
322 }
323 
324 static void
325 handle_set_generic_property(void *data,
326  struct qt_extended_surface *qt_extended_surface, const char *name,
327  struct wl_array *value)
328 {
329 }
330 
331 static void
332 handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
333 {
336 }
337 
338 static const struct qt_extended_surface_listener extended_surface_listener = {
339  handle_onscreen_visibility,
340  handle_set_generic_property,
341  handle_close,
342 };
343 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
344 
345 static void
346 update_scale_factor(SDL_WindowData *window) {
347  float old_factor = window->scale_factor, new_factor = 0.0;
348  int i;
349 
350  if (!(window->sdlwindow->flags & SDL_WINDOW_ALLOW_HIGHDPI)) {
351  return;
352  }
353 
354  if (!window->num_outputs) {
355  new_factor = old_factor;
356  }
357 
358  if (FULLSCREEN_VISIBLE(window->sdlwindow) && window->sdlwindow->fullscreen_mode.driverdata) {
359  new_factor = ((SDL_WaylandOutputData*)(wl_output_get_user_data(window->sdlwindow->fullscreen_mode.driverdata)))->scale_factor;
360  }
361 
362  for (i = 0; i < window->num_outputs; i++) {
363  float factor = ((SDL_WaylandOutputData*)(wl_output_get_user_data(window->outputs[i])))->scale_factor;
364  if (factor > new_factor) {
365  new_factor = factor;
366  }
367  }
368 
369  if (new_factor != old_factor) {
370  /* force the resize event to trigger, as the logical size didn't change */
371  window->resize.width = window->sdlwindow->w;
372  window->resize.height = window->sdlwindow->h;
373  window->resize.scale_factor = new_factor;
374  window->resize.pending = SDL_TRUE;
375  }
376 }
377 
378 static void
379 handle_surface_enter(void *data, struct wl_surface *surface,
380  struct wl_output *output) {
382 
383  window->outputs = SDL_realloc(window->outputs, (window->num_outputs + 1) * sizeof *window->outputs);
384  window->outputs[window->num_outputs++] = output;
385  update_scale_factor(window);
386 }
387 
388 static void
389 handle_surface_leave(void *data, struct wl_surface *surface,
390  struct wl_output *output) {
392  int i;
393 
394  if (window->num_outputs > 1) {
395  struct wl_output **new_outputs = SDL_malloc((window->num_outputs - 1) * sizeof *window->outputs), **iter = new_outputs;
396  for (i=0; i < window->num_outputs; i++) {
397  if (window->outputs[i] != output) {
398  *iter = window->outputs[i];
399  iter++;
400  }
401  }
402  SDL_free(window->outputs);
403  window->outputs = new_outputs;
404  window->num_outputs--;
405  } else {
406  window->num_outputs = 0;
407  SDL_free(window->outputs);
408  window->outputs = NULL;
409  }
410 
411  update_scale_factor(window);
412 }
413 
414 static const struct wl_surface_listener surface_listener = {
415  handle_surface_enter,
416  handle_surface_leave
417 };
418 
419 SDL_bool
421 {
422  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
423  const Uint32 version = ((((Uint32) info->version.major) * 1000000) +
424  (((Uint32) info->version.minor) * 10000) +
425  (((Uint32) info->version.patch)));
426 
427  /* Before 2.0.6, it was possible to build an SDL with Wayland support
428  (SDL_SysWMinfo will be large enough to hold Wayland info), but build
429  your app against SDL headers that didn't have Wayland support
430  (SDL_SysWMinfo could be smaller than Wayland needs. This would lead
431  to an app properly using SDL_GetWindowWMInfo() but we'd accidentally
432  overflow memory on the stack or heap. To protect against this, we've
433  padded out the struct unconditionally in the headers and Wayland will
434  just return an error for older apps using this function. Those apps
435  will need to be recompiled against newer headers or not use Wayland,
436  maybe by forcing SDL_VIDEODRIVER=x11. */
437  if (version < 2000006) {
439  SDL_SetError("Version must be 2.0.6 or newer");
440  return SDL_FALSE;
441  }
442 
443  info->info.wl.display = data->waylandData->display;
444  info->info.wl.surface = data->surface;
445  info->info.wl.shell_surface = data->shell_surface.wl;
447 
448  return SDL_TRUE;
449 }
450 
451 int
453 {
454  return 0; /* just succeed, the real work is done elsewhere. */
455 }
456 
457 static void
458 SetFullscreen(_THIS, SDL_Window * window, struct wl_output *output)
459 {
460  const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
461  SDL_WindowData *wind = window->driverdata;
462 
463  if (viddata->shell.xdg) {
464  if (output) {
465  xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
466  } else {
467  xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
468  }
469  } else if (viddata->shell.zxdg) {
470  if (output) {
471  zxdg_toplevel_v6_set_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel, output);
472  } else {
473  zxdg_toplevel_v6_unset_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel);
474  }
475  } else {
476  if (output) {
477  wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
478  WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
479  0, output);
480  } else {
481  wl_shell_surface_set_toplevel(wind->shell_surface.wl);
482  }
483  }
484 
485  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
486 }
487 
489 {
490  struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
491  SetFullscreen(_this, window, (window->flags & SDL_WINDOW_FULLSCREEN) ? output : NULL);
492 }
493 
494 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
495 static void SDLCALL
496 QtExtendedSurface_OnHintChanged(void *userdata, const char *name,
497  const char *oldValue, const char *newValue)
498 {
499  struct qt_extended_surface *qt_extended_surface = userdata;
500 
501  if (name == NULL) {
502  return;
503  }
504 
505  if (strcmp(name, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION) == 0) {
506  int32_t orientation = QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION;
507 
508  if (newValue != NULL) {
509  if (strcmp(newValue, "portrait") == 0) {
510  orientation = QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION;
511  } else if (strcmp(newValue, "landscape") == 0) {
512  orientation = QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION;
513  } else if (strcmp(newValue, "inverted-portrait") == 0) {
514  orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION;
515  } else if (strcmp(newValue, "inverted-landscape") == 0) {
516  orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION;
517  }
518  }
519 
520  qt_extended_surface_set_content_orientation(qt_extended_surface, orientation);
521  } else if (strcmp(name, SDL_HINT_QTWAYLAND_WINDOW_FLAGS) == 0) {
522  uint32_t flags = 0;
523 
524  if (newValue != NULL) {
525  char *tmp = strdup(newValue);
526  char *saveptr = NULL;
527 
528  char *flag = strtok_r(tmp, " ", &saveptr);
529  while (flag) {
530  if (strcmp(flag, "OverridesSystemGestures") == 0) {
531  flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES;
532  } else if (strcmp(flag, "StaysOnTop") == 0) {
533  flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP;
534  } else if (strcmp(flag, "BypassWindowManager") == 0) {
535  // See https://github.com/qtproject/qtwayland/commit/fb4267103d
536  flags |= 4 /* QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER */;
537  }
538 
539  flag = strtok_r(NULL, " ", &saveptr);
540  }
541 
542  free(tmp);
543  }
544 
545  qt_extended_surface_set_window_flags(qt_extended_surface, flags);
546  }
547 }
548 
549 static void QtExtendedSurface_Subscribe(struct qt_extended_surface *surface, const char *name)
550 {
551  SDL_AddHintCallback(name, QtExtendedSurface_OnHintChanged, surface);
552 }
553 
554 static void QtExtendedSurface_Unsubscribe(struct qt_extended_surface *surface, const char *name)
555 {
556  SDL_DelHintCallback(name, QtExtendedSurface_OnHintChanged, surface);
557 }
558 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
559 
560 void
562  SDL_VideoDisplay * _display, SDL_bool fullscreen)
563 {
564  struct wl_output *output = ((SDL_WaylandOutputData*) _display->driverdata)->output;
565  SetFullscreen(_this, window, fullscreen ? output : NULL);
566 }
567 
568 void
570 {
571  SDL_WindowData *wind = window->driverdata;
572  const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
573 
574  if (viddata->shell.xdg) {
575  } else if (viddata->shell.zxdg) {
576  } else {
577  wl_shell_surface_set_toplevel(wind->shell_surface.wl);
578  }
579 
580  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
581 }
582 
583 void
585 {
586  SDL_WindowData *wind = window->driverdata;
587  const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
588  if ((viddata->decoration_manager) && (wind->server_decoration)) {
589  const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
590  zxdg_toplevel_decoration_v1_set_mode(wind->server_decoration, mode);
591  } else if ((viddata->kwin_server_decoration_manager) && (wind->kwin_server_decoration)) {
592  const enum org_kde_kwin_server_decoration_mode mode = bordered ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER : ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE;
593  org_kde_kwin_server_decoration_request_mode(wind->kwin_server_decoration, mode);
594  }
595 }
596 
597 void
599 {
600  SDL_WindowData *wind = window->driverdata;
602 
603  if (viddata->shell.xdg) {
604  xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
605  } else if (viddata->shell.zxdg) {
606  zxdg_toplevel_v6_set_maximized(wind->shell_surface.zxdg.roleobj.toplevel);
607  } else {
608  wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
609  }
610 
611  WAYLAND_wl_display_flush( viddata->display );
612 }
613 
615 {
617  SDL_VideoData *c;
618  struct wl_region *region;
619 
620  data = calloc(1, sizeof *data);
621  if (data == NULL)
622  return SDL_OutOfMemory();
623 
624  c = _this->driverdata;
625  window->driverdata = data;
626 
627  if (!(window->flags & SDL_WINDOW_OPENGL)) {
629  window->flags |= SDL_WINDOW_OPENGL;
630  }
631 
632  if (window->x == SDL_WINDOWPOS_UNDEFINED) {
633  window->x = 0;
634  }
635  if (window->y == SDL_WINDOWPOS_UNDEFINED) {
636  window->y = 0;
637  }
638 
639  data->waylandData = c;
640  data->sdlwindow = window;
641 
642  data->scale_factor = 1.0;
643 
644  if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
645  int i;
646  for (i=0; i < SDL_GetVideoDevice()->num_displays; i++) {
647  float scale = ((SDL_WaylandOutputData*)SDL_GetVideoDevice()->displays[i].driverdata)->scale_factor;
648  if (scale > data->scale_factor) {
649  data->scale_factor = scale;
650  }
651  }
652  }
653 
654  data->resize.pending = SDL_FALSE;
655  data->resize.width = window->w;
656  data->resize.height = window->h;
657  data->resize.scale_factor = data->scale_factor;
658 
659  data->outputs = NULL;
660  data->num_outputs = 0;
661 
662  data->surface =
663  wl_compositor_create_surface(c->compositor);
664  wl_surface_add_listener(data->surface, &surface_listener, data);
665 
666  if (c->shell.xdg) {
667  data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
668  /* !!! FIXME: add popup role */
669  data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
670  xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
671  xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
672  } else if (c->shell.zxdg) {
673  data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
674  /* !!! FIXME: add popup role */
675  data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface);
676  zxdg_toplevel_v6_add_listener(data->shell_surface.zxdg.roleobj.toplevel, &toplevel_listener_zxdg, data);
677  zxdg_toplevel_v6_set_app_id(data->shell_surface.zxdg.roleobj.toplevel, c->classname);
678  } else {
679  data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface);
680  wl_shell_surface_set_class(data->shell_surface.wl, c->classname);
681  }
682 
683 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
684  if (c->surface_extension) {
685  data->extended_surface = qt_surface_extension_get_extended_surface(
686  c->surface_extension, data->surface);
687 
688  QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION);
689  QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS);
690  }
691 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
692 
693  data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
694  window->w * data->scale_factor, window->h * data->scale_factor);
695 
696  /* Create the GLES window surface */
697  data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
698 
699  if (data->egl_surface == EGL_NO_SURFACE) {
700  return SDL_SetError("failed to create a window surface");
701  }
702 
703  if (c->shell.xdg) {
704  if (data->shell_surface.xdg.surface) {
705  xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
706  xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
707  }
708  } else if (c->shell.zxdg) {
709  if (data->shell_surface.zxdg.surface) {
710  zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
711  zxdg_surface_v6_add_listener(data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg, data);
712  }
713  } else {
714  if (data->shell_surface.wl) {
715  wl_shell_surface_set_user_data(data->shell_surface.wl, data);
716  wl_shell_surface_add_listener(data->shell_surface.wl, &shell_surface_listener_wl, data);
717  }
718  }
719 
720 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
721  if (data->extended_surface) {
722  qt_extended_surface_set_user_data(data->extended_surface, data);
723  qt_extended_surface_add_listener(data->extended_surface,
724  &extended_surface_listener, data);
725  }
726 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
727 
728  if (c->decoration_manager && c->shell.xdg && data->shell_surface.xdg.surface) {
729  data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
730  if (data->server_decoration) {
731  const SDL_bool bordered = (window->flags & SDL_WINDOW_BORDERLESS) == 0;
732  const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
733  zxdg_toplevel_decoration_v1_set_mode(data->server_decoration, mode);
734  }
735  } else if (c->kwin_server_decoration_manager) {
736  data->kwin_server_decoration = org_kde_kwin_server_decoration_manager_create(c->kwin_server_decoration_manager, data->surface);
737  if (data->kwin_server_decoration) {
738  const SDL_bool bordered = (window->flags & SDL_WINDOW_BORDERLESS) == 0;
739  const enum org_kde_kwin_server_decoration_mode mode = bordered ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER : ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE;
740  org_kde_kwin_server_decoration_request_mode(data->kwin_server_decoration, mode);
741  }
742  }
743 
744  region = wl_compositor_create_region(c->compositor);
745  wl_region_add(region, 0, 0, window->w, window->h);
746  wl_surface_set_opaque_region(data->surface, region);
747  wl_region_destroy(region);
748 
749  if (c->relative_mouse_mode) {
751  }
752 
753  wl_surface_commit(data->surface);
754  WAYLAND_wl_display_flush(c->display);
755 
756  /* we have to wait until the surface gets a "configure" event, or
757  use of this surface will fail. This is a new rule for xdg_shell. */
758  if (c->shell.xdg) {
759  if (data->shell_surface.xdg.surface) {
760  while (!data->shell_surface.xdg.initial_configure_seen) {
761  WAYLAND_wl_display_flush(c->display);
762  WAYLAND_wl_display_dispatch(c->display);
763  }
764  }
765  } else if (c->shell.zxdg) {
766  if (data->shell_surface.zxdg.surface) {
767  while (!data->shell_surface.zxdg.initial_configure_seen) {
768  WAYLAND_wl_display_flush(c->display);
769  WAYLAND_wl_display_dispatch(c->display);
770  }
771  }
772  }
773 
774  return 0;
775 }
776 
778 {
780  SDL_WindowData *wind = window->driverdata;
781  struct wl_region *region;
782 
783  wl_surface_set_buffer_scale(wind->surface, get_window_scale_factor(window));
784  WAYLAND_wl_egl_window_resize(wind->egl_window, window->w * get_window_scale_factor(window), window->h * get_window_scale_factor(window), 0, 0);
785 
786  region = wl_compositor_create_region(data->compositor);
787  wl_region_add(region, 0, 0, window->w, window->h);
788  wl_surface_set_opaque_region(wind->surface, region);
789  wl_region_destroy(region);
790 }
791 
793 {
794  SDL_WindowData *wind = window->driverdata;
796 
797  if (window->title != NULL) {
798  if (viddata->shell.xdg) {
799  xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, window->title);
800  } else if (viddata->shell.zxdg) {
801  zxdg_toplevel_v6_set_title(wind->shell_surface.zxdg.roleobj.toplevel, window->title);
802  } else {
803  wl_shell_surface_set_title(wind->shell_surface.wl, window->title);
804  }
805  }
806 
807  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
808 }
809 
811 {
813  SDL_WindowData *wind = window->driverdata;
814 
815  if (data) {
816  SDL_EGL_DestroySurface(_this, wind->egl_surface);
817  WAYLAND_wl_egl_window_destroy(wind->egl_window);
818 
819  if (wind->server_decoration) {
820  zxdg_toplevel_decoration_v1_destroy(wind->server_decoration);
821  }
822 
823  if (wind->kwin_server_decoration) {
824  org_kde_kwin_server_decoration_release(wind->kwin_server_decoration);
825  }
826 
827  if (data->shell.xdg) {
828  if (wind->shell_surface.xdg.roleobj.toplevel) {
829  xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
830  }
831  if (wind->shell_surface.zxdg.surface) {
832  xdg_surface_destroy(wind->shell_surface.xdg.surface);
833  }
834  } else if (data->shell.zxdg) {
835  if (wind->shell_surface.zxdg.roleobj.toplevel) {
836  zxdg_toplevel_v6_destroy(wind->shell_surface.zxdg.roleobj.toplevel);
837  }
838  if (wind->shell_surface.zxdg.surface) {
839  zxdg_surface_v6_destroy(wind->shell_surface.zxdg.surface);
840  }
841  } else {
842  if (wind->shell_surface.wl) {
843  wl_shell_surface_destroy(wind->shell_surface.wl);
844  }
845  }
846 
847 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
848  if (wind->extended_surface) {
849  QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION);
850  QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS);
851  qt_extended_surface_destroy(wind->extended_surface);
852  }
853 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
854  wl_surface_destroy(wind->surface);
855 
856  SDL_free(wind);
857  WAYLAND_wl_display_flush(data->display);
858  }
859  window->driverdata = NULL;
860 }
861 
862 #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
863 
864 /* vi: set ts=4 sw=4 expandtab: */
SDL_SYSWM_UNKNOWN
@ SDL_SYSWM_UNKNOWN
Definition: SDL_syswm.h:121
SDL_zxdg_shell_surface::toplevel
struct zxdg_toplevel_v6 * toplevel
Definition: SDL_waylandwindow.h:38
SDL_waylandvideo.h
SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION
#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION
A variable describing the content orientation on QtWayland-based platforms.
Definition: SDL_hints.h:622
SDL_waylandevents_c.h
c
const GLubyte * c
Definition: SDL_opengl_glext.h:11093
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_WINDOW_ALLOW_HIGHDPI
@ SDL_WINDOW_ALLOW_HIGHDPI
Definition: SDL_video.h:113
SDL_WindowData::serial
uint32_t serial
Definition: SDL_waylandwindow.h:75
SDL_HINT_QTWAYLAND_WINDOW_FLAGS
#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS
Flags to set on QtWayland windows to integrate with the native window manager.
Definition: SDL_hints.h:633
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:381
SDL_WaylandOutputData
Definition: SDL_waylandvideo.h:85
SDL_SysWMinfo::display
Display * display
Definition: SDL_syswm.h:220
scale
GLenum GLenum GLenum GLenum GLenum scale
Definition: SDL_opengl_glext.h:9375
SDL_VideoData::zxdg
struct zxdg_shell_v6 * zxdg
Definition: SDL_waylandvideo.h:58
NULL
#define NULL
Definition: begin_code.h:167
surface
EGLSurface surface
Definition: eglext.h:248
width
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
SDL_WindowData::configure
SDL_bool configure
Definition: SDL_waylandwindow.h:74
SDL_WINDOWEVENT_CLOSE
@ SDL_WINDOWEVENT_CLOSE
Definition: SDL_video.h:167
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
NativeWindowType
EGLNativeWindowType NativeWindowType
Definition: eglplatform.h:112
SDL_SysWMinfo
Definition: SDL_syswm.h:197
SDL_WindowData
Definition: SDL_androidwindow.h:38
SDL_version::minor
Uint8 minor
Definition: SDL_version.h:54
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:49
SDL_WINDOW_FULLSCREEN
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
Wayland_MaximizeWindow
void Wayland_MaximizeWindow(_THIS, SDL_Window *window)
SDL_WINDOW_OPENGL
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_WINDOWEVENT_RESIZED
@ SDL_WINDOWEVENT_RESIZED
Definition: SDL_video.h:155
SDL_xdg_shell_surface::surface
struct xdg_surface * surface
Definition: SDL_waylandwindow.h:45
SDL_WINDOWPOS_UNDEFINED
#define SDL_WINDOWPOS_UNDEFINED
Definition: SDL_video.h:130
SDL_GL_LoadLibrary
#define SDL_GL_LoadLibrary
Definition: SDL_dynapi_overrides.h:553
SDL_VideoData::decoration_manager
struct zxdg_decoration_manager_v1 * decoration_manager
Definition: SDL_waylandvideo.h:64
SDL_zxdg_shell_surface::surface
struct zxdg_surface_v6 * surface
Definition: SDL_waylandwindow.h:36
SDL_WindowData::wl
struct wl_shell_surface * wl
Definition: SDL_waylandwindow.h:60
SDL_SYSWM_WAYLAND
@ SDL_SYSWM_WAYLAND
Definition: SDL_syswm.h:127
SDL_VideoData::compositor
struct wl_compositor * compositor
Definition: SDL_waylandvideo.h:52
SDL_WINDOW_RESIZABLE
@ SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:105
SDL_WindowData::pending
SDL_bool pending
Definition: SDL_waylandwindow.h:74
SDL_WindowData::waylandData
SDL_VideoData * waylandData
Definition: SDL_waylandwindow.h:55
SDL_SysWMinfo::info
union SDL_SysWMinfo::@17 info
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
Wayland_ShowWindow
void Wayland_ShowWindow(_THIS, SDL_Window *window)
SDL_xdg_shell_surface::roleobj
union SDL_xdg_shell_surface::@265 roleobj
SDL_Window::w
int w
Definition: SDL_sysvideo.h:80
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
Wayland_SetWindowTitle
void Wayland_SetWindowTitle(_THIS, SDL_Window *window)
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
SDL_VideoDevice::num_displays
int num_displays
Definition: SDL_sysvideo.h:315
strdup
#define strdup
Definition: vk_sdk_platform.h:42
SDL_WindowData::surface
SDL_Surface * surface
Definition: SDL_emscriptenvideo.h:41
SDL_SysWMinfo::subsystem
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:200
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_WindowData::width
int width
Definition: SDL_waylandwindow.h:76
EGL_NO_SURFACE
#define EGL_NO_SURFACE
Definition: egl.h:100
int32_t
signed int int32_t
Definition: SDL_config_windows.h:62
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
height
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
SDL_max
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
SDL_waylandwindow.h
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_VideoDevice::displays
SDL_VideoDisplay * displays
Definition: SDL_sysvideo.h:316
Wayland_RestoreWindow
void Wayland_RestoreWindow(_THIS, SDL_Window *window)
SDL_xdg_shell_surface::initial_configure_seen
SDL_bool initial_configure_seen
Definition: SDL_waylandwindow.h:50
SDL_WindowData::xdg
SDL_xdg_shell_surface xdg
Definition: SDL_waylandwindow.h:58
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
Wayland_GetWindowWMInfo
SDL_bool Wayland_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
SDL_zxdg_shell_surface::roleobj
union SDL_zxdg_shell_surface::@264 roleobj
Wayland_DestroyWindow
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:139
Wayland_SetWindowBordered
void Wayland_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
SDL_WindowData::egl_window
struct wl_egl_window * egl_window
Definition: SDL_waylandwindow.h:62
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_VideoData::kwin_server_decoration_manager
struct org_kde_kwin_server_decoration_manager * kwin_server_decoration_manager
Definition: SDL_waylandvideo.h:65
SDL_zxdg_shell_surface::initial_configure_seen
SDL_bool initial_configure_seen
Definition: SDL_waylandwindow.h:41
SDL_WindowData::height
int height
Definition: SDL_waylandwindow.h:76
FULLSCREEN_VISIBLE
#define FULLSCREEN_VISIBLE(W)
Definition: SDL_sysvideo.h:116
SDL_VideoData::display
struct wl_display * display
Definition: SDL_waylandvideo.h:50
uint32_t
unsigned int uint32_t
Definition: SDL_config_windows.h:63
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_AddHintCallback
#define SDL_AddHintCallback
Definition: SDL_dynapi_overrides.h:192
SDL_SysWMinfo::version
SDL_version version
Definition: SDL_syswm.h:199
sort_controllers.output
output
Definition: sort_controllers.py:10
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
SDL_WindowData::shell_surface
union SDL_WindowData::@266 shell_surface
SDL_waylandtouch.h
SDL_VideoDisplay
Definition: SDL_sysvideo.h:125
SDL_waylanddyn.h
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
Wayland_SetWindowFullscreen
void Wayland_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen)
SDL_WindowData::zxdg
SDL_zxdg_shell_surface zxdg
Definition: SDL_waylandwindow.h:59
SDL_hints.h
SDL_SendWindowEvent
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
Definition: SDL_windowevents.c:74
Wayland_input_lock_pointer
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
SDL_xdg_shell_surface::toplevel
struct xdg_toplevel * toplevel
Definition: SDL_waylandwindow.h:47
Wayland_SetWindowHitTest
int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: SDL_opengl_glext.h:2479
SDL_GetVideoDevice
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
SDL_WindowData::sdlwindow
SDL_Window * sdlwindow
Definition: SDL_waylandwindow.h:54
SDL_DelHintCallback
#define SDL_DelHintCallback
Definition: SDL_dynapi_overrides.h:193
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_version::patch
Uint8 patch
Definition: SDL_version.h:55
SDL_version::major
Uint8 major
Definition: SDL_version.h:53
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
free
SDL_EventEntry * free
Definition: SDL_events.c:82
SDL_WindowData::egl_surface
EGLSurface egl_surface
Definition: SDL_androidwindow.h:40
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
i
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
SDL_VideoData::shell
struct SDL_VideoData::@263 shell
SDL_VideoData
Definition: SDL_androidvideo.h:36
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_WindowData::kwin_server_decoration
struct org_kde_kwin_server_decoration * kwin_server_decoration
Definition: SDL_waylandwindow.h:67
SDL_WINDOW_BORDERLESS
@ SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:104
SDL_WindowData::resize
struct SDL_WindowData::@267 resize
SDL_VideoData::xdg
struct xdg_wm_base * xdg
Definition: SDL_waylandvideo.h:57
Wayland_CreateWindow
int Wayland_CreateWindow(_THIS, SDL_Window *window)
Wayland_SetWindowSize
void Wayland_SetWindowSize(_THIS, SDL_Window *window)
SDL_WindowData::server_decoration
struct zxdg_toplevel_decoration_v1 * server_decoration
Definition: SDL_waylandwindow.h:66