File indexing completed on 2024-05-19 16:35:36

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 
0011 #include <QObject>
0012 #include <QSocketNotifier>
0013 #include <QVector>
0014 
0015 #include <xcb/xcb.h>
0016 
0017 namespace KWayland
0018 {
0019 namespace Client
0020 {
0021 class DataDevice;
0022 class DataSource;
0023 }
0024 }
0025 namespace KWaylandServer
0026 {
0027 class DataDeviceInterface;
0028 }
0029 
0030 namespace KWin
0031 {
0032 namespace Xwl
0033 {
0034 
0035 /**
0036  * Represents for an arbitrary selection a data transfer between
0037  * sender and receiver.
0038  *
0039  * Lives for the duration of the transfer and must be cleaned up
0040  * externally afterwards. For that the owner should connect to the
0041  * @c finished() signal.
0042  */
0043 class Transfer : public QObject
0044 {
0045     Q_OBJECT
0046 
0047 public:
0048     Transfer(xcb_atom_t selection,
0049              qint32 fd,
0050              xcb_timestamp_t timestamp,
0051              QObject *parent = nullptr);
0052 
0053     virtual bool handlePropertyNotify(xcb_property_notify_event_t *event) = 0;
0054     void timeout();
0055     xcb_timestamp_t timestamp() const
0056     {
0057         return m_timestamp;
0058     }
0059 
0060 Q_SIGNALS:
0061     void finished();
0062 
0063 protected:
0064     void endTransfer();
0065 
0066     xcb_atom_t atom() const
0067     {
0068         return m_atom;
0069     }
0070     qint32 fd() const
0071     {
0072         return m_fd;
0073     }
0074 
0075     void setIncr(bool set)
0076     {
0077         m_incr = set;
0078     }
0079     bool incr() const
0080     {
0081         return m_incr;
0082     }
0083     void resetTimeout()
0084     {
0085         m_timeout = false;
0086     }
0087     void createSocketNotifier(QSocketNotifier::Type type);
0088     void clearSocketNotifier();
0089     QSocketNotifier *socketNotifier() const
0090     {
0091         return m_notifier;
0092     }
0093 
0094 private:
0095     void closeFd();
0096 
0097     xcb_atom_t m_atom;
0098     qint32 m_fd;
0099     xcb_timestamp_t m_timestamp = XCB_CURRENT_TIME;
0100 
0101     QSocketNotifier *m_notifier = nullptr;
0102     bool m_incr = false;
0103     bool m_timeout = false;
0104 
0105     Q_DISABLE_COPY(Transfer)
0106 };
0107 
0108 /**
0109  * Represents a transfer from a Wayland native source to an X window.
0110  */
0111 class TransferWltoX : public Transfer
0112 {
0113     Q_OBJECT
0114 
0115 public:
0116     TransferWltoX(xcb_atom_t selection,
0117                   xcb_selection_request_event_t *request,
0118                   qint32 fd,
0119                   QObject *parent = nullptr);
0120     ~TransferWltoX() override;
0121 
0122     void startTransferFromSource();
0123     bool handlePropertyNotify(xcb_property_notify_event_t *event) override;
0124 
0125 Q_SIGNALS:
0126     void selectionNotify(xcb_selection_request_event_t *event, bool success);
0127 
0128 private:
0129     void startIncr();
0130     void readWlSource();
0131     int flushSourceData();
0132     void handlePropertyDelete();
0133 
0134     xcb_selection_request_event_t *m_request = nullptr;
0135 
0136     /* contains all received data portioned in chunks
0137      * TODO: explain second QPair component
0138      */
0139     QVector<QPair<QByteArray, int>> m_chunks;
0140 
0141     bool m_propertyIsSet = false;
0142     bool m_flushPropertyOnDelete = false;
0143 
0144     Q_DISABLE_COPY(TransferWltoX)
0145 };
0146 
0147 /**
0148  * Helper class for X to Wl transfers.
0149  */
0150 class DataReceiver
0151 {
0152 public:
0153     virtual ~DataReceiver();
0154 
0155     void transferFromProperty(xcb_get_property_reply_t *reply);
0156 
0157     void setData(const char *value, int length);
0158     QByteArray data() const;
0159 
0160     void partRead(int length);
0161 
0162 private:
0163     xcb_get_property_reply_t *m_propertyReply = nullptr;
0164     int m_propertyStart = 0;
0165     QByteArray m_data;
0166 };
0167 
0168 /**
0169  * Represents a transfer from an X window to a Wayland native client.
0170  */
0171 class TransferXtoWl : public Transfer
0172 {
0173     Q_OBJECT
0174 
0175 public:
0176     TransferXtoWl(xcb_atom_t selection,
0177                   xcb_atom_t target,
0178                   qint32 fd,
0179                   xcb_timestamp_t timestamp, xcb_window_t parentWindow,
0180                   QObject *parent = nullptr);
0181     ~TransferXtoWl() override;
0182 
0183     bool handleSelectionNotify(xcb_selection_notify_event_t *event);
0184     bool handlePropertyNotify(xcb_property_notify_event_t *event) override;
0185 
0186 private:
0187     void dataSourceWrite();
0188     void startTransfer();
0189     void getIncrChunk();
0190 
0191     xcb_window_t m_window;
0192     DataReceiver *m_receiver = nullptr;
0193 
0194     Q_DISABLE_COPY(TransferXtoWl)
0195 };
0196 
0197 } // namespace Xwl
0198 } // namespace KWin