src/video/wayland/SDL_waylandwindow.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 20 Jan 2014 12:53:44 -0500
changeset 8116 f7c2f71251e5
parent 8104 2e4f1bd21196
child 8149 681eb46b8ac4
permissions -rw-r--r--
Patched to compile if Wayland is disabled via SDL_config.h (thanks, Martin!).

Fixes Bugzilla #2351.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_waylandwindow.h"
    30 #include "SDL_waylandvideo.h"
    31 #include "SDL_waylandtouch.h"
    32 
    33 static void
    34 handle_ping(void *data, struct wl_shell_surface *shell_surface,
    35             uint32_t serial)
    36 {
    37     wl_shell_surface_pong(shell_surface, serial);
    38 }
    39 
    40 static void
    41 handle_configure(void *data, struct wl_shell_surface *shell_surface,
    42                  uint32_t edges, int32_t width, int32_t height)
    43 {
    44 }
    45 
    46 static void
    47 handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
    48 {
    49 }
    50 
    51 static const struct wl_shell_surface_listener shell_surface_listener = {
    52     handle_ping,
    53     handle_configure,
    54     handle_popup_done
    55 };
    56 
    57 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
    58 static void
    59 handle_onscreen_visibility(void *data,
    60         struct qt_extended_surface *qt_extended_surface, int32_t visible)
    61 {
    62 }
    63 
    64 static void
    65 handle_set_generic_property(void *data,
    66         struct qt_extended_surface *qt_extended_surface, const char *name,
    67         struct wl_array *value)
    68 {
    69 }
    70 
    71 static void
    72 handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
    73 {
    74     SDL_WindowData *window = (SDL_WindowData *)data;
    75     SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
    76 }
    77 
    78 static const struct qt_extended_surface_listener extended_surface_listener = {
    79     handle_onscreen_visibility,
    80     handle_set_generic_property,
    81     handle_close,
    82 };
    83 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
    84 
    85 SDL_bool
    86 Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
    87 {
    88     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    89 
    90     info->info.wl.display = data->waylandData->display;
    91     info->info.wl.surface = data->surface;
    92     info->info.wl.shell_surface = data->shell_surface;
    93     info->subsystem = SDL_SYSWM_WAYLAND;
    94 
    95     return SDL_TRUE;
    96 }
    97 
    98 void Wayland_ShowWindow(_THIS, SDL_Window *window)
    99 {
   100     SDL_WindowData *wind = window->driverdata;
   101 
   102     if (window->flags & SDL_WINDOW_FULLSCREEN)
   103         wl_shell_surface_set_fullscreen(wind->shell_surface,
   104                                         WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
   105                                         0, NULL);
   106     else
   107         wl_shell_surface_set_toplevel(wind->shell_surface);
   108 
   109     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   110 }
   111 
   112 void
   113 Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
   114                             SDL_VideoDisplay * _display, SDL_bool fullscreen)
   115 {
   116     SDL_WindowData *wind = window->driverdata;
   117 
   118     if (fullscreen)
   119         wl_shell_surface_set_fullscreen(wind->shell_surface,
   120                                         WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
   121                                         0, NULL);
   122     else
   123         wl_shell_surface_set_toplevel(wind->shell_surface);
   124 
   125     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   126 }
   127 
   128 int Wayland_CreateWindow(_THIS, SDL_Window *window)
   129 {
   130     SDL_WindowData *data;
   131     SDL_VideoData *c;
   132     struct wl_region *region;
   133 
   134     data = calloc(1, sizeof *data);
   135     if (data == NULL)
   136         return 0;
   137 
   138     c = _this->driverdata;
   139     window->driverdata = data;
   140 
   141     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   142         SDL_GL_LoadLibrary(NULL);
   143         window->flags |= SDL_WINDOW_OPENGL;
   144     }
   145 
   146     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   147         window->x = 0;
   148     }
   149     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
   150         window->y = 0;
   151     }
   152 
   153     data->waylandData = c;
   154     data->sdlwindow = window;
   155 
   156     data->surface =
   157         wl_compositor_create_surface(c->compositor);
   158     wl_surface_set_user_data(data->surface, data);
   159     data->shell_surface = wl_shell_get_shell_surface(c->shell,
   160                                                      data->surface);
   161 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH    
   162     if (c->surface_extension) {
   163         data->extended_surface = qt_surface_extension_get_extended_surface(
   164                 c->surface_extension, data->surface);
   165     }
   166 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   167     data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
   168                                             window->w, window->h);
   169 
   170     /* Create the GLES window surface */
   171     data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
   172     
   173     if (data->egl_surface == EGL_NO_SURFACE) {
   174         SDL_SetError("failed to create a window surface");
   175         return -1;
   176     }
   177 
   178     if (data->shell_surface) {
   179         wl_shell_surface_set_user_data(data->shell_surface, data);
   180         wl_shell_surface_add_listener(data->shell_surface,
   181                                       &shell_surface_listener, data);
   182     }
   183 
   184 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   185     if (data->extended_surface) {
   186         qt_extended_surface_set_user_data(data->extended_surface, data);
   187         qt_extended_surface_add_listener(data->extended_surface,
   188                                          &extended_surface_listener, data);
   189     }
   190 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   191 
   192     region = wl_compositor_create_region(c->compositor);
   193     wl_region_add(region, 0, 0, window->w, window->h);
   194     wl_surface_set_opaque_region(data->surface, region);
   195     wl_region_destroy(region);
   196 
   197     WAYLAND_wl_display_flush(c->display);
   198 
   199     return 0;
   200 }
   201 
   202 void Wayland_SetWindowSize(_THIS, SDL_Window * window)
   203 {
   204     SDL_VideoData *data = _this->driverdata;
   205     SDL_WindowData *wind = window->driverdata;
   206     struct wl_region *region;
   207 
   208     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
   209 
   210     region =wl_compositor_create_region(data->compositor);
   211     wl_region_add(region, 0, 0, window->w, window->h);
   212     wl_surface_set_opaque_region(wind->surface, region);
   213     wl_region_destroy(region);
   214 }
   215 
   216 void Wayland_DestroyWindow(_THIS, SDL_Window *window)
   217 {
   218     SDL_VideoData *data = _this->driverdata;
   219     SDL_WindowData *wind = window->driverdata;
   220 
   221     window->driverdata = NULL;
   222 
   223     if (data) {
   224         SDL_EGL_DestroySurface(_this, wind->egl_surface);
   225         WAYLAND_wl_egl_window_destroy(wind->egl_window);
   226 
   227         if (wind->shell_surface)
   228             wl_shell_surface_destroy(wind->shell_surface);
   229 
   230 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   231         if (wind->extended_surface)
   232             qt_extended_surface_destroy(wind->extended_surface);
   233 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   234         wl_surface_destroy(wind->surface);
   235 
   236         SDL_free(wind);
   237         WAYLAND_wl_display_flush(data->display);
   238     }
   239 }
   240 
   241 #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
   242 
   243 /* vi: set ts=4 sw=4 expandtab: */