[libtaskmanager/x11] Fix transient windows bug

The logic for handling the active window when it is a transient, added in
https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/509, had
a bug (fixed in 67003f740888fa9d1bcee60cd28ce9a862d2452a).

This reworks the implementation and actually makes the original feature work
(a signal also wasn't properly handled).

BUG: 438222
FIXED-IN: 5.22.1


(cherry picked from commit 7573ae03ac)
wilder-5.22
Henri Chain 5 years ago committed by Nate Graham
parent 924bdf5e27
commit 2a1f9e4489
  1. 39
      libtaskmanager/xwindowtasksmodel.cpp

@ -56,8 +56,12 @@ public:
~Private();
QVector<WId> windows;
QMultiHash<WId, WId> transients;
// key=transient child, value=leader
QHash<WId, WId> transients;
// key=leader, values=transient children
QMultiHash<WId, WId> transientsDemandingAttention;
QHash<WId, KWindowInfo *> windowInfoCache;
QHash<WId, AppData> appDataCache;
QHash<WId, QRect> delegateGeometries;
@ -172,6 +176,12 @@ void XWindowTasksModel::Private::init()
// Update IsActive for previously- and newly-active windows.
QObject::connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, q, [this](WId window) {
const WId oldActiveWindow = activeWindow;
const auto leader = transients.value(window, XCB_WINDOW_NONE);
if (leader != XCB_WINDOW_NONE) {
window = leader;
}
activeWindow = window;
lastActivated[activeWindow] = QTime::currentTime();
@ -216,8 +226,8 @@ void XWindowTasksModel::Private::addWindow(WId window)
const WId leader = info.transientFor();
// Handle transient.
if (leader > 0 && leader != window && leader != QX11Info::appRootWindow() && !transients.values().contains(window) && windows.contains(leader)) {
transients.insert(leader, window);
if (leader > 0 && leader != window && leader != QX11Info::appRootWindow() && !transients.contains(window) && windows.contains(leader)) {
transients.insert(window, leader);
// Update demands attention state for leader.
if (info.hasState(NET::DemandsAttention) && windows.contains(leader)) {
@ -255,10 +265,8 @@ void XWindowTasksModel::Private::removeWindow(WId window)
q->endRemoveRows();
} else { // Could be a transient.
// Removing a transient might change the demands attention state of the leader.
WId leader = transients.key(window, XCB_WINDOW_NONE);
if (leader != XCB_WINDOW_NONE) {
transients.remove(leader, window);
leader = transientsDemandingAttention.key(window, XCB_WINDOW_NONE);
if (transients.remove(window)) {
const WId leader = transientsDemandingAttention.key(window, XCB_WINDOW_NONE);
if (leader != XCB_WINDOW_NONE) {
transientsDemandingAttention.remove(leader, window);
@ -316,7 +324,6 @@ void XWindowTasksModel::Private::windowChanged(WId window, NET::Properties prope
{
if (transients.contains(window)) {
transientChanged(window, properties, properties2);
return;
}
@ -629,15 +636,7 @@ QVariant XWindowTasksModel::data(const QModelIndex &index, int role) const
} else if (role == IsWindow) {
return true;
} else if (role == IsActive) {
if (window == d->activeWindow) {
return true;
}
for (const WId transient : d->transients.values(window)) {
if (transient == d->activeWindow) {
return true;
}
}
return false;
return (window == d->activeWindow);
} else if (role == IsClosable) {
return d->windowInfo(window)->actionSupported(NET::ActionClose);
} else if (role == IsMovable) {
@ -729,10 +728,10 @@ void XWindowTasksModel::requestActivate(const QModelIndex &index)
// dialog and trying to bring the window forward by clicking on it in a tasks widget
// TODO: do we need to check all the transients for shaded?"
} else if (!d->transients.isEmpty()) {
foreach (const WId transient, d->transients) {
const auto transients = d->transients.keys(window);
for (const auto transient : qAsConst(transients)) {
KWindowInfo info(transient, NET::WMState, NET::WM2TransientFor);
if (info.valid(true) && info.hasState(NET::Shaded) && info.transientFor() == window) {
if (info.valid(true) && info.hasState(NET::Shaded)) {
window = transient;
break;
}

Loading…
Cancel
Save