diff options
Diffstat (limited to 'src/plugins/platforms/wayland')
9 files changed, 278 insertions, 52 deletions
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index f3e2e9fb94..1314eda012 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -311,7 +311,7 @@ void QWaylandDisplay::displayHandleGlobal(uint32_t id, wl_shell_add_listener(mShell, &shellListener, this); } else if (interface == "wl_input_device") { QWaylandInputDevice *inputDevice = - new QWaylandInputDevice(mDisplay, id); + new QWaylandInputDevice(this, id); mInputDevices.append(inputDevice); } else if (interface == "wl_selection_offer") { QWaylandClipboard::instance(display)->createSelectionOffer(id); diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 7f3737613f..c1e2325766 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -45,10 +45,9 @@ #include "qwaylandwindow.h" #include "qwaylandbuffer.h" -#include <QWindowSystemInterface> - #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> +#include <QDebug> #include <unistd.h> #include <fcntl.h> @@ -58,13 +57,17 @@ #include <X11/keysym.h> #endif -QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, +//#define POINT_DEBUG + +QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id) - : mDisplay(display) - , mInputDevice(wl_input_device_create(display, id, 1)) + : mQDisplay(display) + , mDisplay(display->wl_display()) + , mInputDevice(wl_input_device_create(mDisplay, id, 1)) , mPointerFocus(NULL) , mKeyboardFocus(NULL) , mButtons(0) + , mTouchState(QEvent::TouchBegin) { wl_input_device_add_listener(mInputDevice, &inputDeviceListener, @@ -338,12 +341,168 @@ void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, #endif } +void QWaylandInputDevice::inputHandleTouchDown(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, + int id, + int x, + int y) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointPressed); +} + +void QWaylandInputDevice::inputHandleTouchUp(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, + int id) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + inputDevice->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased); +} + +void QWaylandInputDevice::inputHandleTouchMotion(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, + int id, + int x, + int y) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointMoved); +} + +void QWaylandInputDevice::handleTouchPoint(int id, int x, int y, Qt::TouchPointState state) +{ + QWindowSystemInterface::TouchPoint tp; + + // Find out the coordinates for Released events. + bool coordsOk = false; + if (state == Qt::TouchPointReleased) + for (int i = 0; i < mPrevTouchPoints.count(); ++i) + if (mPrevTouchPoints.at(i).id == id) { + tp.area = mPrevTouchPoints.at(i).area; + coordsOk = true; + break; + } + + if (!coordsOk) { + // x and y are surface relative. + // We need a global (screen) position. + + QWaylandWindow *win = mPointerFocus; + if (!win) + win = mKeyboardFocus; +#ifdef POINT_DEBUG + qDebug() << "surface relative coords" << x << y << "using window" << win; +#endif + if (!win) + return; + + QRect winRect = win->geometry(); + + // Get a normalized position (0..1). + const qreal nx = x / qreal(winRect.width()); + const qreal ny = y / qreal(winRect.height()); + tp.normalPosition = QPointF(nx, ny); + + // Map to screen. + QPlatformScreen *screen = mQDisplay->screens().at(0); + QRect screenRect = screen->geometry(); + x = int(nx * screenRect.width()); + y = int(ny * screenRect.height()); + +#ifdef POINT_DEBUG + qDebug() << "normalized position" << nx << ny + << "win rect" << winRect << "screen rect" << screenRect; + qDebug() << "mapped to screen position" << x << y; +#endif + + tp.area = QRectF(x, y, 1, 1); + } + + tp.state = state; + tp.id = id; + tp.isPrimary = mTouchPoints.isEmpty(); + tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1; + mTouchPoints.append(tp); +} + +void QWaylandInputDevice::inputHandleTouchFrame(void *data, struct wl_input_device *wl_input_device) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + inputDevice->handleTouchFrame(); +} + +void QWaylandInputDevice::handleTouchFrame() +{ + // Copy all points, that are in the previous but not in the current list, as stationary. + for (int i = 0; i < mPrevTouchPoints.count(); ++i) { + const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i)); + if (prevPoint.state == Qt::TouchPointReleased) + continue; + bool found = false; + for (int j = 0; j < mTouchPoints.count(); ++j) + if (mTouchPoints.at(j).id == prevPoint.id) { + found = true; + break; + } + if (!found) { + QWindowSystemInterface::TouchPoint p = prevPoint; + p.state = Qt::TouchPointStationary; + mTouchPoints.append(p); + } + } + + if (mTouchPoints.isEmpty()) { + mPrevTouchPoints.clear(); + return; + } + +#ifdef POINT_DEBUG + qDebug() << mTouchPoints.count() << "touchpoints, event type" << mTouchState; + for (int i = 0; i < mTouchPoints.count(); ++i) + qDebug() << " " << mTouchPoints[i].id << mTouchPoints[i].state << mTouchPoints[i].area; +#endif + + QWindowSystemInterface::handleTouchEvent(0, mTouchState, QTouchEvent::TouchScreen, mTouchPoints); + + bool allReleased = true; + for (int i = 0; i < mTouchPoints.count(); ++i) + if (mTouchPoints.at(i).state != Qt::TouchPointReleased) { + allReleased = false; + break; + } + + mPrevTouchPoints = mTouchPoints; + mTouchPoints.clear(); + + if (allReleased) { +#ifdef POINT_DEBUG + qDebug() << mTouchPoints.count() << "touchpoints, event type" << QEvent::TouchEnd; +#endif + QWindowSystemInterface::handleTouchEvent(0, QEvent::TouchEnd, QTouchEvent::TouchScreen, mTouchPoints); + mTouchState = QEvent::TouchBegin; + mPrevTouchPoints.clear(); + } else if (mTouchState == QEvent::TouchBegin) + mTouchState = QEvent::TouchUpdate; +} + +void QWaylandInputDevice::inputHandleTouchCancel(void *data, struct wl_input_device *wl_input_device) +{ +} + const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { QWaylandInputDevice::inputHandleMotion, QWaylandInputDevice::inputHandleButton, QWaylandInputDevice::inputHandleKey, QWaylandInputDevice::inputHandlePointerFocus, QWaylandInputDevice::inputHandleKeyboardFocus, + QWaylandInputDevice::inputHandleTouchDown, + QWaylandInputDevice::inputHandleTouchUp, + QWaylandInputDevice::inputHandleTouchMotion, + QWaylandInputDevice::inputHandleTouchFrame, + QWaylandInputDevice::inputHandleTouchCancel }; void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h index e5be5bb8d2..008ecf144d 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -48,21 +48,24 @@ #include <QObject> #include <QtGui/QPlatformIntegration> #include <QtGui/QPlatformScreen> +#include <QWindowSystemInterface> #include <wayland-client.h> QT_BEGIN_NAMESPACE class QWaylandWindow; +class QWaylandDisplay; class QWaylandInputDevice { public: - QWaylandInputDevice(struct wl_display *display, uint32_t id); + QWaylandInputDevice(QWaylandDisplay *display, uint32_t id); void attach(QWaylandBuffer *buffer, int x, int y); void handleWindowDestroyed(QWaylandWindow *window); struct wl_input_device *wl_input_device() const { return mInputDevice; } private: + QWaylandDisplay *mQDisplay; struct wl_display *mDisplay; struct wl_input_device *mInputDevice; QWaylandWindow *mPointerFocus; @@ -95,6 +98,32 @@ private: uint32_t time, struct wl_surface *surface, struct wl_array *keys); + static void inputHandleTouchDown(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, + int id, + int x, + int y); + static void inputHandleTouchUp(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, + int id); + static void inputHandleTouchMotion(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, + int id, + int x, + int y); + static void inputHandleTouchFrame(void *data, + struct wl_input_device *wl_input_device); + static void inputHandleTouchCancel(void *data, + struct wl_input_device *wl_input_device); + + void handleTouchPoint(int id, int x, int y, Qt::TouchPointState state); + void handleTouchFrame(); + QList<QWindowSystemInterface::TouchPoint> mTouchPoints; + QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints; + QEvent::Type mTouchState; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 2376df55c9..f685dae729 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -146,8 +146,8 @@ void QWaylandWindow::newSurfaceCreated() { if (mBuffer) { wl_surface_attach(mSurface,mBuffer->buffer(),0,0); - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); - wl_surface_damage(mSurface,0,0,mBuffer->size().width(),mBuffer->size().height()); + // do not damage the surface here, as this leads to graphical corruptions in the compositor until + // the first frame has been rendered } } diff --git a/src/plugins/platforms/wayland/wayland_sha1.txt b/src/plugins/platforms/wayland/wayland_sha1.txt index a696e760d5..9596f7b0a8 100644 --- a/src/plugins/platforms/wayland/wayland_sha1.txt +++ b/src/plugins/platforms/wayland/wayland_sha1.txt @@ -1,3 +1,3 @@ This version of the Qt Wayland plugin is checked against the following sha1 from the Wayland repository: -bfea3d6befdb688d5354e6f15a9400ea637febf9 +aa7bbb210b7121b9314993228960240358e9b123 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 73673aef6f..e781b16c41 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanager-client-protocol.h +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanager-client-protocol.h @@ -36,71 +36,67 @@ struct wl_client; struct wl_windowmanager; -struct wl_proxy; - -extern void -wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...); -extern struct wl_proxy * -wl_proxy_create(struct wl_proxy *factory, - const struct wl_interface *interface); -extern struct wl_proxy * -wl_proxy_create_for_id(struct wl_display *display, - const struct wl_interface *interface, uint32_t id); -extern void -wl_proxy_destroy(struct wl_proxy *proxy); - -extern int -wl_proxy_add_listener(struct wl_proxy *proxy, - void (**implementation)(void), void *data); - -extern void -wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); - -extern void * -wl_proxy_get_user_data(struct wl_proxy *proxy); - extern const struct wl_interface wl_windowmanager_interface; -#define wl_WINDOWMANAGER_MAP_CLIENT_TO_PROCESS 0 -#define wl_WINDOWMANAGER_AUTHENTICATE_WITH_TOKEN 1 +struct wl_windowmanager_listener { + 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) +{ + return wl_proxy_add_listener((struct wl_proxy *) wl_windowmanager, + (void (**)(void)) listener, data); +} + +#define WL_WINDOWMANAGER_MAP_CLIENT_TO_PROCESS 0 +#define WL_WINDOWMANAGER_AUTHENTICATE_WITH_TOKEN 1 static inline struct wl_windowmanager * -wl_windowmanager_create(struct wl_display *display, uint32_t id) +wl_windowmanager_create(struct wl_display *display, uint32_t id, uint32_t version) { - return (struct wl_windowmanager *) - wl_proxy_create_for_id(display, &wl_windowmanager_interface, id); + wl_display_bind(display, id, "wl_windowmanager", version); + + 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 *wl_authentication_token) +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, wl_authentication_token); + 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 4236f395cb..7390c52740 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp @@ -43,6 +43,15 @@ #include "qwaylandwindowmanager-client-protocol.h" #include <stdint.h> +#include <QDebug> +#include <QEvent> +#include <QtGui/QtEvents> +#include <QCoreApplication> + +const struct wl_windowmanager_listener QWaylandWindowManagerIntegration::mWindowManagerListener = { + QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange, + QWaylandWindowManagerIntegration::wlHandleScreenOrientationChange, +}; QWaylandWindowManagerIntegration *QWaylandWindowManagerIntegration::createIntegration(QWaylandDisplay *waylandDisplay) { @@ -70,9 +79,12 @@ 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<QWaylandWindowManagerIntegration *>(data); - integration->mWaylandWindowManager = wl_windowmanager_create(display, id); + integration->mWaylandWindowManager = wl_windowmanager_create(display, id, 1); + + wl_windowmanager_add_listener(integration->mWaylandWindowManager, &mWindowManagerListener, integration); } } @@ -90,3 +102,22 @@ void QWaylandWindowManagerIntegration::authenticateWithToken(const QByteArray &t if (mWaylandWindowManager) wl_windowmanager_authenticate_with_token(mWaylandWindowManager, authToken.constData()); } + +void QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange(void *data, struct wl_windowmanager *wl_windowmanager, int visible) +{ + 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 0e3781dbe2..6b4658c7e1 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.h +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.h @@ -62,9 +62,14 @@ private: static void wlHandleListenerGlobal(wl_display *display, uint32_t id, 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; struct wl_windowmanager *mWaylandWindowManager; + + static const struct wl_windowmanager_listener mWindowManagerListener; }; #endif // QWAYLANDWINDOWMANAGERINTEGRATION_H 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 0250801b1f..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,18 @@ #include "wayland-util.h" static const struct wl_message wl_windowmanager_requests[] = { - { "map_client_to_process", "u" }, - { "authenticate_with_token", "s" }, + { "map_client_to_process", "u", NULL }, + { "authenticate_with_token", "s", NULL }, +}; + +static const struct wl_message wl_windowmanager_events[] = { + { "client_onscreen_visibility", "i", NULL }, + { "set_screen_rotation", "i", NULL }, }; WL_EXPORT const struct wl_interface wl_windowmanager_interface = { - "wl_windowmanager", 1, - ARRAY_LENGTH(wl_windowmanager_requests), wl_windowmanager_requests, - 0, NULL, + "wl_windowmanager", 1, + ARRAY_LENGTH(wl_windowmanager_requests), wl_windowmanager_requests, + ARRAY_LENGTH(wl_windowmanager_events), wl_windowmanager_events, }; + |