File indexing completed on 2024-11-10 04:57:25

0001 /*
0002     SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "wayland/cursorshape_v1.h"
0008 #include "wayland/clientconnection.h"
0009 #include "wayland/display.h"
0010 #include "wayland/pointer.h"
0011 #include "wayland/surface.h"
0012 #include "wayland/tablet_v2.h"
0013 
0014 #include <QPointer>
0015 
0016 #include "qwayland-server-cursor-shape-v1.h"
0017 
0018 namespace KWin
0019 {
0020 
0021 static constexpr int s_version = 1;
0022 
0023 class CursorShapeManagerV1InterfacePrivate : public QtWaylandServer::wp_cursor_shape_manager_v1
0024 {
0025 public:
0026     CursorShapeManagerV1InterfacePrivate(Display *display);
0027 
0028 protected:
0029     void wp_cursor_shape_manager_v1_destroy(Resource *resource) override;
0030     void wp_cursor_shape_manager_v1_get_pointer(Resource *resource, uint32_t cursor_shape_device, struct ::wl_resource *pointer) override;
0031     void wp_cursor_shape_manager_v1_get_tablet_tool_v2(Resource *resource, uint32_t cursor_shape_device, struct ::wl_resource *tablet_tool) override;
0032 };
0033 
0034 class CursorShapeDeviceV1Interface : public QtWaylandServer::wp_cursor_shape_device_v1
0035 {
0036 public:
0037     CursorShapeDeviceV1Interface(PointerInterface *pointer, wl_resource *resource);
0038     CursorShapeDeviceV1Interface(TabletToolV2Interface *tabletTool, wl_resource *resource);
0039 
0040     QPointer<PointerInterface> pointer;
0041     QPointer<TabletToolV2Interface> tabletTool;
0042 
0043 protected:
0044     void wp_cursor_shape_device_v1_destroy_resource(Resource *resource) override;
0045     void wp_cursor_shape_device_v1_destroy(Resource *resource) override;
0046     void wp_cursor_shape_device_v1_set_shape(Resource *resource, uint32_t serial, uint32_t shape) override;
0047 };
0048 
0049 CursorShapeManagerV1InterfacePrivate::CursorShapeManagerV1InterfacePrivate(Display *display)
0050     : QtWaylandServer::wp_cursor_shape_manager_v1(*display, s_version)
0051 {
0052 }
0053 
0054 void CursorShapeManagerV1InterfacePrivate::wp_cursor_shape_manager_v1_destroy(Resource *resource)
0055 {
0056     wl_resource_destroy(resource->handle);
0057 }
0058 
0059 void CursorShapeManagerV1InterfacePrivate::wp_cursor_shape_manager_v1_get_pointer(Resource *resource, uint32_t cursor_shape_device, struct ::wl_resource *pointer)
0060 {
0061     wl_resource *device = wl_resource_create(resource->client(), &wp_cursor_shape_device_v1_interface, resource->version(), cursor_shape_device);
0062     if (!device) {
0063         wl_resource_post_no_memory(resource->handle);
0064         return;
0065     }
0066     new CursorShapeDeviceV1Interface(PointerInterface::get(pointer), device);
0067 }
0068 
0069 void CursorShapeManagerV1InterfacePrivate::wp_cursor_shape_manager_v1_get_tablet_tool_v2(Resource *resource, uint32_t cursor_shape_device, struct ::wl_resource *tablet_tool)
0070 {
0071     wl_resource *device = wl_resource_create(resource->client(), &wp_cursor_shape_device_v1_interface, resource->version(), cursor_shape_device);
0072     if (!device) {
0073         wl_resource_post_no_memory(resource->handle);
0074         return;
0075     }
0076     new CursorShapeDeviceV1Interface(TabletToolV2Interface::get(tablet_tool), device);
0077 }
0078 
0079 CursorShapeManagerV1Interface::CursorShapeManagerV1Interface(Display *display, QObject *parent)
0080     : QObject(parent)
0081     , d(std::make_unique<CursorShapeManagerV1InterfacePrivate>(display))
0082 {
0083 }
0084 
0085 CursorShapeManagerV1Interface::~CursorShapeManagerV1Interface()
0086 {
0087 }
0088 
0089 CursorShapeDeviceV1Interface::CursorShapeDeviceV1Interface(PointerInterface *pointer, wl_resource *resource)
0090     : QtWaylandServer::wp_cursor_shape_device_v1(resource)
0091     , pointer(pointer)
0092 {
0093 }
0094 
0095 CursorShapeDeviceV1Interface::CursorShapeDeviceV1Interface(TabletToolV2Interface *tabletTool, wl_resource *resource)
0096     : QtWaylandServer::wp_cursor_shape_device_v1(resource)
0097     , tabletTool(tabletTool)
0098 {
0099 }
0100 
0101 void CursorShapeDeviceV1Interface::wp_cursor_shape_device_v1_destroy_resource(Resource *resource)
0102 {
0103     delete this;
0104 }
0105 
0106 void CursorShapeDeviceV1Interface::wp_cursor_shape_device_v1_destroy(Resource *resource)
0107 {
0108     wl_resource_destroy(resource->handle);
0109 }
0110 
0111 static QByteArray shapeName(uint32_t shape)
0112 {
0113     switch (shape) {
0114     case QtWaylandServer::wp_cursor_shape_device_v1::shape_default:
0115         return QByteArrayLiteral("default");
0116     case QtWaylandServer::wp_cursor_shape_device_v1::shape_context_menu:
0117         return QByteArrayLiteral("context-menu");
0118     case QtWaylandServer::wp_cursor_shape_device_v1::shape_help:
0119         return QByteArrayLiteral("help");
0120     case QtWaylandServer::wp_cursor_shape_device_v1::shape_pointer:
0121         return QByteArrayLiteral("pointer");
0122     case QtWaylandServer::wp_cursor_shape_device_v1::shape_progress:
0123         return QByteArrayLiteral("progress");
0124     case QtWaylandServer::wp_cursor_shape_device_v1::shape_wait:
0125         return QByteArrayLiteral("wait");
0126     case QtWaylandServer::wp_cursor_shape_device_v1::shape_cell:
0127         return QByteArrayLiteral("cell");
0128     case QtWaylandServer::wp_cursor_shape_device_v1::shape_crosshair:
0129         return QByteArrayLiteral("crosshair");
0130     case QtWaylandServer::wp_cursor_shape_device_v1::shape_text:
0131         return QByteArrayLiteral("text");
0132     case QtWaylandServer::wp_cursor_shape_device_v1::shape_vertical_text:
0133         return QByteArrayLiteral("vertical-text");
0134     case QtWaylandServer::wp_cursor_shape_device_v1::shape_alias:
0135         return QByteArrayLiteral("alias");
0136     case QtWaylandServer::wp_cursor_shape_device_v1::shape_copy:
0137         return QByteArrayLiteral("copy");
0138     case QtWaylandServer::wp_cursor_shape_device_v1::shape_move:
0139         return QByteArrayLiteral("move");
0140     case QtWaylandServer::wp_cursor_shape_device_v1::shape_no_drop:
0141         return QByteArrayLiteral("no-drop");
0142     case QtWaylandServer::wp_cursor_shape_device_v1::shape_not_allowed:
0143         return QByteArrayLiteral("not-allowed");
0144     case QtWaylandServer::wp_cursor_shape_device_v1::shape_grab:
0145         return QByteArrayLiteral("grab");
0146     case QtWaylandServer::wp_cursor_shape_device_v1::shape_grabbing:
0147         return QByteArrayLiteral("grabbing");
0148     case QtWaylandServer::wp_cursor_shape_device_v1::shape_e_resize:
0149         return QByteArrayLiteral("e-resize");
0150     case QtWaylandServer::wp_cursor_shape_device_v1::shape_n_resize:
0151         return QByteArrayLiteral("n-resize");
0152     case QtWaylandServer::wp_cursor_shape_device_v1::shape_ne_resize:
0153         return QByteArrayLiteral("ne-resize");
0154     case QtWaylandServer::wp_cursor_shape_device_v1::shape_nw_resize:
0155         return QByteArrayLiteral("nw-resize");
0156     case QtWaylandServer::wp_cursor_shape_device_v1::shape_s_resize:
0157         return QByteArrayLiteral("s-resize");
0158     case QtWaylandServer::wp_cursor_shape_device_v1::shape_se_resize:
0159         return QByteArrayLiteral("se-resize");
0160     case QtWaylandServer::wp_cursor_shape_device_v1::shape_sw_resize:
0161         return QByteArrayLiteral("sw-resize");
0162     case QtWaylandServer::wp_cursor_shape_device_v1::shape_w_resize:
0163         return QByteArrayLiteral("w-resize");
0164     case QtWaylandServer::wp_cursor_shape_device_v1::shape_ew_resize:
0165         return QByteArrayLiteral("ew-resize");
0166     case QtWaylandServer::wp_cursor_shape_device_v1::shape_ns_resize:
0167         return QByteArrayLiteral("ns-resize");
0168     case QtWaylandServer::wp_cursor_shape_device_v1::shape_nesw_resize:
0169         return QByteArrayLiteral("nesw-resize");
0170     case QtWaylandServer::wp_cursor_shape_device_v1::shape_nwse_resize:
0171         return QByteArrayLiteral("nwse-resize");
0172     case QtWaylandServer::wp_cursor_shape_device_v1::shape_col_resize:
0173         return QByteArrayLiteral("col-resize");
0174     case QtWaylandServer::wp_cursor_shape_device_v1::shape_row_resize:
0175         return QByteArrayLiteral("row-resize");
0176     case QtWaylandServer::wp_cursor_shape_device_v1::shape_all_scroll:
0177         return QByteArrayLiteral("all-scroll");
0178     case QtWaylandServer::wp_cursor_shape_device_v1::shape_zoom_in:
0179         return QByteArrayLiteral("zoom-in");
0180     case QtWaylandServer::wp_cursor_shape_device_v1::shape_zoom_out:
0181         return QByteArrayLiteral("zoom-out");
0182     default:
0183         return QByteArrayLiteral("default");
0184     }
0185 }
0186 
0187 void CursorShapeDeviceV1Interface::wp_cursor_shape_device_v1_set_shape(Resource *resource, uint32_t serial, uint32_t shape)
0188 {
0189     if (shape < shape_default || shape > shape_zoom_out) {
0190         wl_resource_post_error(resource->handle, error_invalid_shape, "unknown cursor shape");
0191         return;
0192     }
0193     if (pointer) {
0194         if (!pointer->focusedSurface() || pointer->focusedSurface()->client()->client() != resource->client()) {
0195             return;
0196         }
0197         if (pointer->focusedSerial() == serial) {
0198             Q_EMIT pointer->cursorChanged(shapeName(shape));
0199         }
0200     } else if (tabletTool) {
0201         if (!tabletTool->currentSurface() || tabletTool->currentSurface()->client()->client() != resource->client()) {
0202             return;
0203         }
0204         if (tabletTool->proximitySerial() == serial) {
0205             Q_EMIT tabletTool->cursorChanged(shapeName(shape));
0206         }
0207     }
0208 }
0209 
0210 } // namespace KWin