From db14c19d17ef739237897d11a9d0afdf99ebb207 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 2 Mar 2016 23:10:16 -0800 Subject: [PATCH 1/3] Fix failure to build from sources: missing #include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qwaylandinputdeviceintegration_p.h:64:85: error: ‘uint32_t’ has not been declared Change-Id: Ic747cc2ab45e4dc6bb70ffff143843d1ed4a341b Reviewed-by: Lars Knoll --- .../inputdeviceintegration/qwaylandinputdeviceintegration_p.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h b/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h index f3c59c898a3..721cb27a1ad 100644 --- a/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h +++ b/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h @@ -48,6 +48,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE namespace QtWaylandClient { From 2414bb75bb692b46c779b170f04519b0a36d99ff Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 11 Mar 2016 11:59:19 +0100 Subject: [PATCH 2/3] Fix client xdg_surface not handling all states from configure event The code used sizeof(state) when it should have been sizeof(*state). Change-Id: Id1714a5e90e6c58850023424726de26719a69046 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/wayland/qwaylandxdgsurface.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp b/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp index c89e230db66..202ac50bb67 100644 --- a/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp @@ -173,15 +173,13 @@ void QWaylandXdgSurface::sendProperty(const QString &name, const QVariant &value void QWaylandXdgSurface::xdg_surface_configure(int32_t width, int32_t height, struct wl_array *states,uint32_t serial) { - uint32_t *state = 0; + uint32_t *state = reinterpret_cast(states->data); + size_t numStates = states->size / sizeof(uint32_t); bool aboutToMaximize = false; bool aboutToFullScreen = false; - state = (uint32_t*) states->data; - - for (uint32_t i = 0; i < states->size / sizeof(state) ; i++) - { - switch (*(state+i)) { + for (size_t i = 0; i < numStates; i++) { + switch (state[i]) { case XDG_SURFACE_STATE_MAXIMIZED: aboutToMaximize = ((width > 0) && (height > 0)); break; From 64740996845c43c7363874a4c4ed876fa6680549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 2 Mar 2016 11:04:10 +0100 Subject: [PATCH 3/3] Add support for bitmap cursors So far QtWayland did not support custom bitmap/pixmap QCursors. This change adds support for them by creating a QWaylandShmBuffer and copying the pixmap data into that buffer. The internal API to set cursors images is changed to not only rely on wl_cursor_image, but also allow to just set the buffer with a specific size and a hot spot. The created WaylandShmBuffer is passed around as a shared pointer, so that it can be automatically cleaned up once the cursor image is no longer used on any seat. Task-number: QTBUG-51604 Change-Id: I1f1ee87f03186c3d564468d3e8ea2a3141d7e2fb Reviewed-by: Giulio Camuffo Reviewed-by: Johan Helsing --- .../platforms/wayland/qwaylandcursor.cpp | 29 ++++++++++++++++++- .../platforms/wayland/qwaylandcursor_p.h | 2 ++ .../platforms/wayland/qwaylanddisplay_p.h | 1 + .../platforms/wayland/qwaylandinputdevice.cpp | 28 ++++++++++++++++-- .../platforms/wayland/qwaylandinputdevice_p.h | 5 ++++ .../platforms/wayland/qwaylandwindow.cpp | 12 ++++---- .../platforms/wayland/qwaylandwindow_p.h | 4 +-- 7 files changed, 70 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index 8dfc95c3604..8d91e3896db 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -85,7 +85,8 @@ struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape) if (newShape < Qt::BitmapCursor) { waylandCursor = requestCursor((WaylandCursor)newShape); } else if (newShape == Qt::BitmapCursor) { - //TODO: Bitmap cursor logic + // cannot create a wl_cursor_image for a CursorShape + return Q_NULLPTR; } else { //TODO: Custom cursor logic (for resize arrows) } @@ -105,12 +106,28 @@ struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape) return image; } +QSharedPointer QWaylandCursor::cursorBitmapImage(const QCursor *cursor) +{ + if (cursor->shape() != Qt::BitmapCursor) + return QSharedPointer(); + + const QImage &img = cursor->pixmap().toImage(); + QSharedPointer buffer(new QWaylandShmBuffer(mDisplay, img.size(), img.format())); + memcpy(buffer->image()->bits(), img.bits(), img.byteCount()); + return buffer; +} + void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window) { Q_UNUSED(window) const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; + if (newShape == Qt::BitmapCursor) { + mDisplay->setCursor(cursorBitmapImage(cursor), cursor->hotSpot()); + return; + } + struct wl_cursor_image *image = cursorImage(newShape); if (!image) { return; @@ -130,6 +147,16 @@ void QWaylandDisplay::setCursor(struct wl_buffer *buffer, struct wl_cursor_image } } +void QWaylandDisplay::setCursor(const QSharedPointer &buffer, const QPoint &hotSpot) +{ + /* Qt doesn't tell us which input device we should set the cursor + * for, so set it for all devices. */ + for (int i = 0; i < mInputDevices.count(); i++) { + QWaylandInputDevice *inputDevice = mInputDevices.at(i); + inputDevice->setCursor(buffer, hotSpot); + } +} + QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const { return mInputDevices.isEmpty() ? 0 : mInputDevices.first(); diff --git a/src/plugins/platforms/wayland/qwaylandcursor_p.h b/src/plugins/platforms/wayland/qwaylandcursor_p.h index 0cc1173f8f9..9e06cf6265b 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor_p.h +++ b/src/plugins/platforms/wayland/qwaylandcursor_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { +class QWaylandBuffer; class QWaylandDisplay; class QWaylandScreen; @@ -72,6 +73,7 @@ public: void setPos(const QPoint &pos); struct wl_cursor_image *cursorImage(Qt::CursorShape shape); + QSharedPointer cursorBitmapImage(const QCursor *cursor); private: enum WaylandCursor { diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 8262e72be46..b53e0577a3b 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -118,6 +118,7 @@ public: QWaylandWindowManagerIntegration *windowManagerIntegration() const; void setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image); + void setCursor(const QSharedPointer &buffer, const QPoint &hotSpot); struct wl_display *wl_display() const { return mDisplay; } struct ::wl_registry *wl_registry() { return object(); } diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index e0a5ce9441a..9eda317b307 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -42,6 +42,7 @@ #include "qwaylandscreen_p.h" #include "qwaylandcursor_p.h" #include "qwaylanddisplay_p.h" +#include "qwaylandshmbackingstore_p.h" #include "../shared/qwaylandxkb.h" #include @@ -329,9 +330,26 @@ void QWaylandInputDevice::setCursor(Qt::CursorShape newShape, QWaylandScreen *sc setCursor(buffer, image); } +void QWaylandInputDevice::setCursor(const QCursor &cursor, QWaylandScreen *screen) +{ + if (cursor.shape() == Qt::BitmapCursor) { + setCursor(screen->waylandCursor()->cursorBitmapImage(&cursor), cursor.hotSpot()); + return; + } + setCursor(cursor.shape(), screen); +} + void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image) +{ + setCursor(buffer, + image ? QPoint(image->hotspot_x, image->hotspot_y) : QPoint(), + image ? QSize(image->width, image->height) : QSize()); +} + +void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, const QPoint &hotSpot, const QSize &size) { if (mCaps & WL_SEAT_CAPABILITY_POINTER) { + mPixmapCursor.clear(); mPointer->mCursorSerial = mPointer->mEnterSerial; /* Hide cursor */ if (!buffer) @@ -341,13 +359,19 @@ void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, struct wl_cursor_i } mPointer->set_cursor(mPointer->mEnterSerial, pointerSurface, - image->hotspot_x, image->hotspot_y); + hotSpot.x(), hotSpot.y()); wl_surface_attach(pointerSurface, buffer, 0, 0); - wl_surface_damage(pointerSurface, 0, 0, image->width, image->height); + wl_surface_damage(pointerSurface, 0, 0, size.width(), size.height()); wl_surface_commit(pointerSurface); } } +void QWaylandInputDevice::setCursor(const QSharedPointer &buffer, const QPoint &hotSpot) +{ + setCursor(buffer->buffer(), hotSpot, buffer->size()); + mPixmapCursor = buffer; +} + class EnterEvent : public QWaylandPointerEvent { public: diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h index 8bfb45cd403..508b67078d9 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h @@ -93,7 +93,10 @@ public: struct ::wl_seat *wl_seat() { return QtWayland::wl_seat::object(); } void setCursor(Qt::CursorShape cursor, QWaylandScreen *screen); + void setCursor(const QCursor &cursor, QWaylandScreen *screen); void setCursor(struct wl_buffer *buffer, struct ::wl_cursor_image *image); + void setCursor(struct wl_buffer *buffer, const QPoint &hotSpot, const QSize &size); + void setCursor(const QSharedPointer &buffer, const QPoint &hotSpot); void handleWindowDestroyed(QWaylandWindow *window); void setDataDevice(QWaylandDataDevice *device); @@ -137,6 +140,8 @@ private: QTouchDevice *mTouchDevice; + QSharedPointer mPixmapCursor; + friend class QWaylandTouchExtension; friend class QWaylandQtKeyExtension; }; diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index caf24c0aab9..68fea2fac88 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -73,7 +73,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mWindowDecoration(0) , mMouseEventsInContentArea(false) , mMousePressedInContentArea(Qt::NoButton) - , m_cursorShape(Qt::ArrowCursor) + , m_cursor(Qt::ArrowCursor) , mWaitingForFrameSync(false) , mFrameCallback(0) , mRequestResizeSent(false) @@ -732,17 +732,17 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe } } -void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, Qt::CursorShape shape) +void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor) { - if (m_cursorShape != shape || device->serial() > device->cursorSerial()) { - device->setCursor(shape, mScreen); - m_cursorShape = shape; + if (device->serial() >= device->cursorSerial()) { + device->setCursor(cursor, mScreen); + m_cursor = cursor; } } void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device) { - setMouseCursor(device, window()->cursor().shape()); + setMouseCursor(device, window()->cursor()); } void QWaylandWindow::requestActivateWindow() diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 701a9cdf6d0..3f35a1eba3f 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -168,7 +168,7 @@ public: inline bool isMaximized() const { return mState == Qt::WindowMaximized; } inline bool isFullscreen() const { return mState == Qt::WindowFullScreen; } - void setMouseCursor(QWaylandInputDevice *device, Qt::CursorShape shape); + void setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor); void restoreMouseCursor(QWaylandInputDevice *device); QWaylandWindow *transientParent() const; @@ -206,7 +206,7 @@ protected: QWaylandAbstractDecoration *mWindowDecoration; bool mMouseEventsInContentArea; Qt::MouseButtons mMousePressedInContentArea; - Qt::CursorShape m_cursorShape; + QCursor m_cursor; WId mWindowId; bool mWaitingForFrameSync;