Changeset View
Changeset View
Standalone View
Standalone View
src/client/plasmawindowmanagement.cpp
Show All 20 Lines | |||||
21 | #include "plasmawindowmodel.h" | 21 | #include "plasmawindowmodel.h" | ||
22 | #include "event_queue.h" | 22 | #include "event_queue.h" | ||
23 | #include "output.h" | 23 | #include "output.h" | ||
24 | #include "surface.h" | 24 | #include "surface.h" | ||
25 | #include "wayland_pointer_p.h" | 25 | #include "wayland_pointer_p.h" | ||
26 | // Wayland | 26 | // Wayland | ||
27 | #include <wayland-plasma-window-management-client-protocol.h> | 27 | #include <wayland-plasma-window-management-client-protocol.h> | ||
28 | 28 | | |||
29 | #include <QtConcurrentRun> | ||||
30 | #include <QFutureWatcher> | ||||
29 | #include <QTimer> | 31 | #include <QTimer> | ||
32 | #include <qplatformdefs.h> | ||||
30 | 33 | | |||
31 | namespace KWayland | 34 | namespace KWayland | ||
32 | { | 35 | { | ||
33 | namespace Client | 36 | namespace Client | ||
34 | { | 37 | { | ||
35 | 38 | | |||
36 | class PlasmaWindowManagement::Private | 39 | class PlasmaWindowManagement::Private | ||
37 | { | 40 | { | ||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Line(s) | 95 | private: | |||
94 | static void appIdChangedCallback(void *data, org_kde_plasma_window *window, const char *app_id); | 97 | static void appIdChangedCallback(void *data, org_kde_plasma_window *window, const char *app_id); | ||
95 | static void stateChangedCallback(void *data, org_kde_plasma_window *window, uint32_t state); | 98 | static void stateChangedCallback(void *data, org_kde_plasma_window *window, uint32_t state); | ||
96 | static void virtualDesktopChangedCallback(void *data, org_kde_plasma_window *window, int32_t number); | 99 | static void virtualDesktopChangedCallback(void *data, org_kde_plasma_window *window, int32_t number); | ||
97 | static void themedIconNameChangedCallback(void *data, org_kde_plasma_window *window, const char *name); | 100 | static void themedIconNameChangedCallback(void *data, org_kde_plasma_window *window, const char *name); | ||
98 | static void unmappedCallback(void *data, org_kde_plasma_window *window); | 101 | static void unmappedCallback(void *data, org_kde_plasma_window *window); | ||
99 | static void initialStateCallback(void *data, org_kde_plasma_window *window); | 102 | static void initialStateCallback(void *data, org_kde_plasma_window *window); | ||
100 | static void parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent); | 103 | static void parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent); | ||
101 | static void windowGeometryCallback(void *data, org_kde_plasma_window *window, int32_t x, int32_t y, uint32_t width, uint32_t height); | 104 | static void windowGeometryCallback(void *data, org_kde_plasma_window *window, int32_t x, int32_t y, uint32_t width, uint32_t height); | ||
105 | static void iconChangedCallback(void *data, org_kde_plasma_window *org_kde_plasma_window); | ||||
102 | void setActive(bool set); | 106 | void setActive(bool set); | ||
103 | void setMinimized(bool set); | 107 | void setMinimized(bool set); | ||
104 | void setMaximized(bool set); | 108 | void setMaximized(bool set); | ||
105 | void setFullscreen(bool set); | 109 | void setFullscreen(bool set); | ||
106 | void setKeepAbove(bool set); | 110 | void setKeepAbove(bool set); | ||
107 | void setKeepBelow(bool set); | 111 | void setKeepBelow(bool set); | ||
108 | void setOnAllDesktops(bool set); | 112 | void setOnAllDesktops(bool set); | ||
109 | void setDemandsAttention(bool set); | 113 | void setDemandsAttention(bool set); | ||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Line(s) | 332 | org_kde_plasma_window_listener PlasmaWindow::Private::s_listener = { | |||
329 | titleChangedCallback, | 333 | titleChangedCallback, | ||
330 | appIdChangedCallback, | 334 | appIdChangedCallback, | ||
331 | stateChangedCallback, | 335 | stateChangedCallback, | ||
332 | virtualDesktopChangedCallback, | 336 | virtualDesktopChangedCallback, | ||
333 | themedIconNameChangedCallback, | 337 | themedIconNameChangedCallback, | ||
334 | unmappedCallback, | 338 | unmappedCallback, | ||
335 | initialStateCallback, | 339 | initialStateCallback, | ||
336 | parentWindowCallback, | 340 | parentWindowCallback, | ||
337 | windowGeometryCallback | 341 | windowGeometryCallback, | ||
342 | iconChangedCallback | ||||
338 | }; | 343 | }; | ||
339 | 344 | | |||
340 | void PlasmaWindow::Private::parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent) | 345 | void PlasmaWindow::Private::parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent) | ||
341 | { | 346 | { | ||
342 | Q_UNUSED(window) | 347 | Q_UNUSED(window) | ||
343 | Private *p = cast(data); | 348 | Private *p = cast(data); | ||
344 | const auto windows = p->wm->windows(); | 349 | const auto windows = p->wm->windows(); | ||
345 | auto it = std::find_if(windows.begin(), windows.end(), | 350 | auto it = std::find_if(windows.begin(), windows.end(), | ||
▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Line(s) | 472 | if (!themedName.isEmpty()) { | |||
468 | QIcon icon = QIcon::fromTheme(themedName); | 473 | QIcon icon = QIcon::fromTheme(themedName); | ||
469 | p->icon = icon; | 474 | p->icon = icon; | ||
470 | } else { | 475 | } else { | ||
471 | p->icon = QIcon(); | 476 | p->icon = QIcon(); | ||
472 | } | 477 | } | ||
473 | emit p->q->iconChanged(); | 478 | emit p->q->iconChanged(); | ||
474 | } | 479 | } | ||
475 | 480 | | |||
481 | static int readData(int fd, QByteArray &data) | ||||
482 | { | ||||
483 | // implementation based on QtWayland file qwaylanddataoffer.cpp | ||||
484 | char buf[4096]; | ||||
485 | int retryCount = 0; | ||||
486 | int n; | ||||
487 | while (true) { | ||||
488 | n = QT_READ(fd, buf, sizeof buf); | ||||
489 | if (n == -1 && (errno == EAGAIN) && ++retryCount < 1000) { | ||||
roberts: EAGAIN comes from reads of O_NONBLOCK fd's, but this seems to be a blocking pipe (no calls to… | |||||
490 | usleep(1000); | ||||
491 | } else { | ||||
492 | break; | ||||
493 | } | ||||
494 | } | ||||
495 | if (n > 0) { | ||||
496 | data.append(buf, n); | ||||
497 | n = readData(fd, data); | ||||
498 | } | ||||
499 | return n; | ||||
500 | } | ||||
501 | | ||||
502 | void PlasmaWindow::Private::iconChangedCallback(void *data, org_kde_plasma_window *window) | ||||
503 | { | ||||
504 | auto p = cast(data); | ||||
505 | Q_UNUSED(window); | ||||
506 | int pipeFds[2]; | ||||
507 | if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) { | ||||
508 | return; | ||||
509 | } | ||||
510 | org_kde_plasma_window_get_icon(p->window, pipeFds[1]); | ||||
511 | close(pipeFds[1]); | ||||
512 | const int pipeFd = pipeFds[0]; | ||||
513 | auto readIcon = [pipeFd] () -> QIcon { | ||||
514 | QByteArray content; | ||||
515 | if (readData(pipeFd, content) != 0) { | ||||
516 | close(pipeFd); | ||||
roberts: pipeFd could leak here. | |||||
517 | return QIcon::fromTheme(QStringLiteral("wayland")); | ||||
518 | } | ||||
519 | close(pipeFd); | ||||
520 | QDataStream ds(content); | ||||
521 | QIcon icon; | ||||
522 | ds >> icon; | ||||
523 | if (icon.isNull()) { | ||||
524 | return QIcon::fromTheme(QStringLiteral("wayland")); | ||||
525 | } | ||||
526 | return icon; | ||||
527 | }; | ||||
528 | QFutureWatcher<QIcon> *watcher = new QFutureWatcher<QIcon>(p->q); | ||||
529 | QObject::connect(watcher, &QFutureWatcher<QIcon>::finished, p->q, | ||||
530 | [p, watcher] { | ||||
531 | watcher->deleteLater(); | ||||
532 | p->icon = watcher->result(); | ||||
533 | emit p->q->iconChanged(); | ||||
534 | } | ||||
535 | ); | ||||
536 | watcher->setFuture(QtConcurrent::run(readIcon)); | ||||
537 | } | ||||
538 | | ||||
476 | void PlasmaWindow::Private::setActive(bool set) | 539 | void PlasmaWindow::Private::setActive(bool set) | ||
477 | { | 540 | { | ||
478 | if (active == set) { | 541 | if (active == set) { | ||
479 | return; | 542 | return; | ||
480 | } | 543 | } | ||
481 | active = set; | 544 | active = set; | ||
482 | emit q->activeChanged(); | 545 | emit q->activeChanged(); | ||
483 | } | 546 | } | ||
▲ Show 20 Lines • Show All 402 Lines • Show Last 20 Lines |
EAGAIN comes from reads of O_NONBLOCK fd's, but this seems to be a blocking pipe (no calls to fcntl() or pipe2()).
As such the read call could block the thread for significant or unbounded time - depending on whether QT_READ swallows EINTR - if the other side of the pipe failed to close the fd.