1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qwaylandclipboard_p.h" |
5 | #include "qwaylanddisplay_p.h" |
6 | #include "qwaylandinputdevice_p.h" |
7 | #include "qwaylanddataoffer_p.h" |
8 | #include "qwaylanddatasource_p.h" |
9 | #include "qwaylanddatadevice_p.h" |
10 | #if QT_CONFIG(wayland_client_primary_selection) |
11 | #include "qwaylandprimaryselectionv1_p.h" |
12 | #endif |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | namespace QtWaylandClient { |
17 | |
18 | QWaylandClipboard::QWaylandClipboard(QWaylandDisplay *display) |
19 | : mDisplay(display) |
20 | { |
21 | m_clientClipboard[QClipboard::Clipboard] = nullptr; |
22 | m_clientClipboard[QClipboard::Selection] = nullptr; |
23 | } |
24 | |
25 | QWaylandClipboard::~QWaylandClipboard() |
26 | { |
27 | if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) |
28 | delete m_clientClipboard[QClipboard::Clipboard]; |
29 | delete m_clientClipboard[QClipboard::Selection]; |
30 | } |
31 | |
32 | QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) |
33 | { |
34 | auto *seat = mDisplay->currentInputDevice(); |
35 | if (!seat) |
36 | return &m_emptyData; |
37 | |
38 | switch (mode) { |
39 | case QClipboard::Clipboard: |
40 | if (auto *dataDevice = seat->dataDevice()) { |
41 | if (dataDevice->selectionSource()) |
42 | return m_clientClipboard[QClipboard::Clipboard]; |
43 | if (auto *offer = dataDevice->selectionOffer()) |
44 | return offer->mimeData(); |
45 | } |
46 | return &m_emptyData; |
47 | case QClipboard::Selection: |
48 | #if QT_CONFIG(wayland_client_primary_selection) |
49 | if (auto *selectionDevice = seat->primarySelectionDevice()) { |
50 | if (selectionDevice->selectionSource()) |
51 | return m_clientClipboard[QClipboard::Selection]; |
52 | if (auto *offer = selectionDevice->selectionOffer()) |
53 | return offer->mimeData(); |
54 | } |
55 | #endif |
56 | return &m_emptyData; |
57 | default: |
58 | return &m_emptyData; |
59 | } |
60 | } |
61 | |
62 | void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) |
63 | { |
64 | auto *seat = mDisplay->currentInputDevice(); |
65 | if (!seat) { |
66 | qCWarning(lcQpaWayland) << "Can't set clipboard contents with no wl_seats available" ; |
67 | return; |
68 | } |
69 | |
70 | if (data && m_clientClipboard[mode] == data) // Already set before? |
71 | return; |
72 | |
73 | static const QString plain = QStringLiteral("text/plain" ); |
74 | static const QString utf8 = QStringLiteral("text/plain;charset=utf-8" ); |
75 | |
76 | if (data && data->hasFormat(mimetype: plain) && !data->hasFormat(mimetype: utf8)) |
77 | data->setData(mimetype: utf8, data: data->data(mimetype: plain)); |
78 | |
79 | if (m_clientClipboard[mode]) { |
80 | if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) |
81 | delete m_clientClipboard[mode]; |
82 | m_clientClipboard[mode] = nullptr; |
83 | } |
84 | |
85 | m_clientClipboard[mode] = data; |
86 | |
87 | switch (mode) { |
88 | case QClipboard::Clipboard: |
89 | if (auto *dataDevice = seat->dataDevice()) { |
90 | dataDevice->setSelectionSource(data ? new QWaylandDataSource(mDisplay->dndSelectionHandler(), |
91 | m_clientClipboard[QClipboard::Clipboard]) : nullptr); |
92 | emitChanged(mode); |
93 | } |
94 | break; |
95 | case QClipboard::Selection: |
96 | #if QT_CONFIG(wayland_client_primary_selection) |
97 | if (auto *selectionDevice = seat->primarySelectionDevice()) { |
98 | selectionDevice->setSelectionSource(data ? new QWaylandPrimarySelectionSourceV1(mDisplay->primarySelectionManager(), |
99 | m_clientClipboard[QClipboard::Selection]) : nullptr); |
100 | emitChanged(mode); |
101 | } |
102 | #endif |
103 | break; |
104 | default: |
105 | break; |
106 | } |
107 | } |
108 | |
109 | bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const |
110 | { |
111 | #if QT_CONFIG(wayland_client_primary_selection) |
112 | if (mode == QClipboard::Selection) { |
113 | auto *seat = mDisplay->currentInputDevice(); |
114 | return seat && seat->primarySelectionDevice(); |
115 | } |
116 | #endif |
117 | return mode == QClipboard::Clipboard; |
118 | } |
119 | |
120 | bool QWaylandClipboard::ownsMode(QClipboard::Mode mode) const |
121 | { |
122 | QWaylandInputDevice *seat = mDisplay->currentInputDevice(); |
123 | if (!seat) |
124 | return false; |
125 | |
126 | switch (mode) { |
127 | case QClipboard::Clipboard: |
128 | return seat->dataDevice() && seat->dataDevice()->selectionSource() != nullptr; |
129 | #if QT_CONFIG(wayland_client_primary_selection) |
130 | case QClipboard::Selection: |
131 | return seat->primarySelectionDevice() && seat->primarySelectionDevice()->selectionSource() != nullptr; |
132 | #endif |
133 | default: |
134 | return false; |
135 | } |
136 | } |
137 | |
138 | } |
139 | |
140 | QT_END_NAMESPACE |
141 | |