diff options
Diffstat (limited to 'src/client/qwaylandcursor.cpp')
-rw-r--r-- | src/client/qwaylandcursor.cpp | 362 |
1 files changed, 193 insertions, 169 deletions
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp index 3d2cbd76..6947e97f 100644 --- a/src/client/qwaylandcursor.cpp +++ b/src/client/qwaylandcursor.cpp @@ -53,48 +53,203 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { -QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) - : mDisplay(screen->display()) - , mCursorTheme(mDisplay->loadCursorTheme(screen->devicePixelRatio())) +QWaylandCursorTheme *QWaylandCursorTheme::create(QWaylandShm *shm, int size) { - initCursorMap(); + static QString themeName = qEnvironmentVariable("XCURSOR_THEME", QStringLiteral("default")); + return create(shm, size, themeName); } -struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape) +QWaylandCursorTheme *QWaylandCursorTheme::create(QWaylandShm *shm, int size, const QString &themeName) { - struct wl_cursor *waylandCursor = nullptr; + QByteArray nameBytes = themeName.toLocal8Bit(); + struct ::wl_cursor_theme *theme = wl_cursor_theme_load(nameBytes.constData(), size, shm->object()); - /* Hide cursor */ - if (newShape == Qt::BlankCursor) - { - mDisplay->setCursor(nullptr, nullptr, 1); + if (!theme) { + qCWarning(lcQpaWayland) << "Could not load cursor theme" << themeName << "size" << size; return nullptr; } - if (newShape < Qt::BitmapCursor) { - waylandCursor = requestCursor((WaylandCursor)newShape); - } else if (newShape == Qt::BitmapCursor) { - // cannot create a wl_cursor_image for a CursorShape + return new QWaylandCursorTheme(theme); +} + +QWaylandCursorTheme::~QWaylandCursorTheme() +{ + wl_cursor_theme_destroy(m_theme); +} + +wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape) +{ + if (struct wl_cursor *cursor = m_cursors.value(shape, nullptr)) + return cursor; + + static const QMultiMap<WaylandCursor, QByteArray>cursorNamesMap { + {ArrowCursor, "left_ptr"}, + {ArrowCursor, "default"}, + {ArrowCursor, "top_left_arrow"}, + {ArrowCursor, "left_arrow"}, + + {UpArrowCursor, "up_arrow"}, + + {CrossCursor, "cross"}, + + {WaitCursor, "wait"}, + {WaitCursor, "watch"}, + {WaitCursor, "0426c94ea35c87780ff01dc239897213"}, + + {IBeamCursor, "ibeam"}, + {IBeamCursor, "text"}, + {IBeamCursor, "xterm"}, + + {SizeVerCursor, "size_ver"}, + {SizeVerCursor, "ns-resize"}, + {SizeVerCursor, "v_double_arrow"}, + {SizeVerCursor, "00008160000006810000408080010102"}, + + {SizeHorCursor, "size_hor"}, + {SizeHorCursor, "ew-resize"}, + {SizeHorCursor, "h_double_arrow"}, + {SizeHorCursor, "028006030e0e7ebffc7f7070c0600140"}, + + {SizeBDiagCursor, "size_bdiag"}, + {SizeBDiagCursor, "nesw-resize"}, + {SizeBDiagCursor, "50585d75b494802d0151028115016902"}, + {SizeBDiagCursor, "fcf1c3c7cd4491d801f1e1c78f100000"}, + + {SizeFDiagCursor, "size_fdiag"}, + {SizeFDiagCursor, "nwse-resize"}, + {SizeFDiagCursor, "38c5dff7c7b8962045400281044508d2"}, + {SizeFDiagCursor, "c7088f0f3e6c8088236ef8e1e3e70000"}, + + {SizeAllCursor, "size_all"}, + + {SplitVCursor, "split_v"}, + {SplitVCursor, "row-resize"}, + {SplitVCursor, "sb_v_double_arrow"}, + {SplitVCursor, "2870a09082c103050810ffdffffe0204"}, + {SplitVCursor, "c07385c7190e701020ff7ffffd08103c"}, + + {SplitHCursor, "split_h"}, + {SplitHCursor, "col-resize"}, + {SplitHCursor, "sb_h_double_arrow"}, + {SplitHCursor, "043a9f68147c53184671403ffa811cc5"}, + {SplitHCursor, "14fef782d02440884392942c11205230"}, + + {PointingHandCursor, "pointing_hand"}, + {PointingHandCursor, "pointer"}, + {PointingHandCursor, "hand1"}, + {PointingHandCursor, "e29285e634086352946a0e7090d73106"}, + + {ForbiddenCursor, "forbidden"}, + {ForbiddenCursor, "not-allowed"}, + {ForbiddenCursor, "crossed_circle"}, + {ForbiddenCursor, "circle"}, + {ForbiddenCursor, "03b6e0fcb3499374a867c041f52298f0"}, + + {WhatsThisCursor, "whats_this"}, + {WhatsThisCursor, "help"}, + {WhatsThisCursor, "question_arrow"}, + {WhatsThisCursor, "5c6cd98b3f3ebcb1f9c7f1c204630408"}, + {WhatsThisCursor, "d9ce0ab605698f320427677b458ad60b"}, + + {BusyCursor, "left_ptr_watch"}, + {BusyCursor, "half-busy"}, + {BusyCursor, "progress"}, + {BusyCursor, "00000000000000020006000e7e9ffc3f"}, + {BusyCursor, "08e8e1c95fe2fc01f976f1e063a24ccd"}, + + {OpenHandCursor, "openhand"}, + {OpenHandCursor, "fleur"}, + {OpenHandCursor, "5aca4d189052212118709018842178c0"}, + {OpenHandCursor, "9d800788f1b08800ae810202380a0822"}, + + {ClosedHandCursor, "closedhand"}, + {ClosedHandCursor, "grabbing"}, + {ClosedHandCursor, "208530c400c041818281048008011002"}, + + {DragCopyCursor, "dnd-copy"}, + {DragCopyCursor, "copy"}, + + {DragMoveCursor, "dnd-move"}, + {DragMoveCursor, "move"}, + + {DragLinkCursor, "dnd-link"}, + {DragLinkCursor, "link"}, + + {ResizeNorthCursor, "n-resize"}, + {ResizeNorthCursor, "top_side"}, + + {ResizeSouthCursor, "s-resize"}, + {ResizeSouthCursor, "bottom_side"}, + + {ResizeEastCursor, "e-resize"}, + {ResizeEastCursor, "right_side"}, + + {ResizeWestCursor, "w-resize"}, + {ResizeWestCursor, "left_side"}, + + {ResizeNorthWestCursor, "nw-resize"}, + {ResizeNorthWestCursor, "top_left_corner"}, + + {ResizeSouthEastCursor, "se-resize"}, + {ResizeSouthEastCursor, "bottom_right_corner"}, + + {ResizeNorthEastCursor, "ne-resize"}, + {ResizeNorthEastCursor, "top_right_corner"}, + + {ResizeSouthWestCursor, "sw-resize"}, + {ResizeSouthWestCursor, "bottom_left_corner"}, + }; + + QList<QByteArray> cursorNames = cursorNamesMap.values(shape); + for (auto &name : qAsConst(cursorNames)) { + if (wl_cursor *cursor = wl_cursor_theme_get_cursor(m_theme, name.constData())) { + m_cursors.insert(shape, cursor); + return cursor; + } + } + + // Fallback to arrow cursor + if (shape != ArrowCursor) + return requestCursor(ArrowCursor); + + // Give up + return nullptr; +} + +struct wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape) +{ + struct wl_cursor *waylandCursor = nullptr; + + if (shape < Qt::BitmapCursor) { + waylandCursor = requestCursor(WaylandCursor(shape)); + } else if (shape == Qt::BitmapCursor) { + qCWarning(lcQpaWayland) << "cannot create a wl_cursor_image for a CursorShape"; return nullptr; } else { //TODO: Custom cursor logic (for resize arrows) } if (!waylandCursor) { - qDebug("Could not find cursor for shape %d", newShape); + qCWarning(lcQpaWayland) << "Could not find cursor for shape" << shape; return nullptr; } struct wl_cursor_image *image = waylandCursor->images[0]; struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); if (!buffer) { - qDebug("Could not find buffer for cursor"); + qCWarning(lcQpaWayland) << "Could not find buffer for cursor"; return nullptr; } return image; } +QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) + : mDisplay(screen->display()) + , mCursorTheme(mDisplay->loadCursorTheme(screen->devicePixelRatio())) +{ +} + QSharedPointer<QWaylandBuffer> QWaylandCursor::cursorBitmapImage(const QCursor *cursor) { if (cursor->shape() != Qt::BitmapCursor) @@ -106,22 +261,39 @@ QSharedPointer<QWaylandBuffer> QWaylandCursor::cursorBitmapImage(const QCursor * return buffer; } +struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape shape) +{ + if (!mCursorTheme) + return nullptr; + return mCursorTheme->cursorImage(shape); +} + void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window) { const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; + if (newShape == Qt::BlankCursor) { + mDisplay->setCursor(nullptr, nullptr, 1); + return; + } + if (newShape == Qt::BitmapCursor) { mDisplay->setCursor(cursorBitmapImage(cursor), cursor->hotSpot(), window->screen()->devicePixelRatio()); return; } - struct wl_cursor_image *image = cursorImage(newShape); - if (!image) { + if (!mCursorTheme) { + qCWarning(lcQpaWayland) << "Can't set cursor from shape with no cursor theme"; return; } - struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); - mDisplay->setCursor(buffer, image, window->screen()->devicePixelRatio()); + if (struct ::wl_cursor_image *image = mCursorTheme->cursorImage(newShape)) { + struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); + mDisplay->setCursor(buffer, image, window->screen()->devicePixelRatio()); + return; + } + + qCWarning(lcQpaWayland) << "Unable to change to cursor" << cursor; } void QWaylandCursor::pointerEvent(const QMouseEvent &event) @@ -137,155 +309,7 @@ QPoint QWaylandCursor::pos() const void QWaylandCursor::setPos(const QPoint &pos) { Q_UNUSED(pos); - qWarning() << "QWaylandCursor::setPos: not implemented"; -} - -wl_cursor *QWaylandCursor::requestCursor(WaylandCursor shape) -{ - struct wl_cursor *cursor = mCursors.value(shape, 0); - - //If the cursor has not been loaded already, load it - if (!cursor) { - if (!mCursorTheme) - return nullptr; - - QList<QByteArray> cursorNames = mCursorNamesMap.values(shape); - foreach (const QByteArray &name, cursorNames) { - cursor = wl_cursor_theme_get_cursor(mCursorTheme, name.constData()); - if (cursor) { - mCursors.insert(shape, cursor); - break; - } - } - } - - //If there still no cursor for a shape, use the default cursor - if (!cursor && shape != ArrowCursor) { - cursor = requestCursor(ArrowCursor); - } - - return cursor; -} - - -void QWaylandCursor::initCursorMap() -{ - //Fill the cursor name map will the table of xcursor names - mCursorNamesMap.insert(ArrowCursor, "left_ptr"); - mCursorNamesMap.insert(ArrowCursor, "default"); - mCursorNamesMap.insert(ArrowCursor, "top_left_arrow"); - mCursorNamesMap.insert(ArrowCursor, "left_arrow"); - - mCursorNamesMap.insert(UpArrowCursor, "up_arrow"); - - mCursorNamesMap.insert(CrossCursor, "cross"); - - mCursorNamesMap.insert(WaitCursor, "wait"); - mCursorNamesMap.insert(WaitCursor, "watch"); - mCursorNamesMap.insert(WaitCursor, "0426c94ea35c87780ff01dc239897213"); - - mCursorNamesMap.insert(IBeamCursor, "ibeam"); - mCursorNamesMap.insert(IBeamCursor, "text"); - mCursorNamesMap.insert(IBeamCursor, "xterm"); - - mCursorNamesMap.insert(SizeVerCursor, "size_ver"); - mCursorNamesMap.insert(SizeVerCursor, "ns-resize"); - mCursorNamesMap.insert(SizeVerCursor, "v_double_arrow"); - mCursorNamesMap.insert(SizeVerCursor, "00008160000006810000408080010102"); - - mCursorNamesMap.insert(SizeHorCursor, "size_hor"); - mCursorNamesMap.insert(SizeHorCursor, "ew-resize"); - mCursorNamesMap.insert(SizeHorCursor, "h_double_arrow"); - mCursorNamesMap.insert(SizeHorCursor, "028006030e0e7ebffc7f7070c0600140"); - - mCursorNamesMap.insert(SizeBDiagCursor, "size_bdiag"); - mCursorNamesMap.insert(SizeBDiagCursor, "nesw-resize"); - mCursorNamesMap.insert(SizeBDiagCursor, "50585d75b494802d0151028115016902"); - mCursorNamesMap.insert(SizeBDiagCursor, "fcf1c3c7cd4491d801f1e1c78f100000"); - - mCursorNamesMap.insert(SizeFDiagCursor, "size_fdiag"); - mCursorNamesMap.insert(SizeFDiagCursor, "nwse-resize"); - mCursorNamesMap.insert(SizeFDiagCursor, "38c5dff7c7b8962045400281044508d2"); - mCursorNamesMap.insert(SizeFDiagCursor, "c7088f0f3e6c8088236ef8e1e3e70000"); - - mCursorNamesMap.insert(SizeAllCursor, "size_all"); - - mCursorNamesMap.insert(SplitVCursor, "split_v"); - mCursorNamesMap.insert(SplitVCursor, "row-resize"); - mCursorNamesMap.insert(SplitVCursor, "sb_v_double_arrow"); - mCursorNamesMap.insert(SplitVCursor, "2870a09082c103050810ffdffffe0204"); - mCursorNamesMap.insert(SplitVCursor, "c07385c7190e701020ff7ffffd08103c"); - - mCursorNamesMap.insert(SplitHCursor, "split_h"); - mCursorNamesMap.insert(SplitHCursor, "col-resize"); - mCursorNamesMap.insert(SplitHCursor, "sb_h_double_arrow"); - mCursorNamesMap.insert(SplitHCursor, "043a9f68147c53184671403ffa811cc5"); - mCursorNamesMap.insert(SplitHCursor, "14fef782d02440884392942c11205230"); - - mCursorNamesMap.insert(PointingHandCursor, "pointing_hand"); - mCursorNamesMap.insert(PointingHandCursor, "pointer"); - mCursorNamesMap.insert(PointingHandCursor, "hand1"); - mCursorNamesMap.insert(PointingHandCursor, "e29285e634086352946a0e7090d73106"); - - mCursorNamesMap.insert(ForbiddenCursor, "forbidden"); - mCursorNamesMap.insert(ForbiddenCursor, "not-allowed"); - mCursorNamesMap.insert(ForbiddenCursor, "crossed_circle"); - mCursorNamesMap.insert(ForbiddenCursor, "circle"); - mCursorNamesMap.insert(ForbiddenCursor, "03b6e0fcb3499374a867c041f52298f0"); - - mCursorNamesMap.insert(WhatsThisCursor, "whats_this"); - mCursorNamesMap.insert(WhatsThisCursor, "help"); - mCursorNamesMap.insert(WhatsThisCursor, "question_arrow"); - mCursorNamesMap.insert(WhatsThisCursor, "5c6cd98b3f3ebcb1f9c7f1c204630408"); - mCursorNamesMap.insert(WhatsThisCursor, "d9ce0ab605698f320427677b458ad60b"); - - mCursorNamesMap.insert(BusyCursor, "left_ptr_watch"); - mCursorNamesMap.insert(BusyCursor, "half-busy"); - mCursorNamesMap.insert(BusyCursor, "progress"); - mCursorNamesMap.insert(BusyCursor, "00000000000000020006000e7e9ffc3f"); - mCursorNamesMap.insert(BusyCursor, "08e8e1c95fe2fc01f976f1e063a24ccd"); - - mCursorNamesMap.insert(OpenHandCursor, "openhand"); - mCursorNamesMap.insert(OpenHandCursor, "fleur"); - mCursorNamesMap.insert(OpenHandCursor, "5aca4d189052212118709018842178c0"); - mCursorNamesMap.insert(OpenHandCursor, "9d800788f1b08800ae810202380a0822"); - - mCursorNamesMap.insert(ClosedHandCursor, "closedhand"); - mCursorNamesMap.insert(ClosedHandCursor, "grabbing"); - mCursorNamesMap.insert(ClosedHandCursor, "208530c400c041818281048008011002"); - - mCursorNamesMap.insert(DragCopyCursor, "dnd-copy"); - mCursorNamesMap.insert(DragCopyCursor, "copy"); - - mCursorNamesMap.insert(DragMoveCursor, "dnd-move"); - mCursorNamesMap.insert(DragMoveCursor, "move"); - - mCursorNamesMap.insert(DragLinkCursor, "dnd-link"); - mCursorNamesMap.insert(DragLinkCursor, "link"); - - mCursorNamesMap.insert(ResizeNorthCursor, "n-resize"); - mCursorNamesMap.insert(ResizeNorthCursor, "top_side"); - - mCursorNamesMap.insert(ResizeSouthCursor, "s-resize"); - mCursorNamesMap.insert(ResizeSouthCursor, "bottom_side"); - - mCursorNamesMap.insert(ResizeEastCursor, "e-resize"); - mCursorNamesMap.insert(ResizeEastCursor, "right_side"); - - mCursorNamesMap.insert(ResizeWestCursor, "w-resize"); - mCursorNamesMap.insert(ResizeWestCursor, "left_side"); - - mCursorNamesMap.insert(ResizeNorthWestCursor, "nw-resize"); - mCursorNamesMap.insert(ResizeNorthWestCursor, "top_left_corner"); - - mCursorNamesMap.insert(ResizeSouthEastCursor, "se-resize"); - mCursorNamesMap.insert(ResizeSouthEastCursor, "bottom_right_corner"); - - mCursorNamesMap.insert(ResizeNorthEastCursor, "ne-resize"); - mCursorNamesMap.insert(ResizeNorthEastCursor, "top_right_corner"); - - mCursorNamesMap.insert(ResizeSouthWestCursor, "sw-resize"); - mCursorNamesMap.insert(ResizeSouthWestCursor, "bottom_left_corner"); + qCWarning(lcQpaWayland) << "Setting cursor position is not possible on wayland"; } } |