File indexing completed on 2024-05-19 05:32:51

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