File indexing completed on 2025-03-16 11:21:58
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