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