1 /* 2 KWin - the KDE window manager 3 This file is part of the KDE project. 4 5 SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com> 6 7 SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 #ifndef KWIN_XWL_TRANSFER 10 #define KWIN_XWL_TRANSFER 11 12 #include <QObject> 13 #include <QSocketNotifier> 14 #include <QVector> 15 16 #include <xcb/xcb.h> 17 18 namespace KWayland 19 { 20 namespace Client 21 { 22 class DataDevice; 23 class DataSource; 24 } 25 } 26 namespace KWaylandServer 27 { 28 class DataDeviceInterface; 29 } 30 31 namespace KWin 32 { 33 namespace Xwl 34 { 35 36 /** 37 * Represents for an arbitrary selection a data transfer between 38 * sender and receiver. 39 * 40 * Lives for the duration of the transfer and must be cleaned up 41 * externally afterwards. For that the owner should connect to the 42 * @c finished() signal. 43 */ 44 class Transfer : public QObject 45 { 46 Q_OBJECT 47 48 public: 49 Transfer(xcb_atom_t selection, 50 qint32 fd, 51 xcb_timestamp_t timestamp, 52 QObject *parent = nullptr); 53 54 virtual bool handlePropertyNotify(xcb_property_notify_event_t *event) = 0; 55 void timeout(); timestamp()56 xcb_timestamp_t timestamp() const { 57 return m_timestamp; 58 } 59 60 Q_SIGNALS: 61 void finished(); 62 63 protected: 64 void endTransfer(); 65 atom()66 xcb_atom_t atom() const { 67 return m_atom; 68 } fd()69 qint32 fd() const { 70 return m_fd; 71 } 72 setIncr(bool set)73 void setIncr(bool set) { 74 m_incr = set; 75 } incr()76 bool incr() const { 77 return m_incr; 78 } resetTimeout()79 void resetTimeout() { 80 m_timeout = false; 81 } 82 void createSocketNotifier(QSocketNotifier::Type type); 83 void clearSocketNotifier(); socketNotifier()84 QSocketNotifier *socketNotifier() const { 85 return m_notifier; 86 } 87 private: 88 void closeFd(); 89 90 xcb_atom_t m_atom; 91 qint32 m_fd; 92 xcb_timestamp_t m_timestamp = XCB_CURRENT_TIME; 93 94 QSocketNotifier *m_notifier = nullptr; 95 bool m_incr = false; 96 bool m_timeout = false; 97 98 Q_DISABLE_COPY(Transfer) 99 }; 100 101 /** 102 * Represents a transfer from a Wayland native source to an X window. 103 */ 104 class TransferWltoX : public Transfer 105 { 106 Q_OBJECT 107 108 public: 109 TransferWltoX(xcb_atom_t selection, 110 xcb_selection_request_event_t *request, 111 qint32 fd, 112 QObject *parent = nullptr); 113 ~TransferWltoX() override; 114 115 void startTransferFromSource(); 116 bool handlePropertyNotify(xcb_property_notify_event_t *event) override; 117 118 Q_SIGNALS: 119 void selectionNotify(xcb_selection_request_event_t *event, bool success); 120 121 private: 122 void startIncr(); 123 void readWlSource(); 124 int flushSourceData(); 125 void handlePropertyDelete(); 126 127 xcb_selection_request_event_t *m_request = nullptr; 128 129 /* contains all received data portioned in chunks 130 * TODO: explain second QPair component 131 */ 132 QVector<QPair<QByteArray, int> > m_chunks; 133 134 bool m_propertyIsSet = false; 135 bool m_flushPropertyOnDelete = false; 136 137 Q_DISABLE_COPY(TransferWltoX) 138 }; 139 140 /** 141 * Helper class for X to Wl transfers. 142 */ 143 class DataReceiver 144 { 145 public: 146 virtual ~DataReceiver(); 147 148 void transferFromProperty(xcb_get_property_reply_t *reply); 149 150 151 virtual void setData(const char *value, int length); 152 QByteArray data() const; 153 154 void partRead(int length); 155 156 protected: setDataInternal(QByteArray data)157 void setDataInternal(QByteArray data) { 158 m_data = data; 159 } 160 161 private: 162 xcb_get_property_reply_t *m_propertyReply = nullptr; 163 int m_propertyStart = 0; 164 QByteArray m_data; 165 }; 166 167 /** 168 * Compatibility receiver for clients only 169 * supporting the NETSCAPE_URL scheme (Firefox) 170 */ 171 class NetscapeUrlReceiver : public DataReceiver 172 { 173 public: 174 void setData(const char *value, int length) override; 175 }; 176 177 /** 178 * Compatibility receiver for clients only 179 * supporting the text/x-moz-url scheme (Chromium on own drags) 180 */ 181 class MozUrlReceiver : public DataReceiver 182 { 183 public: 184 void setData(const char *value, int length) override; 185 }; 186 187 /** 188 * Represents a transfer from an X window to a Wayland native client. 189 */ 190 class TransferXtoWl : public Transfer 191 { 192 Q_OBJECT 193 194 public: 195 TransferXtoWl(xcb_atom_t selection, 196 xcb_atom_t target, 197 qint32 fd, 198 xcb_timestamp_t timestamp, xcb_window_t parentWindow, 199 QObject *parent = nullptr); 200 ~TransferXtoWl() override; 201 202 bool handleSelectionNotify(xcb_selection_notify_event_t *event); 203 bool handlePropertyNotify(xcb_property_notify_event_t *event) override; 204 205 private: 206 void dataSourceWrite(); 207 void startTransfer(); 208 void getIncrChunk(); 209 210 xcb_window_t m_window; 211 DataReceiver *m_receiver = nullptr; 212 213 Q_DISABLE_COPY(TransferXtoWl) 214 }; 215 216 } // namespace Xwl 217 } // namespace KWin 218 219 #endif 220