diff --git a/autotests/netwininfotestwm.cpp b/autotests/netwininfotestwm.cpp --- a/autotests/netwininfotestwm.cpp +++ b/autotests/netwininfotestwm.cpp @@ -437,6 +437,7 @@ const QByteArray fullScreen = QByteArrayLiteral("_NET_WM_STATE_FULLSCREEN"); const QByteArray keepBelow = QByteArrayLiteral("_NET_WM_STATE_BELOW"); const QByteArray demandsAttention = QByteArrayLiteral("_NET_WM_STATE_DEMANDS_ATTENTION"); + const QByteArray focused = QByteArrayLiteral("_NET_WM_STATE_FOCUSED"); QTest::newRow("modal") << NET::States(NET::Modal) << (QVector() << modal); QTest::newRow("sticky") << NET::States(NET::Sticky) << (QVector() << sticky); @@ -452,6 +453,7 @@ QTest::newRow("keepBelow") << NET::States(NET::KeepBelow) << (QVector() << keepBelow); QTest::newRow("demandsAttention") << NET::States(NET::DemandsAttention) << (QVector() << demandsAttention); QTest::newRow("skipSwitcher") << NET::States(NET::SkipSwitcher) << (QVector() << skipSwitcher); + QTest::newRow("focused") << NET::States(NET::Focused) << (QVector() << focused); // TODO: it's possible to be keep above and below at the same time?!? QTest::newRow("all") << NET::States(NET::Modal | @@ -465,11 +467,12 @@ NET::Hidden | NET::FullScreen | NET::DemandsAttention | - NET::SkipSwitcher) + NET::SkipSwitcher | + NET::Focused) << (QVector() << modal << sticky << maxVert << maxHoriz << shaded << skipTaskbar << keepAbove << skipPager << hidden << fullScreen - << keepBelow << demandsAttention << staysOnTop << skipSwitcher); + << keepBelow << demandsAttention << staysOnTop << skipSwitcher << focused); } void NetWinInfoTestWM::testState() diff --git a/src/netwm_def.h b/src/netwm_def.h --- a/src/netwm_def.h +++ b/src/netwm_def.h @@ -499,7 +499,13 @@ @since 5.45 **/ - SkipSwitcher = 1u << 12 + SkipSwitcher = 1u << 12, + /** + indicates that a client should render as though it has focus + Only the window manager is allowed to change it. + @since 5.58 + **/ + Focused = 1u << 13, }; Q_DECLARE_FLAGS(States, State) diff --git a/src/platforms/xcb/atoms_p.h b/src/platforms/xcb/atoms_p.h --- a/src/platforms/xcb/atoms_p.h +++ b/src/platforms/xcb/atoms_p.h @@ -133,6 +133,7 @@ ENUM(_NET_WM_STATE_ABOVE), ENUM(_NET_WM_STATE_BELOW), ENUM(_NET_WM_STATE_DEMANDS_ATTENTION), + ENUM(_NET_WM_STATE_FOCUSED), // KDE-specific atom ENUM(_KDE_NET_WM_STATE_SKIP_SWITCHER), diff --git a/src/platforms/xcb/netwm.cpp b/src/platforms/xcb/netwm.cpp --- a/src/platforms/xcb/netwm.cpp +++ b/src/platforms/xcb/netwm.cpp @@ -1025,6 +1025,9 @@ if (p->states & StaysOnTop) { atoms[pnum++] = p->atom(_NET_WM_STATE_STAYS_ON_TOP); } + if (p->states & Focused) { + atoms[pnum++] = p->atom(_NET_WM_STATE_FOCUSED); + } } if (p->properties & WMStrut) { @@ -1331,10 +1334,10 @@ p->states |= KeepBelow; } else if (atom == p->atom(_NET_WM_STATE_DEMANDS_ATTENTION)) { p->states |= DemandsAttention; - } - - else if (atom == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) { + } else if (atom == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) { p->states |= StaysOnTop; + } else if (atom == p->atom(_NET_WM_STATE_FOCUSED)) { + p->states |= Focused; } else if (atom == p->atom(_NET_WM_STRUT)) { @@ -3035,6 +3038,7 @@ xcb_send_event(p->conn, false, p->root, netwm_sendevent_mask, (const char *) &event); } + //Focused is not added here as it is effectively "read only" set by the WM, a client setting it would be silly } else { p->state &= ~mask; p->state |= state; @@ -3064,6 +3068,9 @@ if (p->state & DemandsAttention) { data[count++] = p->atom(_NET_WM_STATE_DEMANDS_ATTENTION); } + if (p->state & Focused) { + data[count++] = p->atom(_NET_WM_STATE_FOCUSED); + } // Policy if (p->state & KeepAbove) { @@ -3664,6 +3671,8 @@ mask |= DemandsAttention; } else if ((xcb_atom_t) message->data.data32[i] == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) { mask |= StaysOnTop; + } else if ((xcb_atom_t) message->data.data32[i] == p->atom(_NET_WM_STATE_FOCUSED)) { + mask |= Focused; } } @@ -4088,6 +4097,10 @@ else if (state == p->atom(_NET_WM_STATE_STAYS_ON_TOP)) { p->state |= StaysOnTop; } + + else if (state == p->atom(_NET_WM_STATE_FOCUSED)) { + p->state |= Focused; + } } }