Changeset View
Changeset View
Standalone View
Standalone View
libtaskmanager/virtualdesktopinfo.cpp
Show All 14 Lines | |||||
15 | Lesser General Public License for more details. | 15 | Lesser General Public License for more details. | ||
16 | 16 | | |||
17 | You should have received a copy of the GNU Lesser General Public | 17 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | 18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | 20 | | |||
21 | #include "virtualdesktopinfo.h" | 21 | #include "virtualdesktopinfo.h" | ||
22 | 22 | | |||
23 | #include <KWayland/Client/connection_thread.h> | ||||
24 | #include <KWayland/Client/plasmavirtualdesktop.h> | ||||
25 | #include <KWayland/Client/registry.h> | ||||
23 | #include <KWindowSystem> | 26 | #include <KWindowSystem> | ||
24 | 27 | | |||
25 | #include <QDBusConnection> | 28 | #include <QDBusConnection> | ||
26 | 29 | | |||
27 | #include <config-X11.h> | 30 | #include <config-X11.h> | ||
28 | 31 | | |||
29 | #if HAVE_X11 | 32 | #if HAVE_X11 | ||
30 | #include <netwm.h> | 33 | #include <netwm.h> | ||
31 | #include <QX11Info> | 34 | #include <QX11Info> | ||
32 | #endif | 35 | #endif | ||
33 | 36 | | |||
34 | namespace TaskManager | 37 | namespace TaskManager | ||
35 | { | 38 | { | ||
39 | class Q_DECL_HIDDEN VirtualDesktopInfo::Private : public QObject | ||||
40 | { | ||||
41 | Q_OBJECT | ||||
36 | 42 | | |||
37 | VirtualDesktopInfo::VirtualDesktopInfo(QObject *parent) : QObject(parent) | 43 | public: | ||
44 | Private(VirtualDesktopInfo *q); | ||||
45 | virtual ~Private() {} | ||||
46 | | ||||
47 | uint refCount = 1; | ||||
48 | | ||||
49 | virtual void init() = 0; | ||||
50 | virtual QVariant currentDesktop() const = 0; | ||||
51 | virtual int numberOfDesktops() const = 0; | ||||
52 | virtual QVariantList desktopIds() const = 0; | ||||
53 | virtual QStringList desktopNames() const = 0; | ||||
54 | virtual quint32 position(const QVariant &desktop) const = 0; | ||||
55 | virtual int desktopLayoutRows() const = 0; | ||||
56 | virtual void requestActivate(const QVariant &desktop) = 0; | ||||
57 | virtual bool canManageDesktops() const = 0; | ||||
58 | | ||||
59 | Q_SIGNALS: | ||||
60 | void currentDesktopChanged() const; | ||||
61 | void numberOfDesktopsChanged() const; | ||||
62 | void desktopIdsChanged() const; | ||||
63 | void desktopNamesChanged() const; | ||||
64 | void desktopLayoutRowsChanged() const; | ||||
65 | | ||||
66 | protected: | ||||
67 | VirtualDesktopInfo *q; | ||||
68 | }; | ||||
69 | | ||||
70 | VirtualDesktopInfo::Private::Private(VirtualDesktopInfo *q) | ||||
71 | : q(q) | ||||
72 | { | ||||
73 | } | ||||
74 | | ||||
75 | #if HAVE_X11 | ||||
76 | class Q_DECL_HIDDEN VirtualDesktopInfo::XWindowPrivate : public VirtualDesktopInfo::Private | ||||
77 | { | ||||
78 | public: | ||||
79 | XWindowPrivate(VirtualDesktopInfo *q); | ||||
80 | | ||||
81 | void init() override; | ||||
82 | QVariant currentDesktop() const override; | ||||
83 | int numberOfDesktops() const override; | ||||
84 | QVariantList desktopIds() const override; | ||||
85 | QStringList desktopNames() const override; | ||||
86 | quint32 position(const QVariant &desktop) const override; | ||||
87 | int desktopLayoutRows() const override; | ||||
88 | void requestActivate(const QVariant &desktop) override; | ||||
89 | bool canManageDesktops() const override; | ||||
90 | }; | ||||
91 | | ||||
92 | VirtualDesktopInfo::XWindowPrivate::XWindowPrivate(VirtualDesktopInfo *q) | ||||
93 | : VirtualDesktopInfo::Private(q) | ||||
94 | { | ||||
95 | init(); | ||||
96 | } | ||||
97 | | ||||
98 | void VirtualDesktopInfo::XWindowPrivate::init() | ||||
38 | { | 99 | { | ||
39 | connect(KWindowSystem::self(), &KWindowSystem::currentDesktopChanged, | 100 | connect(KWindowSystem::self(), &KWindowSystem::currentDesktopChanged, | ||
40 | this, &VirtualDesktopInfo::currentDesktopChanged); | 101 | this, &VirtualDesktopInfo::XWindowPrivate::currentDesktopChanged); | ||
41 | 102 | | |||
42 | connect(KWindowSystem::self(), &KWindowSystem::numberOfDesktopsChanged, | 103 | connect(KWindowSystem::self(), &KWindowSystem::numberOfDesktopsChanged, | ||
43 | this, &VirtualDesktopInfo::numberOfDesktopsChanged); | 104 | this, &VirtualDesktopInfo::XWindowPrivate::numberOfDesktopsChanged); | ||
44 | 105 | | |||
45 | connect(KWindowSystem::self(), &KWindowSystem::desktopNamesChanged, | 106 | connect(KWindowSystem::self(), &KWindowSystem::desktopNamesChanged, | ||
46 | this, &VirtualDesktopInfo::desktopNamesChanged); | 107 | this, &VirtualDesktopInfo::XWindowPrivate::desktopNamesChanged); | ||
47 | 108 | | |||
48 | #if HAVE_X11 | | |||
49 | if (KWindowSystem::isPlatformX11()) { | | |||
50 | QDBusConnection dbus = QDBusConnection::sessionBus(); | 109 | QDBusConnection dbus = QDBusConnection::sessionBus(); | ||
51 | dbus.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"), | 110 | dbus.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"), | ||
52 | this, SIGNAL(desktopLayoutRowsChanged())); | 111 | this, SIGNAL(desktopLayoutRowsChanged())); | ||
53 | } | 112 | } | ||
54 | #endif | | |||
55 | } | | |||
56 | 113 | | |||
57 | VirtualDesktopInfo::~VirtualDesktopInfo() | 114 | QVariant VirtualDesktopInfo::XWindowPrivate::currentDesktop() const | ||
58 | { | 115 | { | ||
116 | return KWindowSystem::currentDesktop(); | ||||
59 | } | 117 | } | ||
60 | 118 | | |||
61 | int VirtualDesktopInfo::currentDesktop() const | 119 | int VirtualDesktopInfo::XWindowPrivate::numberOfDesktops() const | ||
62 | { | 120 | { | ||
63 | return KWindowSystem::currentDesktop(); | 121 | return KWindowSystem::numberOfDesktops(); | ||
64 | } | 122 | } | ||
65 | 123 | | |||
66 | int VirtualDesktopInfo::numberOfDesktops() const | 124 | QVariantList VirtualDesktopInfo::XWindowPrivate::desktopIds() const | ||
67 | { | 125 | { | ||
68 | return KWindowSystem::numberOfDesktops(); | 126 | QVariantList ids; | ||
zzag: ids.reserve(KWindowSystem::numberOfDesktops()); | |||||
127 | | ||||
128 | for (int i = 1; i <= KWindowSystem::numberOfDesktops(); ++i) { | ||||
129 | ids << i; | ||||
69 | } | 130 | } | ||
70 | 131 | | |||
71 | QStringList VirtualDesktopInfo::desktopNames() const | 132 | return ids; | ||
133 | } | ||||
134 | | ||||
135 | QStringList VirtualDesktopInfo::XWindowPrivate::desktopNames() const | ||||
72 | { | 136 | { | ||
73 | QStringList names; | 137 | QStringList names; | ||
74 | 138 | | |||
75 | // Virtual desktop numbers start at 1. | 139 | // Virtual desktop numbers start at 1. | ||
76 | for (int i = 1; i <= KWindowSystem::numberOfDesktops(); ++i) { | 140 | for (int i = 1; i <= KWindowSystem::numberOfDesktops(); ++i) { | ||
77 | names << KWindowSystem::desktopName(i); | 141 | names << KWindowSystem::desktopName(i); | ||
78 | } | 142 | } | ||
79 | 143 | | |||
80 | return names; | 144 | return names; | ||
81 | } | 145 | } | ||
82 | 146 | | |||
83 | int VirtualDesktopInfo::desktopLayoutRows() const | 147 | quint32 VirtualDesktopInfo::XWindowPrivate::position(const QVariant &desktop) const | ||
148 | { | ||||
149 | bool ok = false; | ||||
150 | | ||||
151 | const quint32 desktopNumber = desktop.toUInt(&ok); | ||||
152 | | ||||
153 | if (!ok) { | ||||
154 | return -1; | ||||
155 | } | ||||
156 | | ||||
157 | return desktopNumber; | ||||
158 | } | ||||
159 | | ||||
160 | int VirtualDesktopInfo::XWindowPrivate::desktopLayoutRows() const | ||||
84 | { | 161 | { | ||
85 | #if HAVE_X11 | | |||
86 | if (KWindowSystem::isPlatformX11()) { | | |||
87 | const NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops | NET::DesktopNames, NET::WM2DesktopLayout); | 162 | const NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops | NET::DesktopNames, NET::WM2DesktopLayout); | ||
88 | return info.desktopLayoutColumnsRows().height(); | 163 | return info.desktopLayoutColumnsRows().height(); | ||
89 | } | 164 | } | ||
165 | | ||||
166 | void VirtualDesktopInfo::XWindowPrivate::requestActivate(const QVariant &desktop) | ||||
167 | { | ||||
168 | bool ok = false; | ||||
169 | const int desktopNumber = desktop.toInt(&ok); | ||||
170 | | ||||
171 | // Virtual desktop numbers start at 1. | ||||
172 | if (ok && desktopNumber > 0 && desktopNumber <= KWindowSystem::numberOfDesktops()) { | ||||
173 | KWindowSystem::setCurrentDesktop(desktopNumber); | ||||
174 | } | ||||
175 | } | ||||
176 | | ||||
177 | bool VirtualDesktopInfo::XWindowPrivate::canManageDesktops() const | ||||
178 | { | ||||
179 | return true; | ||||
180 | } | ||||
90 | #endif | 181 | #endif | ||
91 | 182 | | |||
183 | class Q_DECL_HIDDEN VirtualDesktopInfo::WaylandPrivate : public VirtualDesktopInfo::Private | ||||
184 | { | ||||
185 | public: | ||||
186 | WaylandPrivate(VirtualDesktopInfo *q); | ||||
187 | | ||||
188 | QVariant currentVirtualDesktop; | ||||
189 | QStringList virtualDesktops; | ||||
190 | KWayland::Client::PlasmaVirtualDesktopManagement *virtualDesktopManagement = nullptr; | ||||
191 | | ||||
192 | void init() override; | ||||
193 | QVariant currentDesktop() const override; | ||||
194 | int numberOfDesktops() const override; | ||||
195 | QVariantList desktopIds() const override; | ||||
196 | QStringList desktopNames() const override; | ||||
197 | quint32 position(const QVariant &desktop) const override; | ||||
198 | int desktopLayoutRows() const override; | ||||
199 | void requestActivate(const QVariant &desktop) override; | ||||
200 | bool canManageDesktops() const override; | ||||
201 | }; | ||||
202 | | ||||
203 | VirtualDesktopInfo::WaylandPrivate::WaylandPrivate(VirtualDesktopInfo *q) | ||||
204 | : VirtualDesktopInfo::Private(q) | ||||
205 | { | ||||
206 | init(); | ||||
207 | } | ||||
208 | | ||||
209 | void VirtualDesktopInfo::WaylandPrivate::init() | ||||
210 | { | ||||
211 | if (!KWindowSystem::isPlatformWayland()) { | ||||
212 | return; | ||||
213 | } | ||||
214 | | ||||
215 | KWayland::Client::ConnectionThread *connection = KWayland::Client::ConnectionThread::fromApplication(q); | ||||
216 | | ||||
217 | if (!connection) { | ||||
218 | return; | ||||
219 | } | ||||
220 | | ||||
221 | KWayland::Client::Registry *registry = new KWayland::Client::Registry(q); | ||||
222 | registry->create(connection); | ||||
223 | | ||||
224 | QObject::connect(registry, &KWayland::Client::Registry::plasmaVirtualDesktopManagementAnnounced, | ||||
225 | [this, registry] (quint32 name, quint32 version) { | ||||
226 | virtualDesktopManagement = registry->createPlasmaVirtualDesktopManagement(name, version, q); | ||||
227 | | ||||
228 | /* FIXME: PlasmaVirtualDesktopManagement doesn't have this ...? | ||||
229 | QObject::connect(virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::interfaceAboutToBeReleased, q, | ||||
230 | [this] { | ||||
231 | virtualDesktops.clear(); | ||||
232 | emit numberOfDesktopsChanged(); | ||||
233 | emit currentDesktopChanged(); | ||||
234 | emit desktopIdsChanged(); | ||||
235 | emit desktopNamesChanged(); | ||||
236 | emit desktopLayoutRowsChanged(); | ||||
237 | } | ||||
238 | ); | ||||
239 | */ | ||||
240 | | ||||
241 | QObject::connect(virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopAdded, q, | ||||
242 | [this](const QString &id, quint32 position) { | ||||
243 | virtualDesktops.insert(position, id); | ||||
244 | | ||||
245 | emit numberOfDesktopsChanged(); | ||||
246 | emit desktopIdsChanged(); | ||||
247 | emit desktopNamesChanged(); | ||||
248 | | ||||
249 | const KWayland::Client::PlasmaVirtualDesktop *desktop = virtualDesktopManagement->getVirtualDesktop(id); | ||||
250 | | ||||
251 | QObject::connect(desktop, &KWayland::Client::PlasmaVirtualDesktop::activated, q, | ||||
252 | [desktop, this]() { | ||||
253 | currentVirtualDesktop = desktop->id(); | ||||
254 | emit currentDesktopChanged(); | ||||
255 | } | ||||
256 | ); | ||||
257 | | ||||
258 | if (desktop->active()) { | ||||
259 | currentVirtualDesktop = id; | ||||
260 | emit currentDesktopChanged(); | ||||
261 | } | ||||
262 | } | ||||
263 | ); | ||||
264 | | ||||
265 | QObject::connect(virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopRemoved, q, | ||||
266 | [this](const QString &id) { | ||||
267 | virtualDesktops.removeOne(id); | ||||
268 | | ||||
269 | emit numberOfDesktopsChanged(); | ||||
270 | emit desktopIdsChanged(); | ||||
271 | emit desktopNamesChanged(); | ||||
272 | | ||||
273 | if (currentVirtualDesktop == id) { | ||||
274 | currentVirtualDesktop.clear(); | ||||
275 | emit currentDesktopChanged(); | ||||
276 | } | ||||
277 | } | ||||
278 | ); | ||||
279 | } | ||||
280 | ); | ||||
281 | | ||||
282 | registry->setup(); | ||||
283 | } | ||||
284 | | ||||
285 | QVariant VirtualDesktopInfo::WaylandPrivate::currentDesktop() const | ||||
286 | { | ||||
287 | return currentVirtualDesktop; | ||||
288 | } | ||||
289 | | ||||
290 | int VirtualDesktopInfo::WaylandPrivate::numberOfDesktops() const | ||||
291 | { | ||||
292 | return virtualDesktops.count(); | ||||
293 | } | ||||
294 | | ||||
295 | quint32 VirtualDesktopInfo::WaylandPrivate::position(const QVariant &desktop) const | ||||
296 | { | ||||
297 | return virtualDesktops.indexOf(desktop.toString()); | ||||
298 | } | ||||
299 | | ||||
300 | QVariantList VirtualDesktopInfo::WaylandPrivate::desktopIds() const | ||||
301 | { | ||||
302 | QVariantList ids; | ||||
303 | | ||||
304 | foreach (const QString &id, virtualDesktops) { | ||||
zzag: Call reserve method. Also, why not range based for loop? | |||||
305 | ids << id; | ||||
306 | } | ||||
307 | | ||||
308 | return ids; | ||||
309 | } | ||||
310 | | ||||
311 | QStringList VirtualDesktopInfo::WaylandPrivate::desktopNames() const | ||||
312 | { | ||||
313 | QStringList names; | ||||
314 | | ||||
315 | foreach(const QString &id, virtualDesktops) { | ||||
316 | const KWayland::Client::PlasmaVirtualDesktop *desktop = virtualDesktopManagement->getVirtualDesktop(id); | ||||
317 | | ||||
318 | if (desktop) { | ||||
319 | names << desktop->name(); | ||||
320 | } | ||||
321 | } | ||||
322 | | ||||
323 | return names; | ||||
324 | } | ||||
325 | | ||||
326 | int VirtualDesktopInfo::WaylandPrivate::desktopLayoutRows() const | ||||
327 | { | ||||
328 | // TODO FIXME: We don't have virtual desktop layout information in the Wayland | ||||
329 | // protocol yet. | ||||
92 | return 0; | 330 | return 0; | ||
93 | } | 331 | } | ||
94 | 332 | | |||
333 | void VirtualDesktopInfo::WaylandPrivate::requestActivate(const QVariant &desktop) | ||||
334 | { | ||||
335 | KWayland::Client::PlasmaVirtualDesktop *desktopObj = virtualDesktopManagement->getVirtualDesktop(desktop.toString()); | ||||
336 | | ||||
337 | if (desktopObj) { | ||||
338 | desktopObj->requestActivate(); | ||||
339 | } | ||||
340 | } | ||||
341 | | ||||
342 | bool VirtualDesktopInfo::WaylandPrivate::canManageDesktops() const | ||||
343 | { | ||||
344 | return false; | ||||
345 | } | ||||
346 | | ||||
347 | VirtualDesktopInfo::Private* VirtualDesktopInfo::d = nullptr; | ||||
348 | | ||||
349 | VirtualDesktopInfo::VirtualDesktopInfo(QObject *parent) : QObject(parent) | ||||
350 | { | ||||
351 | if (!d) { | ||||
352 | #if HAVE_X11 | ||||
353 | if (KWindowSystem::isPlatformX11()) { | ||||
354 | d = new VirtualDesktopInfo::XWindowPrivate(this); | ||||
355 | } else | ||||
356 | #endif | ||||
357 | { | ||||
358 | d = new VirtualDesktopInfo::WaylandPrivate(this); | ||||
359 | } | ||||
360 | } else { | ||||
361 | ++d->refCount; | ||||
95 | } | 362 | } | ||
363 | | ||||
364 | connect(d, &VirtualDesktopInfo::Private::currentDesktopChanged, | ||||
365 | this, &VirtualDesktopInfo::currentDesktopChanged); | ||||
366 | connect(d, &VirtualDesktopInfo::Private::numberOfDesktopsChanged, | ||||
367 | this, &VirtualDesktopInfo::numberOfDesktopsChanged); | ||||
368 | connect(d, &VirtualDesktopInfo::Private::desktopIdsChanged, | ||||
369 | this, &VirtualDesktopInfo::desktopIdsChanged); | ||||
370 | connect(d, &VirtualDesktopInfo::Private::desktopNamesChanged, | ||||
371 | this, &VirtualDesktopInfo::desktopNamesChanged); | ||||
372 | connect(d, &VirtualDesktopInfo::Private::desktopLayoutRowsChanged, | ||||
373 | this, &VirtualDesktopInfo::desktopLayoutRowsChanged); | ||||
374 | } | ||||
375 | | ||||
376 | VirtualDesktopInfo::~VirtualDesktopInfo() | ||||
377 | { | ||||
378 | --d->refCount; | ||||
379 | | ||||
380 | if (!d->refCount) { | ||||
381 | delete d; | ||||
382 | d = nullptr; | ||||
383 | } | ||||
384 | } | ||||
385 | | ||||
386 | QVariant VirtualDesktopInfo::currentDesktop() const | ||||
387 | { | ||||
388 | return d->currentDesktop(); | ||||
389 | } | ||||
390 | | ||||
391 | int VirtualDesktopInfo::numberOfDesktops() const | ||||
392 | { | ||||
393 | return d->numberOfDesktops(); | ||||
394 | } | ||||
395 | | ||||
396 | QVariantList VirtualDesktopInfo::desktopIds() const | ||||
397 | { | ||||
398 | return d->desktopIds(); | ||||
399 | } | ||||
400 | | ||||
401 | QStringList VirtualDesktopInfo::desktopNames() const | ||||
402 | { | ||||
403 | return d->desktopNames(); | ||||
404 | } | ||||
405 | | ||||
406 | quint32 VirtualDesktopInfo::position(const QVariant &desktop) const | ||||
407 | { | ||||
408 | return d->position(desktop); | ||||
409 | } | ||||
410 | | ||||
411 | int VirtualDesktopInfo::desktopLayoutRows() const | ||||
412 | { | ||||
413 | return d->desktopLayoutRows(); | ||||
414 | } | ||||
415 | | ||||
416 | void VirtualDesktopInfo::requestActivate(const QVariant &desktop) | ||||
417 | { | ||||
418 | d->requestActivate(desktop); | ||||
419 | } | ||||
420 | | ||||
421 | bool VirtualDesktopInfo::canManageDesktops() const | ||||
422 | { | ||||
423 | return d->canManageDesktops(); | ||||
424 | } | ||||
425 | | ||||
426 | } | ||||
427 | | ||||
428 | #include "virtualdesktopinfo.moc" |
ids.reserve(KWindowSystem::numberOfDesktops());