src/video/wayland/SDL_waylandwindow.c
author Arne Janbu <arnej@arnej.de>
Sat, 10 Jan 2015 13:47:37 +0100
changeset 9362 dfd8202eb9a7
parent 8978 7753e4fd3d1d
child 9467 975453c4e217
permissions -rw-r--r--
Fix build on Linux when wayland is enabled

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