src/video/wayland/SDL_waylandwindow.c
changeset 12033 bc702c5a7c3a
parent 11944 295cf9910d75
child 12201 8bdc4d340419
child 12367 8256aaaafe54
     1.1 --- a/src/video/wayland/SDL_waylandwindow.c	Sun Jun 24 15:21:01 2018 -0400
     1.2 +++ b/src/video/wayland/SDL_waylandwindow.c	Sun Jun 24 22:42:36 2018 -0700
     1.3 @@ -33,6 +33,7 @@
     1.4  #include "SDL_waylanddyn.h"
     1.5  #include "SDL_hints.h"
     1.6  
     1.7 +#include "xdg-shell-client-protocol.h"
     1.8  #include "xdg-shell-unstable-v6-client-protocol.h"
     1.9  
    1.10  /* On modern desktops, we probably will use the xdg-shell protocol instead
    1.11 @@ -185,6 +186,87 @@
    1.12  };
    1.13  
    1.14  
    1.15 +
    1.16 +static void
    1.17 +handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
    1.18 +{
    1.19 +    SDL_WindowData *wind = (SDL_WindowData *)data;
    1.20 +    SDL_Window *window = wind->sdlwindow;
    1.21 +    struct wl_region *region;
    1.22 +
    1.23 +    wind->shell_surface.xdg.initial_configure_seen = SDL_TRUE;
    1.24 +
    1.25 +    WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
    1.26 +
    1.27 +    region = wl_compositor_create_region(wind->waylandData->compositor);
    1.28 +    wl_region_add(region, 0, 0, window->w, window->h);
    1.29 +    wl_surface_set_opaque_region(wind->surface, region);
    1.30 +    wl_region_destroy(region);
    1.31 +    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, window->w, window->h);
    1.32 +    xdg_surface_ack_configure(xdg, serial);
    1.33 +}
    1.34 +
    1.35 +static const struct xdg_surface_listener shell_surface_listener_xdg = {
    1.36 +    handle_configure_xdg_shell_surface
    1.37 +};
    1.38 +
    1.39 +
    1.40 +static void
    1.41 +handle_configure_xdg_toplevel(void *data,
    1.42 +			  struct xdg_toplevel *xdg_toplevel,
    1.43 +			  int32_t width,
    1.44 +			  int32_t height,
    1.45 +			  struct wl_array *states)
    1.46 +{
    1.47 +    SDL_WindowData *wind = (SDL_WindowData *)data;
    1.48 +    SDL_Window *window = wind->sdlwindow;
    1.49 +
    1.50 +    /* wl_shell_surface spec states that this is a suggestion.
    1.51 +       Ignore if less than or greater than max/min size. */
    1.52 +
    1.53 +    if (width == 0 || height == 0) {
    1.54 +        return;
    1.55 +    }
    1.56 +
    1.57 +    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
    1.58 +        if ((window->flags & SDL_WINDOW_RESIZABLE)) {
    1.59 +            if (window->max_w > 0) {
    1.60 +                width = SDL_min(width, window->max_w);
    1.61 +            } 
    1.62 +            width = SDL_max(width, window->min_w);
    1.63 +
    1.64 +            if (window->max_h > 0) {
    1.65 +                height = SDL_min(height, window->max_h);
    1.66 +            }
    1.67 +            height = SDL_max(height, window->min_h);
    1.68 +        } else {
    1.69 +            return;
    1.70 +        }
    1.71 +    }
    1.72 +
    1.73 +    if (width == window->w && height == window->h) {
    1.74 +        return;
    1.75 +    }
    1.76 +
    1.77 +    window->w = width;
    1.78 +    window->h = height;
    1.79 +}
    1.80 +
    1.81 +static void
    1.82 +handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
    1.83 +{
    1.84 +    SDL_WindowData *window = (SDL_WindowData *)data;
    1.85 +    SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
    1.86 +}
    1.87 +
    1.88 +static const struct xdg_toplevel_listener toplevel_listener_xdg = {
    1.89 +    handle_configure_xdg_toplevel,
    1.90 +    handle_close_xdg_toplevel
    1.91 +};
    1.92 +
    1.93 +
    1.94 +
    1.95 +
    1.96  #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
    1.97  static void
    1.98  handle_onscreen_visibility(void *data,
    1.99 @@ -257,7 +339,13 @@
   1.100      const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
   1.101      SDL_WindowData *wind = window->driverdata;
   1.102  
   1.103 -    if (viddata->shell.zxdg) {
   1.104 +    if (viddata->shell.xdg) {
   1.105 +        if (output) {
   1.106 +            xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
   1.107 +        } else {
   1.108 +            xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
   1.109 +        }
   1.110 +    } else if (viddata->shell.zxdg) {
   1.111          if (output) {
   1.112              zxdg_toplevel_v6_set_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel, output);
   1.113          } else {
   1.114 @@ -362,7 +450,8 @@
   1.115      SDL_WindowData *wind = window->driverdata;
   1.116      const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
   1.117  
   1.118 -    if (viddata->shell.zxdg) {
   1.119 +    if (viddata->shell.xdg) {
   1.120 +    } else if (viddata->shell.zxdg) {
   1.121      } else {
   1.122          wl_shell_surface_set_toplevel(wind->shell_surface.wl);
   1.123      }
   1.124 @@ -376,7 +465,9 @@
   1.125      SDL_WindowData *wind = window->driverdata;
   1.126      SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
   1.127  
   1.128 -    if (viddata->shell.zxdg) {
   1.129 +    if (viddata->shell.xdg) {
   1.130 +        xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
   1.131 +    } else if (viddata->shell.zxdg) {
   1.132          zxdg_toplevel_v6_set_maximized(wind->shell_surface.zxdg.roleobj.toplevel);
   1.133      } else {
   1.134          wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
   1.135 @@ -417,7 +508,13 @@
   1.136          wl_compositor_create_surface(c->compositor);
   1.137      wl_surface_set_user_data(data->surface, data);
   1.138  
   1.139 -    if (c->shell.zxdg) {
   1.140 +    if (c->shell.xdg) {
   1.141 +        data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
   1.142 +        /* !!! FIXME: add popup role */
   1.143 +        data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
   1.144 +        xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
   1.145 +        xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
   1.146 +    } else if (c->shell.zxdg) {
   1.147          data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
   1.148          /* !!! FIXME: add popup role */
   1.149          data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface);
   1.150 @@ -448,7 +545,12 @@
   1.151          return SDL_SetError("failed to create a window surface");
   1.152      }
   1.153  
   1.154 -    if (c->shell.zxdg) {
   1.155 +    if (c->shell.xdg) {
   1.156 +        if (data->shell_surface.xdg.surface) {
   1.157 +            xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
   1.158 +            xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
   1.159 +        }
   1.160 +    } else if (c->shell.zxdg) {
   1.161          if (data->shell_surface.zxdg.surface) {
   1.162              zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
   1.163              zxdg_surface_v6_add_listener(data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg, data);
   1.164 @@ -482,7 +584,14 @@
   1.165  
   1.166      /* we have to wait until the surface gets a "configure" event, or
   1.167         use of this surface will fail. This is a new rule for xdg_shell. */
   1.168 -    if (c->shell.zxdg) {
   1.169 +    if (c->shell.xdg) {
   1.170 +        if (data->shell_surface.xdg.surface) {
   1.171 +            while (!data->shell_surface.xdg.initial_configure_seen) {
   1.172 +                WAYLAND_wl_display_flush(c->display);
   1.173 +                WAYLAND_wl_display_dispatch(c->display);
   1.174 +            }
   1.175 +        }
   1.176 +    } else if (c->shell.zxdg) {
   1.177          if (data->shell_surface.zxdg.surface) {
   1.178              while (!data->shell_surface.zxdg.initial_configure_seen) {
   1.179                  WAYLAND_wl_display_flush(c->display);
   1.180 @@ -514,7 +623,9 @@
   1.181      SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
   1.182      
   1.183      if (window->title != NULL) {
   1.184 -        if (viddata->shell.zxdg) {
   1.185 +        if (viddata->shell.xdg) {
   1.186 +            xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, window->title);
   1.187 +        } else if (viddata->shell.zxdg) {
   1.188              zxdg_toplevel_v6_set_title(wind->shell_surface.zxdg.roleobj.toplevel, window->title);
   1.189          } else {
   1.190              wl_shell_surface_set_title(wind->shell_surface.wl, window->title);
   1.191 @@ -533,7 +644,14 @@
   1.192          SDL_EGL_DestroySurface(_this, wind->egl_surface);
   1.193          WAYLAND_wl_egl_window_destroy(wind->egl_window);
   1.194  
   1.195 -        if (data->shell.zxdg) {
   1.196 +        if (data->shell.xdg) {
   1.197 +            if (wind->shell_surface.xdg.roleobj.toplevel) {
   1.198 +                xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
   1.199 +            }
   1.200 +            if (wind->shell_surface.zxdg.surface) {
   1.201 +                xdg_surface_destroy(wind->shell_surface.xdg.surface);
   1.202 +            }
   1.203 +        } else if (data->shell.zxdg) {
   1.204              if (wind->shell_surface.zxdg.roleobj.toplevel) {
   1.205                  zxdg_toplevel_v6_destroy(wind->shell_surface.zxdg.roleobj.toplevel);
   1.206              }