plasmawindowmanagement.cpp 27.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/********************************************************************
Copyright 2015  Martin Gräßlin <mgraesslin@kde.org>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "plasmawindowmanagement.h"
Eike Hein's avatar
Eike Hein committed
21
#include "plasmawindowmodel.h"
22
#include "plasmavirtualdesktop.h"
23 24 25 26 27 28 29
#include "event_queue.h"
#include "output.h"
#include "surface.h"
#include "wayland_pointer_p.h"
// Wayland
#include <wayland-plasma-window-management-client-protocol.h>

30 31
#include <QtConcurrentRun>
#include <QFutureWatcher>
32
#include <QTimer>
33
#include <qplatformdefs.h>
34

35 36
#include <errno.h>

37 38 39 40 41
namespace KWayland
{
namespace Client
{

42
class Q_DECL_HIDDEN PlasmaWindowManagement::Private
43 44 45 46 47 48
{
public:
    Private(PlasmaWindowManagement *q);
    WaylandPointer<org_kde_plasma_window_management, org_kde_plasma_window_management_destroy> wm;
    EventQueue *queue = nullptr;
    bool showingDesktop = false;
49
    QList<PlasmaWindow*> windows;
50
    PlasmaWindow *activeWindow = nullptr;
51 52 53 54 55

    void setup(org_kde_plasma_window_management *wm);

private:
    static void showDesktopCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t state);
56
    static void windowCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t id);
57
    void setShowDesktop(bool set);
58
    void windowCreated(org_kde_plasma_window *id, quint32 internalId);
59 60 61 62 63

    static struct org_kde_plasma_window_management_listener s_listener;
    PlasmaWindowManagement *q;
};

64
class Q_DECL_HIDDEN PlasmaWindow::Private
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
{
public:
    Private(org_kde_plasma_window *window, quint32 internalId, PlasmaWindow *q);
    WaylandPointer<org_kde_plasma_window, org_kde_plasma_window_destroy> window;
    quint32 internalId;
    QString title;
    QString appId;
    quint32 desktop = 0;
    bool active = false;
    bool minimized = false;
    bool maximized = false;
    bool fullscreen = false;
    bool keepAbove = false;
    bool keepBelow = false;
    bool onAllDesktops = false;
    bool demandsAttention = false;
    bool closeable = false;
    bool minimizeable = false;
    bool maximizeable = false;
    bool fullscreenable = false;
    bool skipTaskbar = false;
Scott Harvey's avatar
Scott Harvey committed
86
    bool skipSwitcher = false;
87 88 89 90 91 92 93 94
    bool shadeable = false;
    bool shaded = false;
    bool movable = false;
    bool resizable = false;
    bool virtualDesktopChangeable = false;
    QIcon icon;
    PlasmaWindowManagement *wm = nullptr;
    bool unmapped = false;
95 96
    QPointer<PlasmaWindow> parentWindow;
    QMetaObject::Connection parentWindowUnmappedConnection;
97
    QStringList plasmaVirtualDesktops;
98
    QRect geometry;
99
    quint32 pid = 0;
100 101 102 103

private:
    static void titleChangedCallback(void *data, org_kde_plasma_window *window, const char *title);
    static void appIdChangedCallback(void *data, org_kde_plasma_window *window, const char *app_id);
104
    static void pidChangedCallback(void *data, org_kde_plasma_window *window, uint32_t pid);
105 106 107 108 109
    static void stateChangedCallback(void *data, org_kde_plasma_window *window, uint32_t state);
    static void virtualDesktopChangedCallback(void *data, org_kde_plasma_window *window, int32_t number);
    static void themedIconNameChangedCallback(void *data, org_kde_plasma_window *window, const char *name);
    static void unmappedCallback(void *data, org_kde_plasma_window *window);
    static void initialStateCallback(void *data, org_kde_plasma_window *window);
110
    static void parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent);
111
    static void windowGeometryCallback(void *data, org_kde_plasma_window *window, int32_t x, int32_t y, uint32_t width, uint32_t height);
112
    static void iconChangedCallback(void *data, org_kde_plasma_window *org_kde_plasma_window);
113 114
    static void virtualDesktopEnteredCallback(void *data, org_kde_plasma_window *org_kde_plasma_window, const char *id);
    static void virtualDesktopLeftCallback(void *data, org_kde_plasma_window *org_kde_plasma_window, const char *id);
115 116 117 118 119 120 121 122 123 124 125 126 127
    void setActive(bool set);
    void setMinimized(bool set);
    void setMaximized(bool set);
    void setFullscreen(bool set);
    void setKeepAbove(bool set);
    void setKeepBelow(bool set);
    void setOnAllDesktops(bool set);
    void setDemandsAttention(bool set);
    void setCloseable(bool set);
    void setMinimizeable(bool set);
    void setMaximizeable(bool set);
    void setFullscreenable(bool set);
    void setSkipTaskbar(bool skip);
Scott Harvey's avatar
Scott Harvey committed
128
    void setSkipSwitcher(bool skip);
129 130 131 132 133
    void setShadeable(bool set);
    void setShaded(bool set);
    void setMovable(bool set);
    void setResizable(bool set);
    void setVirtualDesktopChangeable(bool set);
134
    void setParentWindow(PlasmaWindow *parentWindow);
135
    void setPid(const quint32 pid);
136 137 138 139 140 141 142 143 144 145

    static Private *cast(void *data) {
        return reinterpret_cast<Private*>(data);
    }

    PlasmaWindow *q;

    static struct org_kde_plasma_window_listener s_listener;
};

146 147 148 149 150 151
PlasmaWindowManagement::Private::Private(PlasmaWindowManagement *q)
    : q(q)
{
}

org_kde_plasma_window_management_listener PlasmaWindowManagement::Private::s_listener = {
152
    showDesktopCallback,
153
    windowCallback
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
};

void PlasmaWindowManagement::Private::setup(org_kde_plasma_window_management *windowManagement)
{
    Q_ASSERT(!wm);
    Q_ASSERT(windowManagement);
    wm.setup(windowManagement);
    org_kde_plasma_window_management_add_listener(windowManagement, &s_listener, this);
}

void PlasmaWindowManagement::Private::showDesktopCallback(void *data, org_kde_plasma_window_management *org_kde_plasma_window_management, uint32_t state)
{
    auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
    Q_ASSERT(wm->wm == org_kde_plasma_window_management);
    switch (state) {
    case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED:
        wm->setShowDesktop(true);
        break;
    case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED:
        wm->setShowDesktop(false);
        break;
    default:
        Q_UNREACHABLE();
        break;
    }
}

void PlasmaWindowManagement::Private::setShowDesktop(bool set)
{
    if (showingDesktop == set) {
        return;
    }
    showingDesktop = set;
    emit q->showingDesktopChanged(showingDesktop);
}

190
void PlasmaWindowManagement::Private::windowCallback(void *data, org_kde_plasma_window_management *interface, uint32_t id)
191 192
{
    auto wm = reinterpret_cast<PlasmaWindowManagement::Private*>(data);
193
    Q_ASSERT(wm->wm == interface);
194 195 196 197 198
    QTimer *timer = new QTimer();
    timer->setSingleShot(true);
    timer->setInterval(0);
    QObject::connect(timer, &QTimer::timeout, wm->q,
        [timer, wm, id] {
199
            wm->windowCreated(org_kde_plasma_window_management_get_window(wm->wm, id), id);
200 201 202 203
            timer->deleteLater();
        }, Qt::QueuedConnection
    );
    timer->start();
204 205
}

206
void PlasmaWindowManagement::Private::windowCreated(org_kde_plasma_window *id, quint32 internalId)
207 208 209 210
{
    if (queue) {
        queue->addProxy(id);
    }
211
    PlasmaWindow *window = new PlasmaWindow(q, id, internalId);
212
    window->d->wm = q;
213 214 215 216
    windows << window;
    QObject::connect(window, &QObject::destroyed, q,
        [this, window] {
            windows.removeAll(window);
217 218 219 220 221 222 223 224 225 226 227 228
            if (activeWindow == window) {
                activeWindow = nullptr;
                emit q->activeWindowChanged();
            }
        }
    );
    QObject::connect(window, &PlasmaWindow::unmapped, q,
        [this, window] {
            if (activeWindow == window) {
                activeWindow = nullptr;
                emit q->activeWindowChanged();
            }
229 230
        }
    );
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    QObject::connect(window, &PlasmaWindow::activeChanged, q,
        [this, window] {
            if (window->isActive()) {
                if (activeWindow == window) {
                    return;
                }
                activeWindow = window;
                emit q->activeWindowChanged();
            } else {
                if (activeWindow == window) {
                    activeWindow = nullptr;
                    emit q->activeWindowChanged();
                }
            }
        }
    );
247 248
}

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
PlasmaWindowManagement::PlasmaWindowManagement(QObject *parent)
    : QObject(parent)
    , d(new Private(this))
{
}

PlasmaWindowManagement::~PlasmaWindowManagement()
{
    release();
}

void PlasmaWindowManagement::destroy()
{
    if (!d->wm) {
        return;
    }
    emit interfaceAboutToBeDestroyed();
    d->wm.destroy();
}

void PlasmaWindowManagement::release()
{
    if (!d->wm) {
        return;
    }
    emit interfaceAboutToBeReleased();
    d->wm.release();
}

void PlasmaWindowManagement::setup(org_kde_plasma_window_management *wm)
{
    d->setup(wm);
}

void PlasmaWindowManagement::setEventQueue(EventQueue *queue)
{
    d->queue = queue;
}

EventQueue *PlasmaWindowManagement::eventQueue()
{
    return d->queue;
}

bool PlasmaWindowManagement::isValid() const
{
    return d->wm.isValid();
}

PlasmaWindowManagement::operator org_kde_plasma_window_management*()
{
    return d->wm;
}

PlasmaWindowManagement::operator org_kde_plasma_window_management*() const
{
    return d->wm;
}

void PlasmaWindowManagement::hideDesktop()
{
    setShowingDesktop(false);
}

void PlasmaWindowManagement::showDesktop()
{
    setShowingDesktop(true);
}

void PlasmaWindowManagement::setShowingDesktop(bool show)
{
    org_kde_plasma_window_management_show_desktop(d->wm, show ? ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED : ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED);
}

bool PlasmaWindowManagement::isShowingDesktop() const
{
    return d->showingDesktop;
}

328 329 330 331 332
QList< PlasmaWindow* > PlasmaWindowManagement::windows() const
{
    return d->windows;
}

333 334 335 336 337
PlasmaWindow *PlasmaWindowManagement::activeWindow() const
{
    return d->activeWindow;
}

Eike Hein's avatar
Eike Hein committed
338 339 340 341 342
PlasmaWindowModel *PlasmaWindowManagement::createWindowModel()
{
    return new PlasmaWindowModel(this);
}

343 344 345
org_kde_plasma_window_listener PlasmaWindow::Private::s_listener = {
    titleChangedCallback,
    appIdChangedCallback,
346
    stateChangedCallback,
347
    virtualDesktopChangedCallback,
348
    themedIconNameChangedCallback,
349
    unmappedCallback,
350
    initialStateCallback,
351
    parentWindowCallback,
352
    windowGeometryCallback,
353
    iconChangedCallback,
354 355 356
    pidChangedCallback,
    virtualDesktopEnteredCallback,
    virtualDesktopLeftCallback
357 358
};

359 360 361 362 363
void PlasmaWindow::Private::parentWindowCallback(void *data, org_kde_plasma_window *window, org_kde_plasma_window *parent)
{
    Q_UNUSED(window)
    Private *p = cast(data);
    const auto windows = p->wm->windows();
Frederik Gladhorn's avatar
Frederik Gladhorn committed
364
    auto it = std::find_if(windows.constBegin(), windows.constEnd(),
365 366 367 368
        [parent] (const PlasmaWindow *w) {
            return *w == parent;
        }
    );
Frederik Gladhorn's avatar
Frederik Gladhorn committed
369
    p->setParentWindow(it != windows.constEnd() ? *it : nullptr);
370 371
}

372 373 374 375 376 377 378 379 380 381 382 383
void PlasmaWindow::Private::windowGeometryCallback(void *data, org_kde_plasma_window *window, int32_t x, int32_t y, uint32_t width, uint32_t height)
{
    Q_UNUSED(window)
    Private *p = cast(data);
    QRect geo(x, y, width, height);
    if (geo == p->geometry) {
        return;
    }
    p->geometry = geo;
    emit p->q->geometryChanged();
}

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
void PlasmaWindow::Private::setParentWindow(PlasmaWindow *parent)
{
    const auto old = parentWindow;
    QObject::disconnect(parentWindowUnmappedConnection);
    if (parent && !parent->d->unmapped) {
        parentWindow = QPointer<PlasmaWindow>(parent);
        parentWindowUnmappedConnection = QObject::connect(parent, &PlasmaWindow::unmapped, q,
            [this] {
                setParentWindow(nullptr);
            }
        );
    } else {
        parentWindow = QPointer<PlasmaWindow>();
        parentWindowUnmappedConnection = QMetaObject::Connection();
    }
    if (parentWindow.data() != old.data()) {
        emit q->parentWindowChanged();
    }
}

404 405 406 407 408 409 410 411 412
void PlasmaWindow::Private::initialStateCallback(void *data, org_kde_plasma_window *window)
{
    Q_UNUSED(window)
    Private *p = cast(data);
    if (!p->unmapped) {
        emit p->wm->windowCreated(p->q);
    }
}

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
void PlasmaWindow::Private::titleChangedCallback(void *data, org_kde_plasma_window *window, const char *title)
{
    Q_UNUSED(window)
    Private *p = cast(data);
    const QString t = QString::fromUtf8(title);
    if (p->title == t) {
        return;
    }
    p->title = t;
    emit p->q->titleChanged();
}

void PlasmaWindow::Private::appIdChangedCallback(void *data, org_kde_plasma_window *window, const char *appId)
{
    Q_UNUSED(window)
    Private *p = cast(data);
    const QString s = QString::fromUtf8(appId);
    if (s == p->appId) {
        return;
    }
    p->appId = s;
    emit p->q->appIdChanged();
}

437 438 439 440 441 442 443 444 445 446
void PlasmaWindow::Private::pidChangedCallback(void *data, org_kde_plasma_window *window, uint32_t pid)
{
    Q_UNUSED(window)
    Private *p = cast(data);
    if (p->pid == static_cast<quint32>(pid)) {
        return;
    }
    p->pid = pid;
}

447 448 449 450
void PlasmaWindow::Private::virtualDesktopChangedCallback(void *data, org_kde_plasma_window *window, int32_t number)
{
    Q_UNUSED(window)
    Private *p = cast(data);
Allen Winter's avatar
Allen Winter committed
451
    if (p->desktop == static_cast<quint32>(number)) {
452 453 454 455 456 457 458 459
        return;
    }
    p->desktop = number;
    emit p->q->virtualDesktopChanged();
}

void PlasmaWindow::Private::unmappedCallback(void *data, org_kde_plasma_window *window)
{
460
    auto p = cast(data);
461
    Q_UNUSED(window);
462
    p->unmapped = true;
463 464
    emit p->q->unmapped();
    p->q->deleteLater();
465 466
}

467 468 469 470 471 472 473
void PlasmaWindow::Private::virtualDesktopEnteredCallback(void *data, org_kde_plasma_window *window, const char *id)
{
    auto p = cast(data);
    Q_UNUSED(window);
    const QString stringId(QString::fromUtf8(id));
    p->plasmaVirtualDesktops << stringId;
    emit p->q->plasmaVirtualDesktopEntered(stringId);
474 475 476
    if (p->plasmaVirtualDesktops.count() == 1) {
        emit p->q->onAllDesktopsChanged();
    }
477 478 479 480 481 482 483 484 485
}

void PlasmaWindow::Private::virtualDesktopLeftCallback(void *data, org_kde_plasma_window *window, const char *id)
{
    auto p = cast(data);
    Q_UNUSED(window);
    const QString stringId(QString::fromUtf8(id));
    p->plasmaVirtualDesktops.removeAll(stringId);
    emit p->q->plasmaVirtualDesktopLeft(stringId);
486 487 488
    if (p->plasmaVirtualDesktops.isEmpty()) {
        emit p->q->onAllDesktopsChanged();
    }
489 490
}

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
void PlasmaWindow::Private::stateChangedCallback(void *data, org_kde_plasma_window *window, uint32_t state)
{
    auto p = cast(data);
    Q_UNUSED(window);
    p->setActive(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
    p->setMinimized(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
    p->setMaximized(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
    p->setFullscreen(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN);
    p->setKeepAbove(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
    p->setKeepBelow(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
    p->setOnAllDesktops(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ON_ALL_DESKTOPS);
    p->setDemandsAttention(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION);
    p->setCloseable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE);
    p->setFullscreenable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE);
    p->setMaximizeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE);
    p->setMinimizeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE);
Marco Martin's avatar
Marco Martin committed
507
    p->setSkipTaskbar(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR);
Scott Harvey's avatar
Scott Harvey committed
508
    p->setSkipSwitcher(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER);
509
    p->setShadeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE);
510
    p->setShaded(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
511 512
    p->setMovable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE);
    p->setResizable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE);
513
    p->setVirtualDesktopChangeable(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE);
514 515
}

516 517 518 519
void PlasmaWindow::Private::themedIconNameChangedCallback(void *data, org_kde_plasma_window *window, const char *name)
{
    auto p = cast(data);
    Q_UNUSED(window);
520 521 522 523 524 525 526
    const QString themedName = QString::fromUtf8(name);
    if (!themedName.isEmpty()) {
        QIcon icon = QIcon::fromTheme(themedName);
        p->icon = icon;
    } else {
        p->icon = QIcon();
    }
527 528 529
    emit p->q->iconChanged();
}

530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
static int readData(int fd, QByteArray &data)
{
    // implementation based on QtWayland file qwaylanddataoffer.cpp
    char buf[4096];
    int retryCount = 0;
    int n;
    while (true) {
        n = QT_READ(fd, buf, sizeof buf);
        if (n == -1 && (errno == EAGAIN) && ++retryCount < 1000) {
            usleep(1000);
        } else {
            break;
        }
    }
    if (n > 0) {
        data.append(buf, n);
        n = readData(fd, data);
    }
    return n;
}

void PlasmaWindow::Private::iconChangedCallback(void *data, org_kde_plasma_window *window)
{
    auto p = cast(data);
    Q_UNUSED(window);
    int pipeFds[2];
    if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) {
        return;
    }
    org_kde_plasma_window_get_icon(p->window, pipeFds[1]);
    close(pipeFds[1]);
    const int pipeFd = pipeFds[0];
    auto readIcon = [pipeFd] () -> QIcon {
        QByteArray content;
        if (readData(pipeFd, content) != 0) {
            close(pipeFd);
566
            return QIcon();
567 568 569 570 571 572 573 574 575 576 577
        }
        close(pipeFd);
        QDataStream ds(content);
        QIcon icon;
        ds >> icon;
        return icon;
    };
    QFutureWatcher<QIcon> *watcher = new QFutureWatcher<QIcon>(p->q);
    QObject::connect(watcher, &QFutureWatcher<QIcon>::finished, p->q,
        [p, watcher] {
            watcher->deleteLater();
578 579 580 581 582 583
            QIcon icon = watcher->result();
            if (!icon.isNull()) {
                p->icon = icon;
            } else {
                p->icon = QIcon::fromTheme(QStringLiteral("wayland"));
            }
584 585 586 587 588 589
            emit p->q->iconChanged();
        }
    );
    watcher->setFuture(QtConcurrent::run(readIcon));
}

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
void PlasmaWindow::Private::setActive(bool set)
{
    if (active == set) {
        return;
    }
    active = set;
    emit q->activeChanged();
}

void PlasmaWindow::Private::setFullscreen(bool set)
{
    if (fullscreen == set) {
        return;
    }
    fullscreen = set;
    emit q->fullscreenChanged();
}

void PlasmaWindow::Private::setKeepAbove(bool set)
{
    if (keepAbove == set) {
        return;
    }
    keepAbove = set;
    emit q->keepAboveChanged();
}

void PlasmaWindow::Private::setKeepBelow(bool set)
{
    if (keepBelow == set) {
        return;
    }
    keepBelow = set;
    emit q->keepBelowChanged();
}

void PlasmaWindow::Private::setMaximized(bool set)
{
    if (maximized == set) {
        return;
    }
    maximized = set;
    emit q->maximizedChanged();
}

void PlasmaWindow::Private::setMinimized(bool set)
{
    if (minimized == set) {
        return;
    }
    minimized = set;
    emit q->minimizedChanged();
}

void PlasmaWindow::Private::setOnAllDesktops(bool set)
{
    if (onAllDesktops == set) {
        return;
    }
    onAllDesktops = set;
    emit q->onAllDesktopsChanged();
}

void PlasmaWindow::Private::setDemandsAttention(bool set)
{
    if (demandsAttention == set) {
        return;
    }
    demandsAttention = set;
    emit q->demandsAttentionChanged();
}

void PlasmaWindow::Private::setCloseable(bool set)
{
    if (closeable == set) {
        return;
    }
    closeable = set;
    emit q->closeableChanged();
}

void PlasmaWindow::Private::setFullscreenable(bool set)
{
    if (fullscreenable == set) {
        return;
    }
    fullscreenable = set;
    emit q->fullscreenableChanged();
}

void PlasmaWindow::Private::setMaximizeable(bool set)
{
    if (maximizeable == set) {
        return;
    }
    maximizeable = set;
    emit q->maximizeableChanged();
}

void PlasmaWindow::Private::setMinimizeable(bool set)
{
    if (minimizeable == set) {
        return;
    }
    minimizeable = set;
    emit q->minimizeableChanged();
}

Marco Martin's avatar
Marco Martin committed
698 699 700 701 702 703 704 705 706
void PlasmaWindow::Private::setSkipTaskbar(bool skip)
{
    if (skipTaskbar == skip) {
        return;
    }
    skipTaskbar = skip;
    emit q->skipTaskbarChanged();
}

Scott Harvey's avatar
Scott Harvey committed
707 708 709 710 711 712 713 714 715
void PlasmaWindow::Private::setSkipSwitcher(bool skip)
{
    if (skipSwitcher == skip) {
        return;
    }
    skipSwitcher = skip;
    emit q->skipSwitcherChanged();
}

716
void PlasmaWindow::Private::setShadeable(bool set)
717
{
718
    if (shadeable == set) {
719 720
        return;
    }
721 722
    shadeable = set;
    emit q->shadeableChanged();
723 724 725 726 727 728 729 730 731 732 733
}

void PlasmaWindow::Private::setShaded(bool set)
{
    if (shaded == set) {
        return;
    }
    shaded = set;
    emit q->shadedChanged();
}

734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
void PlasmaWindow::Private::setMovable(bool set)
{
    if (movable == set) {
        return;
    }
    movable = set;
    emit q->movableChanged();
}

void PlasmaWindow::Private::setResizable(bool set)
{
    if (resizable == set) {
        return;
    }
    resizable = set;
    emit q->resizableChanged();
}

752 753 754 755 756 757 758 759 760
void PlasmaWindow::Private::setVirtualDesktopChangeable(bool set)
{
    if (virtualDesktopChangeable == set) {
        return;
    }
    virtualDesktopChangeable = set;
    emit q->virtualDesktopChangeableChanged();
}

761 762 763
PlasmaWindow::Private::Private(org_kde_plasma_window *w, quint32 internalId, PlasmaWindow *q)
    : internalId(internalId)
    , q(q)
764 765 766 767 768
{
    window.setup(w);
    org_kde_plasma_window_add_listener(w, &s_listener, this);
}

769
PlasmaWindow::PlasmaWindow(PlasmaWindowManagement *parent, org_kde_plasma_window *window, quint32 internalId)
770
    : QObject(parent)
771
    , d(new Private(window, internalId, this))
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
{
}

PlasmaWindow::~PlasmaWindow()
{
    release();
}

void PlasmaWindow::destroy()
{
    d->window.destroy();
}

void PlasmaWindow::release()
{
    d->window.release();
}

bool PlasmaWindow::isValid() const
{
    return d->window.isValid();
}

PlasmaWindow::operator org_kde_plasma_window*() const
{
    return d->window;
}

PlasmaWindow::operator org_kde_plasma_window*()
{
    return d->window;
}

QString PlasmaWindow::appId() const
{
    return d->appId;
}

810 811 812 813 814
quint32 PlasmaWindow::pid() const
{
    return d->pid;
}

815 816 817 818 819 820 821 822 823 824
QString PlasmaWindow::title() const
{
    return d->title;
}

quint32 PlasmaWindow::virtualDesktop() const
{
    return d->desktop;
}

825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
bool PlasmaWindow::isActive() const
{
    return d->active;
}

bool PlasmaWindow::isFullscreen() const
{
    return d->fullscreen;
}

bool PlasmaWindow::isKeepAbove() const
{
    return d->keepAbove;
}

bool PlasmaWindow::isKeepBelow() const
{
    return d->keepBelow;
}

bool PlasmaWindow::isMaximized() const
{
    return d->maximized;
}

bool PlasmaWindow::isMinimized() const
{
    return d->minimized;
}

bool PlasmaWindow::isOnAllDesktops() const
{
857 858 859 860 861 862 863
    //from protocol version 8 virtual desktops are managed by plasmaVirtualDesktops
    if (org_kde_plasma_window_get_version(d->window) < 8) {
        return d->onAllDesktops;
    } else {
        return d->plasmaVirtualDesktops.isEmpty();
    }
    
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
}

bool PlasmaWindow::isDemandingAttention() const
{
    return d->demandsAttention;
}

bool PlasmaWindow::isCloseable() const
{
    return d->closeable;
}

bool PlasmaWindow::isFullscreenable() const
{
    return d->fullscreenable;
}

bool PlasmaWindow::isMaximizeable() const
{
    return d->maximizeable;
}

bool PlasmaWindow::isMinimizeable() const
{
    return d->minimizeable;
}

Marco Martin's avatar
Marco Martin committed
891 892 893 894 895
bool PlasmaWindow::skipTaskbar() const
{
    return d->skipTaskbar;
}

Scott Harvey's avatar
Scott Harvey committed
896 897 898 899
bool PlasmaWindow::skipSwitcher() const
{
    return d->skipSwitcher;
}
Marco Martin's avatar
Marco Martin committed
900

901 902 903 904 905
QIcon PlasmaWindow::icon() const
{
    return d->icon;
}

906
bool PlasmaWindow::isShadeable() const
907
{
908
    return d->shadeable;
909 910 911 912 913 914 915
}

bool PlasmaWindow::isShaded() const
{
    return d->shaded;
}

916 917 918 919 920 921 922 923 924 925
bool PlasmaWindow::isResizable() const
{
    return d->resizable;
}

bool PlasmaWindow::isMovable() const
{
    return d->movable;
}

926 927 928 929 930
bool PlasmaWindow::isVirtualDesktopChangeable() const
{
    return d->virtualDesktopChangeable;
}

931 932 933 934 935 936 937
void PlasmaWindow::requestActivate()
{
    org_kde_plasma_window_set_state(d->window,
        ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE,
        ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
}

938 939 940 941 942
void PlasmaWindow::requestClose()
{
    org_kde_plasma_window_close(d->window);
}

943 944 945 946 947 948 949 950 951 952
void PlasmaWindow::requestMove()
{
    org_kde_plasma_window_request_move(d->window);
}

void PlasmaWindow::requestResize()
{
    org_kde_plasma_window_request_resize(d->window);
}

953 954 955 956 957
void PlasmaWindow::requestVirtualDesktop(quint32 desktop)
{
    org_kde_plasma_window_set_virtual_desktop(d->window, desktop);
}

958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
void PlasmaWindow::requestToggleKeepAbove()
{
    if (d->keepAbove) {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE,
            0);
    } else {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
    }
}

void PlasmaWindow::requestToggleKeepBelow()
{
    if (d->keepBelow) {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW,
            0);
    } else {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
    }
}

984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
void PlasmaWindow::requestToggleMinimized()
{
    if (d->minimized) {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED,
            0);
    } else {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
    }
}

void PlasmaWindow::requestToggleMaximized()
{
    if (d->maximized) {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED,
            0);
    } else {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
    }
}

1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
void PlasmaWindow::setMinimizedGeometry(Surface *panel, const QRect &geom)
{
    org_kde_plasma_window_set_minimized_geometry(d->window, *panel, geom.x(), geom.y(), geom.width(), geom.height());
}

void PlasmaWindow::unsetMinimizedGeometry(Surface *panel)
{
    org_kde_plasma_window_unset_minimized_geometry(d->window, *panel);
}

1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
void PlasmaWindow::requestToggleShaded()
{
    if (d->shaded) {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED,
            0);
    } else {
        org_kde_plasma_window_set_state(d->window,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED,
            ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
    }
}

1033 1034 1035 1036 1037
quint32 PlasmaWindow::internalId() const
{
    return d->internalId;
}

1038 1039 1040 1041 1042
QPointer<PlasmaWindow> PlasmaWindow::parentWindow() const
{
    return d->parentWindow;
}

1043 1044 1045 1046 1047
QRect PlasmaWindow::geometry() const
{
    return d->geometry;
}

1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
void PlasmaWindow::requestEnterVirtualDesktop(const QString &id)
{
    org_kde_plasma_window_request_enter_virtual_desktop(d->window, id.toUtf8());
}

void PlasmaWindow::requestEnterNewVirtualDesktop()
{
    org_kde_plasma_window_request_enter_new_virtual_desktop(d->window);
}

void PlasmaWindow::requestLeaveVirtualDesktop(const QString &id)
{
    org_kde_plasma_window_request_leave_virtual_desktop(d->window, id.toUtf8());
}

QStringList PlasmaWindow::plasmaVirtualDesktops() const
{
    return d->plasmaVirtualDesktops;
}

1068 1069
}
}