From 612dab26cdf7b9a1deac44f3e0e848f42be477e2 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Tue, 14 Apr 2015 15:19:31 +0200 Subject: [PATCH] [qtwayland] Set orientation and window flags via SDL hints --- include/SDL_hints.h | 27 ++++++++++++ src/video/wayland/SDL_waylandwindow.c | 78 ++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index b98ce68..5d96f0f 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -435,6 +435,33 @@ extern "C" { */ #define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" +/** + * \brief A variable describing the content orientation on QtWayland-based platforms. + * + * On QtWayland platforms, windows are rotated client-side to allow for custom + * transitions. In order to correctly position overlays (e.g. volume bar) and + * gestures (e.g. events view, close/minimize gestures), the system needs to + * know in which orientation the application is currently drawing its contents. + * + * This does not cause the window to be rotated or resized, the application + * needs to take care of drawing the content in the right orientation (the + * framebuffer is always in portrait mode). + * + * This variable can be one of the following values: + * "primary" (default), "portrait", "landscape", "inverted-portrait", "inverted-landscape" + */ +#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION" + +/** + * \brief Flags to set on QtWayland windows to integrate with the native window manager. + * + * On QtWayland platforms, this hint controls the flags to set on the windows. + * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures. + * + * This variable is a space-separated list of the following values (empty = no flags): + * "OverridesSystemGestures", "StaysOnTop", "BypassWindowManager" + */ +#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS" /** * \brief An enumeration of hint priorities diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index c040ca9..518c0bf 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -29,6 +29,7 @@ #include "SDL_waylandwindow.h" #include "SDL_waylandvideo.h" #include "SDL_waylandtouch.h" +#include "SDL_hints.h" static void handle_ping(void *data, struct wl_shell_surface *shell_surface, @@ -109,6 +110,73 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window) WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display ); } +#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH +static void QtExtendedSurface_OnHintChanged(void *userdata, const char *name, + const char *oldValue, const char *newValue) +{ + struct qt_extended_surface *qt_extended_surface = userdata; + + if (name == NULL) { + return; + } + + if (strcmp(name, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION) == 0) { + int32_t orientation = QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION; + + if (newValue != NULL) { + if (strcmp(newValue, "portrait") == 0) { + orientation = QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION; + } else if (strcmp(newValue, "landscape") == 0) { + orientation = QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION; + } else if (strcmp(newValue, "inverted-portrait") == 0) { + orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION; + } else if (strcmp(newValue, "inverted-landscape") == 0) { + orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION; + } + } + + qt_extended_surface_set_content_orientation(qt_extended_surface, orientation); + } else if (strcmp(name, SDL_HINT_QTWAYLAND_WINDOW_FLAGS) == 0) { + uint32_t flags = 0; + + if (newValue != NULL) { + char *tmp = strdup(newValue); + char *saveptr = NULL; + + char *flag = strtok_r(tmp, " ", &saveptr); + while (flag) { + if (strcmp(flag, "OverridesSystemGestures") == 0) { + flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES; + } else if (strcmp(flag, "StaysOnTop") == 0) { + flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP; + } else if (strcmp(flag, "BypassWindowManager") == 0) { + // See https://github.com/qtproject/qtwayland/commit/fb4267103d + flags |= 4 /* QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER */; + } + + flag = strtok_r(NULL, " ", &saveptr); + } + + free(tmp); + } + + qt_extended_surface_set_window_flags(qt_extended_surface, flags); + } +} + +static void QtExtendedSurface_Subscribe(struct qt_extended_surface *surface, const char *name) +{ + SDL_AddHintCallback(name, QtExtendedSurface_OnHintChanged, surface); + // Initial call to set the flags if the hints have been set before + QtExtendedSurface_OnHintChanged(surface, name, "", SDL_GetHint(name)); +} + +static void QtExtendedSurface_Unsubscribe(struct qt_extended_surface *surface, const char *name) +{ + SDL_DelHintCallback(name, QtExtendedSurface_OnHintChanged, surface); +} +#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ + void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen) @@ -158,10 +226,13 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window) wl_surface_set_user_data(data->surface, data); data->shell_surface = wl_shell_get_shell_surface(c->shell, data->surface); -#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH +#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH if (c->surface_extension) { data->extended_surface = qt_surface_extension_get_extended_surface( c->surface_extension, data->surface); + + QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION); + QtExtendedSurface_Subscribe(data->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS); } #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ @@ -240,8 +311,11 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window) wl_shell_surface_destroy(wind->shell_surface); #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH - if (wind->extended_surface) + if (wind->extended_surface) { + QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION); + QtExtendedSurface_Unsubscribe(wind->extended_surface, SDL_HINT_QTWAYLAND_WINDOW_FLAGS); qt_extended_surface_destroy(wind->extended_surface); + } #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ wl_surface_destroy(wind->surface); -- 2.1.4