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