Changeset View
Changeset View
Standalone View
Standalone View
libtaskmanager/xwindowtasksmodel.cpp
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Line(s) | 57 | public: | |||
---|---|---|---|---|---|
60 | 60 | | |||
61 | QVector<WId> windows; | 61 | QVector<WId> windows; | ||
62 | QSet<WId> transients; | 62 | QSet<WId> transients; | ||
63 | QMultiHash<WId, WId> transientsDemandingAttention; | 63 | QMultiHash<WId, WId> transientsDemandingAttention; | ||
64 | QHash<WId, KWindowInfo*> windowInfoCache; | 64 | QHash<WId, KWindowInfo*> windowInfoCache; | ||
65 | QHash<WId, AppData> appDataCache; | 65 | QHash<WId, AppData> appDataCache; | ||
66 | QHash<WId, QRect> delegateGeometries; | 66 | QHash<WId, QRect> delegateGeometries; | ||
67 | QSet<WId> usingFallbackIcon; | 67 | QSet<WId> usingFallbackIcon; | ||
68 | QHash<WId, QTime> lastActivated; | ||||
69 | QList<WId> cachedStackingOrder; | ||||
68 | WId activeWindow = -1; | 70 | WId activeWindow = -1; | ||
69 | KSharedConfig::Ptr rulesConfig; | 71 | KSharedConfig::Ptr rulesConfig; | ||
70 | KDirWatch *configWatcher = nullptr; | 72 | KDirWatch *configWatcher = nullptr; | ||
71 | QTimer sycocaChangeTimer; | 73 | QTimer sycocaChangeTimer; | ||
72 | 74 | | |||
73 | void init(); | 75 | void init(); | ||
74 | void addWindow(WId window); | 76 | void addWindow(WId window); | ||
75 | void removeWindow(WId window); | 77 | void removeWindow(WId window); | ||
Show All 39 Lines | 109 | auto clearCacheAndRefresh = [this] { | |||
115 | q->dataChanged(q->index(0, 0), q->index(windows.count() - 1, 0), | 117 | q->dataChanged(q->index(0, 0), q->index(windows.count() - 1, 0), | ||
116 | QVector<int>{Qt::DecorationRole, AbstractTasksModel::AppId, | 118 | QVector<int>{Qt::DecorationRole, AbstractTasksModel::AppId, | ||
117 | AbstractTasksModel::AppName, AbstractTasksModel::GenericName, | 119 | AbstractTasksModel::AppName, AbstractTasksModel::GenericName, | ||
118 | AbstractTasksModel::LauncherUrl, | 120 | AbstractTasksModel::LauncherUrl, | ||
119 | AbstractTasksModel::LauncherUrlWithoutIcon, | 121 | AbstractTasksModel::LauncherUrlWithoutIcon, | ||
120 | AbstractTasksModel::SkipTaskbar}); | 122 | AbstractTasksModel::SkipTaskbar}); | ||
121 | }; | 123 | }; | ||
122 | 124 | | |||
125 | cachedStackingOrder = KWindowSystem::stackingOrder(); | ||||
126 | | ||||
123 | sycocaChangeTimer.setSingleShot(true); | 127 | sycocaChangeTimer.setSingleShot(true); | ||
124 | sycocaChangeTimer.setInterval(100); | 128 | sycocaChangeTimer.setInterval(100); | ||
125 | 129 | | |||
126 | QObject::connect(&sycocaChangeTimer, &QTimer::timeout, q, clearCacheAndRefresh); | 130 | QObject::connect(&sycocaChangeTimer, &QTimer::timeout, q, clearCacheAndRefresh); | ||
127 | 131 | | |||
128 | void (KSycoca::*myDatabaseChangeSignal)(const QStringList &) = &KSycoca::databaseChanged; | 132 | void (KSycoca::*myDatabaseChangeSignal)(const QStringList &) = &KSycoca::databaseChanged; | ||
129 | QObject::connect(KSycoca::self(), myDatabaseChangeSignal, q, | 133 | QObject::connect(KSycoca::self(), myDatabaseChangeSignal, q, | ||
130 | [this](const QStringList &changedResources) { | 134 | [this](const QStringList &changedResources) { | ||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Line(s) | 173 | QObject::connect(windowSystem, &XWindowSystemEventBatcher::windowChanged, q, | |||
172 | } | 176 | } | ||
173 | ); | 177 | ); | ||
174 | 178 | | |||
175 | // Update IsActive for previously- and newly-active windows. | 179 | // Update IsActive for previously- and newly-active windows. | ||
176 | QObject::connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, q, | 180 | QObject::connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, q, | ||
177 | [this](WId window) { | 181 | [this](WId window) { | ||
178 | const WId oldActiveWindow = activeWindow; | 182 | const WId oldActiveWindow = activeWindow; | ||
179 | activeWindow = window; | 183 | activeWindow = window; | ||
184 | lastActivated[activeWindow] = QTime::currentTime(); | ||||
180 | 185 | | |||
181 | int row = windows.indexOf(oldActiveWindow); | 186 | int row = windows.indexOf(oldActiveWindow); | ||
182 | 187 | | |||
183 | if (row != -1) { | 188 | if (row != -1) { | ||
184 | dataChanged(oldActiveWindow, QVector<int>{IsActive}); | 189 | dataChanged(oldActiveWindow, QVector<int>{IsActive}); | ||
185 | } | 190 | } | ||
186 | 191 | | |||
187 | row = windows.indexOf(window); | 192 | row = windows.indexOf(window); | ||
188 | 193 | | |||
189 | if (row != -1) { | 194 | if (row != -1) { | ||
190 | dataChanged(window, QVector<int>{IsActive}); | 195 | dataChanged(window, QVector<int>{IsActive}); | ||
191 | } | 196 | } | ||
192 | } | 197 | } | ||
193 | ); | 198 | ); | ||
194 | 199 | | |||
200 | QObject::connect(KWindowSystem::self(), &KWindowSystem::stackingOrderChanged, q, | ||||
201 | [this]() { | ||||
202 | cachedStackingOrder = KWindowSystem::stackingOrder(); | ||||
203 | q->dataChanged(q->index(0, 0), q->index(q->rowCount() - 1, 0), | ||||
davidedmundson: if (rowCount > 0) {
}
otherwise you emit data changed for an invalid index. I think it could… | |||||
204 | QVector<int>{StackingOrder}); | ||||
205 | } | ||||
206 | ); | ||||
207 | | ||||
195 | activeWindow = KWindowSystem::activeWindow(); | 208 | activeWindow = KWindowSystem::activeWindow(); | ||
196 | 209 | | |||
197 | // Add existing windows. | 210 | // Add existing windows. | ||
198 | foreach(const WId window, KWindowSystem::windows()) { | 211 | foreach(const WId window, KWindowSystem::windows()) { | ||
199 | addWindow(window); | 212 | addWindow(window); | ||
200 | } | 213 | } | ||
201 | } | 214 | } | ||
202 | 215 | | |||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | 262 | { | |||
250 | const int row = windows.indexOf(window); | 263 | const int row = windows.indexOf(window); | ||
251 | 264 | | |||
252 | if (row != -1) { | 265 | if (row != -1) { | ||
253 | q->beginRemoveRows(QModelIndex(), row, row); | 266 | q->beginRemoveRows(QModelIndex(), row, row); | ||
254 | windows.removeAt(row); | 267 | windows.removeAt(row); | ||
255 | transientsDemandingAttention.remove(window); | 268 | transientsDemandingAttention.remove(window); | ||
256 | delete windowInfoCache.take(window); | 269 | delete windowInfoCache.take(window); | ||
257 | appDataCache.remove(window); | 270 | appDataCache.remove(window); | ||
258 | usingFallbackIcon.remove(window); | | |||
259 | delegateGeometries.remove(window); | 271 | delegateGeometries.remove(window); | ||
272 | usingFallbackIcon.remove(window); | ||||
273 | lastActivated.remove(window); | ||||
260 | q->endRemoveRows(); | 274 | q->endRemoveRows(); | ||
261 | } else { // Could be a transient. | 275 | } else { // Could be a transient. | ||
262 | // Removing a transient might change the demands attention state of the leader. | 276 | // Removing a transient might change the demands attention state of the leader. | ||
263 | if (transients.remove(window)) { | 277 | if (transients.remove(window)) { | ||
264 | const WId leader = transientsDemandingAttention.key(window, XCB_WINDOW_NONE); | 278 | const WId leader = transientsDemandingAttention.key(window, XCB_WINDOW_NONE); | ||
265 | 279 | | |||
266 | if (leader != XCB_WINDOW_NONE) { | 280 | if (leader != XCB_WINDOW_NONE) { | ||
267 | transientsDemandingAttention.remove(leader, window); | 281 | transientsDemandingAttention.remove(leader, window); | ||
▲ Show 20 Lines • Show All 380 Lines • ▼ Show 20 Line(s) | 659 | } else if (role == SkipTaskbar) { | |||
648 | // but they should be shown on pagers. | 662 | // but they should be shown on pagers. | ||
649 | return (info->hasState(NET::SkipTaskbar) | 663 | return (info->hasState(NET::SkipTaskbar) | ||
650 | || info->windowType(NET::UtilityMask) == NET::Utility | 664 | || info->windowType(NET::UtilityMask) == NET::Utility | ||
651 | || d->appData(window).skipTaskbar); | 665 | || d->appData(window).skipTaskbar); | ||
652 | } else if (role == SkipPager) { | 666 | } else if (role == SkipPager) { | ||
653 | return d->windowInfo(window)->hasState(NET::SkipPager); | 667 | return d->windowInfo(window)->hasState(NET::SkipPager); | ||
654 | } else if (role == AppPid) { | 668 | } else if (role == AppPid) { | ||
655 | return d->windowInfo(window)->pid(); | 669 | return d->windowInfo(window)->pid(); | ||
670 | } else if (role == StackingOrder) { | ||||
671 | return d->cachedStackingOrder.indexOf(window); | ||||
672 | } else if (role == LastActivated) { | ||||
673 | if (d->lastActivated.contains(window)) { | ||||
674 | return d->lastActivated.value(window); | ||||
675 | } | ||||
That's double lookup in intensive called function, what about int idx = d->lastActivated.indexOf(window); if (idx >= 0) return d->lastActivated.at(idx); anthonyfieroni: That's double lookup in intensive called function, what about
```
int idx = d->lastActivated. | |||||
@anthonyfieroni d->lastActivated is a QHash, so your suggestion does even build. OTOH, using iterators will do it. pino: @anthonyfieroni `d->lastActivated` is a QHash, so your suggestion does even build. OTOH, using… | |||||
656 | } | 676 | } | ||
657 | 677 | | |||
658 | return QVariant(); | 678 | return QVariant(); | ||
659 | } | 679 | } | ||
660 | 680 | | |||
661 | int XWindowTasksModel::rowCount(const QModelIndex &parent) const | 681 | int XWindowTasksModel::rowCount(const QModelIndex &parent) const | ||
662 | { | 682 | { | ||
663 | return parent.isValid() ? 0 : d->windows.count(); | 683 | return parent.isValid() ? 0 : d->windows.count(); | ||
▲ Show 20 Lines • Show All 433 Lines • Show Last 20 Lines |
if (rowCount > 0) {
}
otherwise you emit data changed for an invalid index. I think it could happen as stacking order includes some windows not listed here and we have the xwindowsystemeventbatcher