changeset: 9559:632a38a709c9 tag: tip user: Thomas Perl date: Tue Apr 14 17:37:48 2015 +0200 summary: QtWayland: Set orientation and window flags via SDL hints diff -r 4bab88dd387e -r 632a38a709c9 include/SDL_hints.h --- a/include/SDL_hints.h Mon Apr 13 20:52:38 2015 +0200 +++ b/include/SDL_hints.h Tue Apr 14 17:37:48 2015 +0200 @@ -344,6 +344,33 @@ */ #define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION" +/** + * \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 If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS) diff -r 4bab88dd387e -r 632a38a709c9 src/video/wayland/SDL_waylandwindow.c --- a/src/video/wayland/SDL_waylandwindow.c Mon Apr 13 20:52:38 2015 +0200 +++ b/src/video/wayland/SDL_waylandwindow.c Tue Apr 14 17:37:48 2015 +0200 @@ -129,6 +129,73 @@ 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) @@ -178,10 +245,13 @@ 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 */ @@ -246,8 +316,11 @@ 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);