src/video/wayland/SDL_waylandwindow.c
author Thomas Perl <m@thp.io>
Sat, 05 Apr 2014 17:19:34 +0200
changeset 8712 e33b5f7df761
parent 8149 681eb46b8ac4
child 8766 e5f584f77609
permissions -rw-r--r--
Wayland: Resize windows with 0x0 requested size to screen size

This makes it in line with other platforms, where SDL_CreateWindow() with
width=0, height=0 and SDL_WINDOW_FULLSCREEN opens a fullscreen window.
     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 }
    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 
   168     /**
   169      * If the user specified 0x0 as the size (turned to 1x1 by SDL_CreateWindow
   170      * in SDL_video.c), we want to make the window fill the whole screen
   171      **/
   172     if (window->w == 1) {
   173         window->w = c->screen_allocation.width;
   174     }
   175     if (window->h == 1) {
   176         window->h = c->screen_allocation.height;
   177     }
   178 
   179     data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
   180                                             window->w, window->h);
   181 
   182     /* Create the GLES window surface */
   183     data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
   184     
   185     if (data->egl_surface == EGL_NO_SURFACE) {
   186         SDL_SetError("failed to create a window surface");
   187         return -1;
   188     }
   189 
   190     if (data->shell_surface) {
   191         wl_shell_surface_set_user_data(data->shell_surface, data);
   192         wl_shell_surface_add_listener(data->shell_surface,
   193                                       &shell_surface_listener, data);
   194     }
   195 
   196 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   197     if (data->extended_surface) {
   198         qt_extended_surface_set_user_data(data->extended_surface, data);
   199         qt_extended_surface_add_listener(data->extended_surface,
   200                                          &extended_surface_listener, data);
   201     }
   202 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   203 
   204     region = wl_compositor_create_region(c->compositor);
   205     wl_region_add(region, 0, 0, window->w, window->h);
   206     wl_surface_set_opaque_region(data->surface, region);
   207     wl_region_destroy(region);
   208 
   209     WAYLAND_wl_display_flush(c->display);
   210 
   211     return 0;
   212 }
   213 
   214 void Wayland_SetWindowSize(_THIS, SDL_Window * window)
   215 {
   216     SDL_VideoData *data = _this->driverdata;
   217     SDL_WindowData *wind = window->driverdata;
   218     struct wl_region *region;
   219 
   220     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
   221 
   222     region =wl_compositor_create_region(data->compositor);
   223     wl_region_add(region, 0, 0, window->w, window->h);
   224     wl_surface_set_opaque_region(wind->surface, region);
   225     wl_region_destroy(region);
   226 }
   227 
   228 void Wayland_DestroyWindow(_THIS, SDL_Window *window)
   229 {
   230     SDL_VideoData *data = _this->driverdata;
   231     SDL_WindowData *wind = window->driverdata;
   232 
   233     window->driverdata = NULL;
   234 
   235     if (data) {
   236         SDL_EGL_DestroySurface(_this, wind->egl_surface);
   237         WAYLAND_wl_egl_window_destroy(wind->egl_window);
   238 
   239         if (wind->shell_surface)
   240             wl_shell_surface_destroy(wind->shell_surface);
   241 
   242 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   243         if (wind->extended_surface)
   244             qt_extended_surface_destroy(wind->extended_surface);
   245 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   246         wl_surface_destroy(wind->surface);
   247 
   248         SDL_free(wind);
   249         WAYLAND_wl_display_flush(data->display);
   250     }
   251 }
   252 
   253 #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
   254 
   255 /* vi: set ts=4 sw=4 expandtab: */