wayland: Fix activation when activating surfaces disappear
We track when the user last interacted with a window so that we can decide on the relevance of newly activated windows. Fixes network/neochat#524
This commit is contained in:
parent
e6d2bc153f
commit
f3ec05c85a
5 changed files with 91 additions and 3 deletions
|
@ -2635,6 +2635,64 @@ void InputRedirection::setLastInputHandler(QObject *device)
|
||||||
m_lastInputDevice = device;
|
m_lastInputDevice = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WindowInteractedSpy : public InputEventSpy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void keyEvent(KeyEvent *event) override
|
||||||
|
{
|
||||||
|
if (event->isAutoRepeat() || event->type() != QEvent::KeyPress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointerEvent(KWin::MouseEvent *event) override
|
||||||
|
{
|
||||||
|
if (event->type() != QEvent::MouseButtonPress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabletPadButtonEvent(uint, bool pressed, const KWin::TabletPadId &) override
|
||||||
|
{
|
||||||
|
if (!pressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabletToolButtonEvent(uint, bool pressed, const KWin::TabletToolId &) override
|
||||||
|
{
|
||||||
|
if (!pressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabletToolEvent(KWin::TabletEvent *event) override
|
||||||
|
{
|
||||||
|
if (event->type() != QEvent::TabletPress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void touchDown(qint32, const QPointF &, quint32) override
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
auto window = workspace()->activeWindow();
|
||||||
|
if (!window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window->setLastUsageSerial(waylandServer()->seat()->display()->serial());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class UserActivitySpy : public InputEventSpy
|
class UserActivitySpy : public InputEventSpy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -2793,6 +2851,7 @@ void InputRedirection::setupInputFilters()
|
||||||
}
|
}
|
||||||
installInputEventSpy(new HideCursorSpy);
|
installInputEventSpy(new HideCursorSpy);
|
||||||
installInputEventSpy(new UserActivitySpy);
|
installInputEventSpy(new UserActivitySpy);
|
||||||
|
installInputEventSpy(new WindowInteractedSpy);
|
||||||
if (hasGlobalShortcutSupport) {
|
if (hasGlobalShortcutSupport) {
|
||||||
installInputEventFilter(new TerminateServerFilter);
|
installInputEventFilter(new TerminateServerFilter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4566,6 +4566,18 @@ void Window::applyWindowRules()
|
||||||
setDesktopFileName(rules()->checkDesktopFile(desktopFileName()).toUtf8());
|
setDesktopFileName(rules()->checkDesktopFile(desktopFileName()).toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::setLastUsageSerial(quint32 serial)
|
||||||
|
{
|
||||||
|
if (m_lastUsageSerial < serial) {
|
||||||
|
m_lastUsageSerial = serial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 Window::lastUsageSerial() const
|
||||||
|
{
|
||||||
|
return m_lastUsageSerial;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
|
|
||||||
#include "moc_window.cpp"
|
#include "moc_window.cpp"
|
||||||
|
|
|
@ -1399,6 +1399,12 @@ public:
|
||||||
*/
|
*/
|
||||||
static QString iconFromDesktopFile(const QString &fileName);
|
static QString iconFromDesktopFile(const QString &fileName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the last user usage serial of the surface as @p serial
|
||||||
|
*/
|
||||||
|
void setLastUsageSerial(quint32 serial);
|
||||||
|
quint32 lastUsageSerial() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
virtual void closeWindow() = 0;
|
virtual void closeWindow() = 0;
|
||||||
|
|
||||||
|
@ -1980,6 +1986,7 @@ private:
|
||||||
QKeySequence _shortcut;
|
QKeySequence _shortcut;
|
||||||
|
|
||||||
WindowRules m_rules;
|
WindowRules m_rules;
|
||||||
|
quint32 m_lastUsageSerial = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,6 +37,15 @@ XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface
|
||||||
if (!m_currentActivationToken || !window || window->property("token").toString() == m_currentActivationToken->token) {
|
if (!m_currentActivationToken || !window || window->property("token").toString() == m_currentActivationToken->token) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We check that it's not the app that we are trying to activate
|
||||||
|
if (window->desktopFileName() != m_currentActivationToken->applicationId) {
|
||||||
|
// But also that the new one has been requested after the token was requested
|
||||||
|
if (window->lastUsageSerial() < m_currentActivationToken->serial) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
});
|
});
|
||||||
activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString {
|
activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString {
|
||||||
|
@ -82,10 +91,10 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons
|
||||||
|
|
||||||
auto ownerWindow = waylandServer()->findWindow(m_currentActivationToken->surface);
|
auto ownerWindow = waylandServer()->findWindow(m_currentActivationToken->surface);
|
||||||
qCDebug(KWIN_CORE) << "activating" << window << surface << "on behalf of" << m_currentActivationToken->surface << "into" << ownerWindow;
|
qCDebug(KWIN_CORE) << "activating" << window << surface << "on behalf of" << m_currentActivationToken->surface << "into" << ownerWindow;
|
||||||
if (ws->activeWindow() == ownerWindow || isPrivilegedInWindowManagement(m_currentActivationToken->client)) {
|
if (ws->activeWindow() == ownerWindow || ws->activeWindow()->lastUsageSerial() < m_currentActivationToken->serial || isPrivilegedInWindowManagement(m_currentActivationToken->client)) {
|
||||||
ws->activateWindow(window);
|
ws->activateWindow(window);
|
||||||
} else {
|
} else {
|
||||||
qCWarning(KWIN_CORE) << "Activation requested while owner isn't active" << ownerWindow->desktopFileName()
|
qCWarning(KWIN_CORE) << "Activation requested while owner isn't active" << (ownerWindow ? ownerWindow->desktopFileName() : "null")
|
||||||
<< m_currentActivationToken->applicationId;
|
<< m_currentActivationToken->applicationId;
|
||||||
window->demandAttention();
|
window->demandAttention();
|
||||||
clear();
|
clear();
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "kwin_export.h"
|
#include "kwin_export.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
namespace KWaylandServer
|
namespace KWaylandServer
|
||||||
|
@ -36,7 +37,7 @@ public:
|
||||||
|
|
||||||
const QString token;
|
const QString token;
|
||||||
const KWaylandServer::ClientConnection *client;
|
const KWaylandServer::ClientConnection *client;
|
||||||
const KWaylandServer::SurfaceInterface *surface;
|
QPointer<const KWaylandServer::SurfaceInterface> surface;
|
||||||
const uint serial;
|
const uint serial;
|
||||||
const KWaylandServer::SeatInterface *seat;
|
const KWaylandServer::SeatInterface *seat;
|
||||||
QString applicationId;
|
QString applicationId;
|
||||||
|
|
Loading…
Reference in a new issue