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: 2019 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 <QVector>
0013 
0014 #include <xcb/xcb.h>
0015 
0016 struct xcb_xfixes_selection_notify_event_t;
0017 
0018 class QTimer;
0019 
0020 namespace KWin
0021 {
0022 namespace Xwl
0023 {
0024 class TransferWltoX;
0025 class TransferXtoWl;
0026 class WlSource;
0027 class X11Source;
0028 
0029 /**
0030  * Base class representing generic X selections and their respective
0031  * Wayland counter-parts.
0032  *
0033  * The class needs to be subclassed and adjusted according to the
0034  * selection, but provides common fucntionality to be expected of all
0035  * selections.
0036  *
0037  * A selection should exist through the whole runtime of an Xwayland
0038  * session.
0039  *
0040  * Independently of each other the class holds the currently active
0041  * source instance and active transfers relative to the represented
0042  * selection.
0043  */
0044 class Selection : public QObject
0045 {
0046     Q_OBJECT
0047 
0048 public:
0049     static xcb_atom_t mimeTypeToAtom(const QString &mimeType);
0050     static xcb_atom_t mimeTypeToAtomLiteral(const QString &mimeType);
0051     static QStringList atomToMimeTypes(xcb_atom_t atom);
0052     static QString atomName(xcb_atom_t atom);
0053     static void sendSelectionNotify(xcb_selection_request_event_t *event, bool success);
0054 
0055     // on selection owner changes by X clients (Xwl -> Wl)
0056     bool handleXfixesNotify(xcb_xfixes_selection_notify_event_t *event);
0057     bool filterEvent(xcb_generic_event_t *event);
0058 
0059     xcb_atom_t atom() const
0060     {
0061         return m_atom;
0062     }
0063     xcb_window_t window() const
0064     {
0065         return m_window;
0066     }
0067     void overwriteRequestorWindow(xcb_window_t window);
0068 
0069 Q_SIGNALS:
0070     void transferFinished(xcb_timestamp_t eventTime);
0071 
0072 protected:
0073     Selection(xcb_atom_t atom, QObject *parent);
0074     void registerXfixes();
0075 
0076     virtual void doHandleXfixesNotify(xcb_xfixes_selection_notify_event_t *event) = 0;
0077     virtual void x11OffersChanged(const QStringList &added, const QStringList &removed) = 0;
0078 
0079     virtual bool handleClientMessage(xcb_client_message_event_t *event)
0080     {
0081         return false;
0082     }
0083     // sets the current provider of the selection
0084     void setWlSource(WlSource *source);
0085     WlSource *wlSource() const
0086     {
0087         return m_waylandSource;
0088     }
0089     void createX11Source(xcb_xfixes_selection_notify_event_t *event);
0090     X11Source *x11Source() const
0091     {
0092         return m_xSource;
0093     }
0094     // must be called in order to provide data from Wl to X
0095     void ownSelection(bool own);
0096     void setWindow(xcb_window_t window)
0097     {
0098         m_window = window;
0099     }
0100 
0101 private:
0102     bool handleSelectionRequest(xcb_selection_request_event_t *event);
0103     bool handleSelectionNotify(xcb_selection_notify_event_t *event);
0104     bool handlePropertyNotify(xcb_property_notify_event_t *event);
0105 
0106     void startTransferToWayland(xcb_atom_t target, qint32 fd);
0107     void startTransferToX(xcb_selection_request_event_t *event, qint32 fd);
0108 
0109     // Timeout transfers, which have become inactive due to client errors.
0110     void timeoutTransfers();
0111     void startTimeoutTransfersTimer();
0112     void endTimeoutTransfersTimer();
0113 
0114     xcb_atom_t m_atom = XCB_ATOM_NONE;
0115     xcb_window_t m_window = XCB_WINDOW_NONE;
0116     xcb_window_t m_requestorWindow = XCB_WINDOW_NONE;
0117     xcb_timestamp_t m_timestamp;
0118 
0119     // Active source, if any. Only one of them at max can exist
0120     // at the same time.
0121     WlSource *m_waylandSource = nullptr;
0122     X11Source *m_xSource = nullptr;
0123 
0124     // active transfers
0125     QVector<TransferWltoX *> m_wlToXTransfers;
0126     QVector<TransferXtoWl *> m_xToWlTransfers;
0127     QTimer *m_timeoutTransfers = nullptr;
0128 
0129     bool m_disownPending = false;
0130 
0131     Q_DISABLE_COPY(Selection)
0132 };
0133 
0134 } // namespace Xwl
0135 } // namespace KWin