Fixed bug 3063 - Wayland: SDL resizes EGL surface to 0x0.
authorSam Lantinga <slouken@libsdl.org>
Fri, 07 Oct 2016 18:11:03 -0700
changeset 10492786e10ab72d8
parent 10491 c64e191b5518
child 10493 30155a7426c4
Fixed bug 3063 - Wayland: SDL resizes EGL surface to 0x0.

x414e54

Wayland will sometimes send empty resize events (0 width and 0 height) to the client. I have not worked out the exact conditions a client would receive these but I can assume it might be if the window is offscreen or not mapped yet.

This causes issues with some SDL clients as they receive the 0x0 event and unexpected resize event or might not request to resize back to the correct size.

As per the wl_shell Wayland spec configure events are only a suggestion and the client is free to ignore or pick a different size (this is how min/max and fixed aspect ratio is supped to be implemented).

A patch is attached but is just the first iteration and I will fix any issues such as checking for FULLSCREEN/MAXIMIZED or RESIZABLE flags unless someone else fixes this first.

I have update to take into account non resizable and fullscreen windows. Also adding in maximize/restore and title functions for Wayland.
src/video/wayland/SDL_waylandvideo.c
src/video/wayland/SDL_waylandwindow.c
src/video/wayland/SDL_waylandwindow.h
     1.1 --- a/src/video/wayland/SDL_waylandvideo.c	Fri Oct 07 18:09:09 2016 -0700
     1.2 +++ b/src/video/wayland/SDL_waylandvideo.c	Fri Oct 07 18:11:03 2016 -0700
     1.3 @@ -169,7 +169,10 @@
     1.4      device->CreateWindow = Wayland_CreateWindow;
     1.5      device->ShowWindow = Wayland_ShowWindow;
     1.6      device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
     1.7 +    device->MaximizeWindow = Wayland_MaximizeWindow;
     1.8 +    device->RestoreWindow = Wayland_RestoreWindow;
     1.9      device->SetWindowSize = Wayland_SetWindowSize;
    1.10 +    device->SetWindowTitle = Wayland_SetWindowTitle;
    1.11      device->DestroyWindow = Wayland_DestroyWindow;
    1.12      device->SetWindowHitTest = Wayland_SetWindowHitTest;
    1.13  
     2.1 --- a/src/video/wayland/SDL_waylandwindow.c	Fri Oct 07 18:09:09 2016 -0700
     2.2 +++ b/src/video/wayland/SDL_waylandwindow.c	Fri Oct 07 18:11:03 2016 -0700
     2.3 @@ -47,6 +47,33 @@
     2.4      SDL_Window *window = wind->sdlwindow;
     2.5      struct wl_region *region;
     2.6  
     2.7 +    /* wl_shell_surface spec states that this is a suggestion.
     2.8 +       Ignore if less than or greater than max/min size. */
     2.9 +
    2.10 +    if (width == 0 || height == 0) {
    2.11 +        return;
    2.12 +    }
    2.13 +
    2.14 +    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
    2.15 +        if ((window->flags & SDL_WINDOW_RESIZABLE)) {
    2.16 +            if (window->max_w > 0) {
    2.17 +                width = SDL_min(width, window->max_w);
    2.18 +            } 
    2.19 +            width = SDL_max(width, window->min_w);
    2.20 +
    2.21 +            if (window->max_h > 0) {
    2.22 +                height = SDL_min(height, window->max_h);
    2.23 +            }
    2.24 +            height = SDL_max(height, window->min_h);
    2.25 +        } else {
    2.26 +            return;
    2.27 +        }
    2.28 +    }
    2.29 +
    2.30 +    if (width == window->w && height == window->h) {
    2.31 +        return;
    2.32 +    }
    2.33 +
    2.34      window->w = width;
    2.35      window->h = height;
    2.36      WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
    2.37 @@ -146,6 +173,26 @@
    2.38      WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
    2.39  }
    2.40  
    2.41 +void
    2.42 +Wayland_RestoreWindow(_THIS, SDL_Window * window)
    2.43 +{
    2.44 +    SDL_WindowData *wind = window->driverdata;
    2.45 +
    2.46 +    wl_shell_surface_set_toplevel(wind->shell_surface);
    2.47 +
    2.48 +    WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
    2.49 +}
    2.50 +
    2.51 +void
    2.52 +Wayland_MaximizeWindow(_THIS, SDL_Window * window)
    2.53 +{
    2.54 +    SDL_WindowData *wind = window->driverdata;
    2.55 +
    2.56 +    wl_shell_surface_set_maximized(wind->shell_surface, NULL);
    2.57 +
    2.58 +    WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
    2.59 +}
    2.60 +
    2.61  int Wayland_CreateWindow(_THIS, SDL_Window *window)
    2.62  {
    2.63      SDL_WindowData *data;
    2.64 @@ -239,6 +286,17 @@
    2.65      wl_region_destroy(region);
    2.66  }
    2.67  
    2.68 +void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
    2.69 +{
    2.70 +    SDL_WindowData *wind = window->driverdata;
    2.71 +    
    2.72 +    if (window->title != NULL) {
    2.73 +        wl_shell_surface_set_title(wind->shell_surface, window->title);
    2.74 +    }
    2.75 +
    2.76 +    WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
    2.77 +}
    2.78 +
    2.79  void Wayland_DestroyWindow(_THIS, SDL_Window *window)
    2.80  {
    2.81      SDL_VideoData *data = _this->driverdata;
     3.1 --- a/src/video/wayland/SDL_waylandwindow.h	Fri Oct 07 18:09:09 2016 -0700
     3.2 +++ b/src/video/wayland/SDL_waylandwindow.h	Fri Oct 07 18:11:03 2016 -0700
     3.3 @@ -50,8 +50,11 @@
     3.4  extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
     3.5                                          SDL_VideoDisplay * _display,
     3.6                                          SDL_bool fullscreen);
     3.7 +extern void Wayland_MaximizeWindow(_THIS, SDL_Window * window);
     3.8 +extern void Wayland_RestoreWindow(_THIS, SDL_Window * window);
     3.9  extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
    3.10  extern void Wayland_SetWindowSize(_THIS, SDL_Window * window);
    3.11 +extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);
    3.12  extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
    3.13  
    3.14  extern SDL_bool