File indexing completed on 2024-05-19 05:35:55

0001 /*
0002     SPDX-FileCopyrightText: 2016 Eike Hein <hein.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "windowmodel.h"
0007 #include "pagermodel.h"
0008 
0009 #include <abstracttasksmodel.h>
0010 
0011 #include <QGuiApplication>
0012 #include <QMetaEnum>
0013 #include <QScreen>
0014 
0015 #include <KWindowSystem>
0016 #include <KX11Extras>
0017 
0018 using namespace TaskManager;
0019 
0020 class WindowModel::Private
0021 {
0022 public:
0023     Private(WindowModel *q);
0024 
0025     PagerModel *pagerModel = nullptr;
0026 
0027 private:
0028     WindowModel *q;
0029 };
0030 
0031 WindowModel::Private::Private(WindowModel *q)
0032     : q(q)
0033 {
0034     Q_UNUSED(this->q);
0035 }
0036 
0037 WindowModel::WindowModel(PagerModel *parent)
0038     : TaskFilterProxyModel(parent)
0039     , d(new Private(this))
0040 {
0041     d->pagerModel = parent;
0042     connect(parent, &PagerModel::pagerItemSizeChanged, this, &WindowModel::onPagerItemSizeChanged);
0043     connect(this, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
0044         if (roles.contains(AbstractTasksModel::StackingOrder)) {
0045             Q_EMIT dataChanged(topLeft, bottomRight, {WindowModelRoles::StackingOrder});
0046         }
0047     });
0048 }
0049 
0050 WindowModel::~WindowModel()
0051 {
0052 }
0053 
0054 QHash<int, QByteArray> WindowModel::roleNames() const
0055 {
0056     QHash<int, QByteArray> roles = TaskFilterProxyModel::roleNames();
0057 
0058     QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("WindowModelRoles"));
0059 
0060     for (int i = 0; i < e.keyCount(); ++i) {
0061         roles.insert(e.value(i), e.key(i));
0062     }
0063 
0064     return roles;
0065 }
0066 
0067 QVariant WindowModel::data(const QModelIndex &index, int role) const
0068 {
0069     if (role == AbstractTasksModel::Geometry) {
0070         QRect windowGeo = TaskFilterProxyModel::data(index, role).toRect();
0071         const QRect clampingRect(QPoint(0, 0), d->pagerModel->pagerItemSize());
0072 
0073         if (KWindowSystem::isPlatformX11() && KX11Extras::mapViewport()) {
0074             int x = windowGeo.center().x() % clampingRect.width();
0075             int y = windowGeo.center().y() % clampingRect.height();
0076 
0077             if (x < 0) {
0078                 x = x + clampingRect.width();
0079             }
0080 
0081             if (y < 0) {
0082                 y = y + clampingRect.height();
0083             }
0084 
0085             const QRect mappedGeo(x - windowGeo.width() / 2, y - windowGeo.height() / 2, windowGeo.width(), windowGeo.height());
0086 
0087             if (filterByScreen() && screenGeometry().isValid()) {
0088                 const QPoint &screenOffset = screenGeometry().topLeft();
0089 
0090                 windowGeo = mappedGeo.translated(0 - screenOffset.x(), 0 - screenOffset.y());
0091             }
0092         } else if (filterByScreen() && screenGeometry().isValid()) {
0093             const QPoint &screenOffset = screenGeometry().topLeft();
0094 
0095             windowGeo.translate(0 - screenOffset.x(), 0 - screenOffset.y());
0096         }
0097 
0098         // Restrict to desktop/screen rect.
0099         return windowGeo.intersected(clampingRect);
0100     } else if (role == StackingOrder) {
0101         const auto &winId = TaskFilterProxyModel::data(index, AbstractTasksModel::WinIdList);
0102         const int z = d->pagerModel->stackingOrder(index).indexOf(winId);
0103 
0104         if (z != -1) {
0105             return z;
0106         }
0107         return 0;
0108     }
0109 
0110     return TaskFilterProxyModel::data(index, role);
0111 }
0112 
0113 void WindowModel::onPagerItemSizeChanged()
0114 {
0115     if (rowCount() > 0) {
0116         Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {AbstractTasksModel::Geometry});
0117     }
0118 }