From a77ce3301c2035a2aaa3c14e051dceb46ca27924 Mon Sep 17 00:00:00 2001 From: Lasse Holmstedt Date: Mon, 4 Jul 2011 12:08:38 +0200 Subject: [PATCH] Add QScreenOrientationChangeEvent and rotation support to wayland client Qt Compositor propagates screen orientation changes to wayland, which are then picked up by the wayland client. The wayland client then sends a QScreenOrientationChangeEvent to QApplication, which can handle the orientation change. Change-Id: Ieb2225e52b7e3c318648f2cb21dab7937f301505 Reviewed-on: http://codereview.qt.nokia.com/1063 Reviewed-by: Matthias Ettrich --- src/corelib/kernel/qcoreevent.h | 2 + src/gui/kernel/qevent.cpp | 98 +++++++++++++++++++ src/gui/kernel/qevent.h | 24 +++++ src/gui/kernel/qevent_p.h | 11 +++ .../qwaylandwindowmanager-client-protocol.h | 35 ++++--- .../qwaylandwindowmanagerintegration.cpp | 16 ++- .../qwaylandwindowmanagerintegration.h | 1 + .../wayland-windowmanager-protocol.c | 7 +- 8 files changed, 172 insertions(+), 22 deletions(-) diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 302d525042..01a5356f73 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -273,6 +273,8 @@ public: ScrollPrepare = 204, Scroll = 205, + OrientationChange = 206, // Screen orientation has changed + // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 946ab33e80..5d356292fe 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -53,6 +53,7 @@ #include "qevent_p.h" #include "qgesture.h" #include "qgesture_p.h" +#include "qmath.h" #ifdef Q_OS_SYMBIAN #include "private/qcore_symbian_p.h" @@ -4818,4 +4819,101 @@ const QScrollEventPrivate *QScrollEvent::d_func() const return reinterpret_cast(d); } +/*! + \enum QScreenOrientationChangeEvent::Orientation + + This enum describes the orientations that a device can have. + + \value Portrait The device is in a position where its top edge is pointing up. + + \value Landscape The device is rotated clockwise 90 degrees, so that its left edge is pointing up. + + \value PortraitInverted The device is rotated 180 degrees, so that its bottom edge is pointing up. + + \value LandscapeInverted The device is counterclockwise 90 degrees, so that its right edge is pointing up. + + \sa QScreenOrientationChangeEvent::orientation() + \sa QScreenOrientationChangeEvent::orientationInDegrees() +*/ + +/*! + Creates a new QScreenOrientationChangeEvent + \a screenOrientationInDegrees is the new screen orientation, expressed in degrees. + The orientation must be expressed in steps of 90 degrees. +*/ +QScreenOrientationChangeEvent::QScreenOrientationChangeEvent(qint32 screenOrientationInDegrees) + : QEvent(QEvent::OrientationChange) +{ + d = reinterpret_cast(new QScreenOrientationChangeEventPrivate()); + d_func()->orientationInDegrees = screenOrientationInDegrees; + + qint32 orientationIndex = (qAbs(screenOrientationInDegrees) % 360) / 90; + // flip around the negative coords to correct order. + if (screenOrientationInDegrees < 0) { + if (orientationIndex == 1) + orientationIndex = 3; + else if (orientationIndex == 3) + orientationIndex = 1; + } + + orientationIndex = qPow(2, orientationIndex); + d_func()->orientation = (QScreenOrientationChangeEvent::Orientation)(orientationIndex); + d_func()->isValid = (screenOrientationInDegrees % 90 == 0); +} + +/*! + Creates a new QScreenOrientationChangeEvent + \a orientation is the new orientation of the screen. +*/ +QScreenOrientationChangeEvent::QScreenOrientationChangeEvent(QScreenOrientationChangeEvent::Orientation screenOrientation) + : QEvent(QEvent::OrientationChange) +{ + d = reinterpret_cast(new QScreenOrientationChangeEventPrivate()); + d_func()->orientation = screenOrientation; + d_func()->orientationInDegrees = 90 * ((uint)screenOrientation); + d_func()->isValid = true; +} + +/*! + Destroys QScreenOrientationChangeEvent. +*/ +QScreenOrientationChangeEvent::~QScreenOrientationChangeEvent() +{ + delete reinterpret_cast(d); +} + +/*! + Returns the orientation of the screen. +*/ +QScreenOrientationChangeEvent::Orientation QScreenOrientationChangeEvent::orientation() const +{ + return d_func()->orientation; +} + +/*! + Returns the screen orientation in degrees. + The orientation is expressed in steps of 90 degrees and depends on the previous value of the orientation. + This is intended to allow for smooth animations from one orientation to the other. +*/ +qint32 QScreenOrientationChangeEvent::orientationInDegrees() const +{ + return d_func()->orientationInDegrees; +} + +/*! + \internal +*/ +QScreenOrientationChangeEventPrivate *QScreenOrientationChangeEvent::d_func() +{ + return reinterpret_cast(d); +} + +/*! + \internal +*/ +const QScreenOrientationChangeEventPrivate *QScreenOrientationChangeEvent::d_func() const +{ + return reinterpret_cast(d); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 0847fd6046..a6196346a7 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -938,6 +938,30 @@ private: const QScrollEventPrivate *d_func() const; }; +class QScreenOrientationChangeEventPrivate; +class Q_GUI_EXPORT QScreenOrientationChangeEvent : public QEvent +{ +public: + enum Orientation { + Portrait = 1, + Landscape = 2, + PortraitInverted = 4, + LandscapeInverted = 8 + }; + QScreenOrientationChangeEvent(qint32 screenOrientationInDegrees); + QScreenOrientationChangeEvent(Orientation screenOrientation); + ~QScreenOrientationChangeEvent(); + + bool isValid() const; + qint32 orientationInDegrees() const; + Orientation orientation() const; + +private: + QScreenOrientationChangeEventPrivate *d_func(); + const QScreenOrientationChangeEventPrivate *d_func() const; + +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 4dd3d3fbfb..ffe1dfdefc 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -200,6 +200,17 @@ public: QScrollEvent::ScrollState state; }; +class QScreenOrientationChangeEventPrivate +{ +public: + inline QScreenOrientationChangeEventPrivate() + { + } + QScreenOrientationChangeEvent::Orientation orientation; + qint32 orientationInDegrees; + bool isValid; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanager-client-protocol.h b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanager-client-protocol.h index 8b238fb6aa..e781b16c41 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanager-client-protocol.h +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanager-client-protocol.h @@ -39,17 +39,20 @@ struct wl_windowmanager; extern const struct wl_interface wl_windowmanager_interface; struct wl_windowmanager_listener { - void (*client_onscreen_visibility)(void *data, - struct wl_windowmanager *wl_windowmanager, - int visible); + void (*client_onscreen_visibility)(void *data, + struct wl_windowmanager *wl_windowmanager, + int visible); + void (*set_screen_rotation)(void *data, + struct wl_windowmanager *wl_windowmanager, + int rotation); }; static inline int wl_windowmanager_add_listener(struct wl_windowmanager *wl_windowmanager, - const struct wl_windowmanager_listener *listener, void *data) + const struct wl_windowmanager_listener *listener, void *data) { - return wl_proxy_add_listener((struct wl_proxy *) wl_windowmanager, - (void (**)(void)) listener, data); + return wl_proxy_add_listener((struct wl_proxy *) wl_windowmanager, + (void (**)(void)) listener, data); } #define WL_WINDOWMANAGER_MAP_CLIENT_TO_PROCESS 0 @@ -58,42 +61,42 @@ wl_windowmanager_add_listener(struct wl_windowmanager *wl_windowmanager, static inline struct wl_windowmanager * wl_windowmanager_create(struct wl_display *display, uint32_t id, uint32_t version) { - wl_display_bind(display, id, "wl_windowmanager", version); + wl_display_bind(display, id, "wl_windowmanager", version); - return (struct wl_windowmanager *) - wl_proxy_create_for_id(display, &wl_windowmanager_interface, id); + return (struct wl_windowmanager *) + wl_proxy_create_for_id(display, &wl_windowmanager_interface, id); } static inline void wl_windowmanager_set_user_data(struct wl_windowmanager *wl_windowmanager, void *user_data) { - wl_proxy_set_user_data((struct wl_proxy *) wl_windowmanager, user_data); + wl_proxy_set_user_data((struct wl_proxy *) wl_windowmanager, user_data); } static inline void * wl_windowmanager_get_user_data(struct wl_windowmanager *wl_windowmanager) { - return wl_proxy_get_user_data((struct wl_proxy *) wl_windowmanager); + return wl_proxy_get_user_data((struct wl_proxy *) wl_windowmanager); } static inline void wl_windowmanager_destroy(struct wl_windowmanager *wl_windowmanager) { - wl_proxy_destroy((struct wl_proxy *) wl_windowmanager); + wl_proxy_destroy((struct wl_proxy *) wl_windowmanager); } static inline void wl_windowmanager_map_client_to_process(struct wl_windowmanager *wl_windowmanager, uint32_t processid) { - wl_proxy_marshal((struct wl_proxy *) wl_windowmanager, - WL_WINDOWMANAGER_MAP_CLIENT_TO_PROCESS, processid); + wl_proxy_marshal((struct wl_proxy *) wl_windowmanager, + WL_WINDOWMANAGER_MAP_CLIENT_TO_PROCESS, processid); } static inline void wl_windowmanager_authenticate_with_token(struct wl_windowmanager *wl_windowmanager, const char *processid) { - wl_proxy_marshal((struct wl_proxy *) wl_windowmanager, - WL_WINDOWMANAGER_AUTHENTICATE_WITH_TOKEN, processid); + wl_proxy_marshal((struct wl_proxy *) wl_windowmanager, + WL_WINDOWMANAGER_AUTHENTICATE_WITH_TOKEN, processid); } #ifdef __cplusplus diff --git a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp index 1889d05a29..7390c52740 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp @@ -43,13 +43,14 @@ #include "qwaylandwindowmanager-client-protocol.h" #include - #include #include +#include #include const struct wl_windowmanager_listener QWaylandWindowManagerIntegration::mWindowManagerListener = { QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange, + QWaylandWindowManagerIntegration::wlHandleScreenOrientationChange, }; QWaylandWindowManagerIntegration *QWaylandWindowManagerIntegration::createIntegration(QWaylandDisplay *waylandDisplay) @@ -78,6 +79,7 @@ struct wl_windowmanager *QWaylandWindowManagerIntegration::windowManager() const void QWaylandWindowManagerIntegration::wlHandleListenerGlobal(wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) { + Q_UNUSED(version); if (strcmp(interface, "wl_windowmanager") == 0) { QWaylandWindowManagerIntegration *integration = static_cast(data); integration->mWaylandWindowManager = wl_windowmanager_create(display, id, 1); @@ -103,11 +105,19 @@ void QWaylandWindowManagerIntegration::authenticateWithToken(const QByteArray &t void QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange(void *data, struct wl_windowmanager *wl_windowmanager, int visible) { - QWaylandWindowManagerIntegration *integration = (QWaylandWindowManagerIntegration *)data; - + Q_UNUSED(data); + Q_UNUSED(wl_windowmanager); QEvent evt(visible != 0 ? QEvent::ApplicationActivated : QEvent::ApplicationDeactivated); QCoreApplication::sendEvent(QCoreApplication::instance(), &evt); qDebug() << "OnScreenVisibility" << (visible != 0); } + +void QWaylandWindowManagerIntegration::wlHandleScreenOrientationChange(void *data, struct wl_windowmanager *wl_windowmanager, int screenOrientation) +{ + Q_UNUSED(data); + Q_UNUSED(wl_windowmanager); + QScreenOrientationChangeEvent event(screenOrientation); + QCoreApplication::sendEvent(QCoreApplication::instance(), &event); +} diff --git a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.h b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.h index ac76fd6211..6b4658c7e1 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.h +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.h @@ -63,6 +63,7 @@ private: const char *interface, uint32_t version, void *data); static void wlHandleOnScreenVisibilityChange(void *data, struct wl_windowmanager *wl_windowmanager, int visible); + static void wlHandleScreenOrientationChange(void *data, struct wl_windowmanager *wl_windowmanager, int screenOrientation); private: QWaylandDisplay *mWaylandDisplay; diff --git a/src/plugins/platforms/wayland/windowmanager_integration/wayland-windowmanager-protocol.c b/src/plugins/platforms/wayland/windowmanager_integration/wayland-windowmanager-protocol.c index e759b3ac1b..8125dec4d3 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/wayland-windowmanager-protocol.c +++ b/src/plugins/platforms/wayland/windowmanager_integration/wayland-windowmanager-protocol.c @@ -26,12 +26,13 @@ #include "wayland-util.h" static const struct wl_message wl_windowmanager_requests[] = { - { "map_client_to_process", "u", NULL }, - { "authenticate_with_token", "s", NULL }, + { "map_client_to_process", "u", NULL }, + { "authenticate_with_token", "s", NULL }, }; static const struct wl_message wl_windowmanager_events[] = { - { "client_onscreen_visibility", "i", NULL }, + { "client_onscreen_visibility", "i", NULL }, + { "set_screen_rotation", "i", NULL }, }; WL_EXPORT const struct wl_interface wl_windowmanager_interface = {