SDL  2.0
SDL_waylandwindow.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
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 
35 static void
36 handle_ping(void *data, struct wl_shell_surface *shell_surface,
37  uint32_t serial)
38 {
39  wl_shell_surface_pong(shell_surface, serial);
40 }
41 
42 static void
43 handle_configure(void *data, struct wl_shell_surface *shell_surface,
45 {
46  SDL_WindowData *wind = (SDL_WindowData *)data;
47  SDL_Window *window = wind->sdlwindow;
48  struct wl_region *region;
49 
50  /* wl_shell_surface spec states that this is a suggestion.
51  Ignore if less than or greater than max/min size. */
52 
53  if (width == 0 || height == 0) {
54  return;
55  }
56 
57  if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
58  if ((window->flags & SDL_WINDOW_RESIZABLE)) {
59  if (window->max_w > 0) {
60  width = SDL_min(width, window->max_w);
61  }
62  width = SDL_max(width, window->min_w);
63 
64  if (window->max_h > 0) {
65  height = SDL_min(height, window->max_h);
66  }
67  height = SDL_max(height, window->min_h);
68  } else {
69  return;
70  }
71  }
72 
73  if (width == window->w && height == window->h) {
74  return;
75  }
76 
77  window->w = width;
78  window->h = height;
79  WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
80 
81  region = wl_compositor_create_region(wind->waylandData->compositor);
82  wl_region_add(region, 0, 0, window->w, window->h);
83  wl_surface_set_opaque_region(wind->surface, region);
84  wl_region_destroy(region);
85  SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
86 }
87 
88 static void
89 handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
90 {
91 }
92 
93 static const struct wl_shell_surface_listener shell_surface_listener = {
94  handle_ping,
95  handle_configure,
96  handle_popup_done
97 };
98 
99 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
100 static void
101 handle_onscreen_visibility(void *data,
102  struct qt_extended_surface *qt_extended_surface, int32_t visible)
103 {
104 }
105 
106 static void
107 handle_set_generic_property(void *data,
108  struct qt_extended_surface *qt_extended_surface, const char *name,
109  struct wl_array *value)
110 {
111 }
112 
113 static void
114 handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
115 {
116  SDL_WindowData *window = (SDL_WindowData *)data;
118 }
119 
120 static const struct qt_extended_surface_listener extended_surface_listener = {
121  handle_onscreen_visibility,
122  handle_set_generic_property,
123  handle_close,
124 };
125 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
126 
127 SDL_bool
129 {
130  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
131 
132  info->info.wl.display = data->waylandData->display;
133  info->info.wl.surface = data->surface;
134  info->info.wl.shell_surface = data->shell_surface;
136 
137  return SDL_TRUE;
138 }
139 
140 int
142 {
143  return 0; /* just succeed, the real work is done elsewhere. */
144 }
145 
146 void Wayland_ShowWindow(_THIS, SDL_Window *window)
147 {
148  SDL_WindowData *wind = window->driverdata;
149 
150  if (window->flags & SDL_WINDOW_FULLSCREEN)
151  wl_shell_surface_set_fullscreen(wind->shell_surface,
152  WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
153  0, (struct wl_output *)window->fullscreen_mode.driverdata);
154  else
155  wl_shell_surface_set_toplevel(wind->shell_surface);
156 
157  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
158 }
159 
160 void
162  SDL_VideoDisplay * _display, SDL_bool fullscreen)
163 {
164  SDL_WindowData *wind = window->driverdata;
165 
166  if (fullscreen)
167  wl_shell_surface_set_fullscreen(wind->shell_surface,
168  WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
169  0, (struct wl_output *)_display->driverdata);
170  else
171  wl_shell_surface_set_toplevel(wind->shell_surface);
172 
173  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
174 }
175 
176 void
178 {
179  SDL_WindowData *wind = window->driverdata;
180 
181  wl_shell_surface_set_toplevel(wind->shell_surface);
182 
183  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
184 }
185 
186 void
188 {
189  SDL_WindowData *wind = window->driverdata;
190 
191  wl_shell_surface_set_maximized(wind->shell_surface, NULL);
192 
193  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
194 }
195 
197 {
199  SDL_VideoData *c;
200  struct wl_region *region;
201 
202  data = calloc(1, sizeof *data);
203  if (data == NULL)
204  return SDL_OutOfMemory();
205 
206  c = _this->driverdata;
207  window->driverdata = data;
208 
209  if (!(window->flags & SDL_WINDOW_OPENGL)) {
211  window->flags |= SDL_WINDOW_OPENGL;
212  }
213 
214  if (window->x == SDL_WINDOWPOS_UNDEFINED) {
215  window->x = 0;
216  }
217  if (window->y == SDL_WINDOWPOS_UNDEFINED) {
218  window->y = 0;
219  }
220 
221  data->waylandData = c;
222  data->sdlwindow = window;
223 
224  data->surface =
225  wl_compositor_create_surface(c->compositor);
226  wl_surface_set_user_data(data->surface, data);
227  data->shell_surface = wl_shell_get_shell_surface(c->shell,
228  data->surface);
229  wl_shell_surface_set_class (data->shell_surface, c->classname);
230 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
231  if (c->surface_extension) {
232  data->extended_surface = qt_surface_extension_get_extended_surface(
233  c->surface_extension, data->surface);
234  }
235 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
236 
237  data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
238  window->w, window->h);
239 
240  /* Create the GLES window surface */
241  data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
242 
243  if (data->egl_surface == EGL_NO_SURFACE) {
244  return SDL_SetError("failed to create a window surface");
245  }
246 
247  if (data->shell_surface) {
248  wl_shell_surface_set_user_data(data->shell_surface, data);
249  wl_shell_surface_add_listener(data->shell_surface,
250  &shell_surface_listener, data);
251  }
252 
253 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
254  if (data->extended_surface) {
255  qt_extended_surface_set_user_data(data->extended_surface, data);
256  qt_extended_surface_add_listener(data->extended_surface,
257  &extended_surface_listener, data);
258  }
259 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
260 
261  region = wl_compositor_create_region(c->compositor);
262  wl_region_add(region, 0, 0, window->w, window->h);
263  wl_surface_set_opaque_region(data->surface, region);
264  wl_region_destroy(region);
265 
266  if (c->relative_mouse_mode) {
268  }
269 
270  WAYLAND_wl_display_flush(c->display);
271 
272  return 0;
273 }
274 
275 void Wayland_SetWindowSize(_THIS, SDL_Window * window)
276 {
277  SDL_VideoData *data = _this->driverdata;
278  SDL_WindowData *wind = window->driverdata;
279  struct wl_region *region;
280 
281  WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
282 
283  region =wl_compositor_create_region(data->compositor);
284  wl_region_add(region, 0, 0, window->w, window->h);
285  wl_surface_set_opaque_region(wind->surface, region);
286  wl_region_destroy(region);
287 }
288 
290 {
291  SDL_WindowData *wind = window->driverdata;
292 
293  if (window->title != NULL) {
294  wl_shell_surface_set_title(wind->shell_surface, window->title);
295  }
296 
297  WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
298 }
299 
301 {
302  SDL_VideoData *data = _this->driverdata;
303  SDL_WindowData *wind = window->driverdata;
304 
305  if (data) {
306  SDL_EGL_DestroySurface(_this, wind->egl_surface);
307  WAYLAND_wl_egl_window_destroy(wind->egl_window);
308 
309  if (wind->shell_surface)
310  wl_shell_surface_destroy(wind->shell_surface);
311 
312 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
313  if (wind->extended_surface)
314  qt_extended_surface_destroy(wind->extended_surface);
315 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
316  wl_surface_destroy(wind->surface);
317 
318  SDL_free(wind);
319  WAYLAND_wl_display_flush(data->display);
320  }
321  window->driverdata = NULL;
322 }
323 
324 #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
325 
326 /* vi: set ts=4 sw=4 expandtab: */
void Wayland_SetWindowSize(_THIS, SDL_Window *window)
#define SDL_min(x, y)
Definition: SDL_stdinc.h:351
void Wayland_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *_display, SDL_bool fullscreen)
SDL_DisplayMode fullscreen_mode
Definition: SDL_sysvideo.h:87
GLint GLint GLsizei width
Definition: SDL_opengl.h:1565
signed int int32_t
int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
struct wl_display * display
void Wayland_MaximizeWindow(_THIS, SDL_Window *window)
static SDL_Window * window
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
void Wayland_ShowWindow(_THIS, SDL_Window *window)
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:196
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
#define SDL_WINDOWPOS_UNDEFINED
Definition: SDL_video.h:127
GLuint const GLchar * name
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1565
#define SDL_GL_LoadLibrary
struct SDL_WaylandInput * input
int Wayland_CreateWindow(_THIS, SDL_Window *window)
#define calloc
Definition: SDL_malloc.c:642
#define SDL_max(x, y)
Definition: SDL_stdinc.h:352
SDL_Surface * surface
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
void Wayland_SetWindowTitle(_THIS, SDL_Window *window)
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
GLsizei const GLfloat * value
#define _THIS
void SDL_free(void *mem)
void * driverdata
Definition: SDL_video.h:59
SDL_Window * sdlwindow
struct wl_shell_surface * shell_surface
SDL_bool Wayland_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
struct wl_shell * shell
SDL_VideoData * waylandData
const GLubyte * c
char * title
Definition: SDL_sysvideo.h:75
GLenum GLenum GLsizei const GLuint GLboolean enabled
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
unsigned int uint32_t
#define SDL_SetError
struct wl_compositor * compositor
void Wayland_RestoreWindow(_THIS, SDL_Window *window)
The type used to identify a window.
Definition: SDL_sysvideo.h:71
union SDL_SysWMinfo::@18 info
struct SDL_SysWMinfo::@18::@20 wl
void * driverdata
Definition: SDL_sysvideo.h:109
Uint32 flags
Definition: SDL_sysvideo.h:81
EGLSurface egl_surface
struct wl_egl_window * egl_window