src/video/wayland/SDL_waylandwindow.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 12 Apr 2015 20:40:06 -0400
changeset 9554 879f71e1478b
parent 9543 07cdf7b8f9bc
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Implemented SetWindowHitTest() for Wayland (thanks, x414e54!).

Fixes Bugzilla #2941.
     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 int
   113 Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
   114 {
   115     return 0;  /* just succeed, the real work is done elsewhere. */
   116 }
   117 
   118 void Wayland_ShowWindow(_THIS, SDL_Window *window)
   119 {
   120     SDL_WindowData *wind = window->driverdata;
   121 
   122     if (window->flags & SDL_WINDOW_FULLSCREEN)
   123         wl_shell_surface_set_fullscreen(wind->shell_surface,
   124                                         WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
   125                                         0, (struct wl_output *)window->fullscreen_mode.driverdata);
   126     else
   127         wl_shell_surface_set_toplevel(wind->shell_surface);
   128 
   129     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   130 }
   131 
   132 void
   133 Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
   134                             SDL_VideoDisplay * _display, SDL_bool fullscreen)
   135 {
   136     SDL_WindowData *wind = window->driverdata;
   137 
   138     if (fullscreen)
   139         wl_shell_surface_set_fullscreen(wind->shell_surface,
   140                                         WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
   141                                         0, (struct wl_output *)_display->driverdata);
   142     else
   143         wl_shell_surface_set_toplevel(wind->shell_surface);
   144 
   145     WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
   146 }
   147 
   148 int Wayland_CreateWindow(_THIS, SDL_Window *window)
   149 {
   150     SDL_WindowData *data;
   151     SDL_VideoData *c;
   152     struct wl_region *region;
   153 
   154     data = calloc(1, sizeof *data);
   155     if (data == NULL)
   156         return SDL_OutOfMemory();
   157 
   158     c = _this->driverdata;
   159     window->driverdata = data;
   160 
   161     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   162         SDL_GL_LoadLibrary(NULL);
   163         window->flags |= SDL_WINDOW_OPENGL;
   164     }
   165 
   166     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   167         window->x = 0;
   168     }
   169     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
   170         window->y = 0;
   171     }
   172 
   173     data->waylandData = c;
   174     data->sdlwindow = window;
   175 
   176     data->surface =
   177         wl_compositor_create_surface(c->compositor);
   178     wl_surface_set_user_data(data->surface, data);
   179     data->shell_surface = wl_shell_get_shell_surface(c->shell,
   180                                                      data->surface);
   181 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH    
   182     if (c->surface_extension) {
   183         data->extended_surface = qt_surface_extension_get_extended_surface(
   184                 c->surface_extension, data->surface);
   185     }
   186 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   187 
   188     data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
   189                                             window->w, window->h);
   190 
   191     /* Create the GLES window surface */
   192     data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
   193     
   194     if (data->egl_surface == EGL_NO_SURFACE) {
   195         return SDL_SetError("failed to create a window surface");
   196     }
   197 
   198     if (data->shell_surface) {
   199         wl_shell_surface_set_user_data(data->shell_surface, data);
   200         wl_shell_surface_add_listener(data->shell_surface,
   201                                       &shell_surface_listener, data);
   202     }
   203 
   204 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   205     if (data->extended_surface) {
   206         qt_extended_surface_set_user_data(data->extended_surface, data);
   207         qt_extended_surface_add_listener(data->extended_surface,
   208                                          &extended_surface_listener, data);
   209     }
   210 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   211 
   212     region = wl_compositor_create_region(c->compositor);
   213     wl_region_add(region, 0, 0, window->w, window->h);
   214     wl_surface_set_opaque_region(data->surface, region);
   215     wl_region_destroy(region);
   216 
   217     WAYLAND_wl_display_flush(c->display);
   218 
   219     return 0;
   220 }
   221 
   222 void Wayland_SetWindowSize(_THIS, SDL_Window * window)
   223 {
   224     SDL_VideoData *data = _this->driverdata;
   225     SDL_WindowData *wind = window->driverdata;
   226     struct wl_region *region;
   227 
   228     WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
   229 
   230     region =wl_compositor_create_region(data->compositor);
   231     wl_region_add(region, 0, 0, window->w, window->h);
   232     wl_surface_set_opaque_region(wind->surface, region);
   233     wl_region_destroy(region);
   234 }
   235 
   236 void Wayland_DestroyWindow(_THIS, SDL_Window *window)
   237 {
   238     SDL_VideoData *data = _this->driverdata;
   239     SDL_WindowData *wind = window->driverdata;
   240 
   241     if (data) {
   242         SDL_EGL_DestroySurface(_this, wind->egl_surface);
   243         WAYLAND_wl_egl_window_destroy(wind->egl_window);
   244 
   245         if (wind->shell_surface)
   246             wl_shell_surface_destroy(wind->shell_surface);
   247 
   248 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   249         if (wind->extended_surface)
   250             qt_extended_surface_destroy(wind->extended_surface);
   251 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
   252         wl_surface_destroy(wind->surface);
   253 
   254         SDL_free(wind);
   255         WAYLAND_wl_display_flush(data->display);
   256     }
   257     window->driverdata = NULL;
   258 }
   259 
   260 #endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
   261 
   262 /* vi: set ts=4 sw=4 expandtab: */