Create a dedicated X11Filter for Client sync events and move it to X11 platform

Summary:
On Wayland we have the sync disabled as it doesn't work properly. This
allows us to also move the sync event handling into the X11 standalone
platform.

The code is slightly refactored: instead of passing the event to each
Client, we search for the matching Client. For that the SyncAlaram struct
is added to public section of Client. The method to handle the sync
doesn't need the event any more and is moved from events.cpp to
client.cpp.

Test Plan:
Run Xephyr+kwin_x11, resized a window and verified through
gdb breakpoint that the sync still works

Reviewers: #kwin, #plasma

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D7942
This commit is contained in:
Martin Flöser 2017-09-22 20:35:50 +02:00
parent 8f4b6a8973
commit 2e868c50df
8 changed files with 128 additions and 34 deletions

View file

@ -2155,5 +2155,20 @@ void Client::checkApplicationMenuObjectPath()
readApplicationMenuObjectPath(property);
}
void Client::handleSync()
{
setReadyForPainting();
setupWindowManagementInterface();
syncRequest.isPending = false;
if (syncRequest.failsafeTimeout)
syncRequest.failsafeTimeout->stop();
if (isResize()) {
if (syncRequest.timeout)
syncRequest.timeout->stop();
performMoveResize();
} else // setReadyForPainting does as well, but there's a small chance for resize syncs after the resize ended
addRepaintFull();
}
} // namespace

View file

@ -43,8 +43,6 @@ class QTimer;
class KStartupInfoData;
class KStartupInfoId;
struct xcb_sync_alarm_notify_event_t;
namespace KWin
{
@ -121,7 +119,6 @@ public:
QPoint inputPos() const { return input_offset; } // Inside of geometry()
bool windowEvent(xcb_generic_event_t *e);
void syncEvent(xcb_sync_alarm_notify_event_t* e);
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
bool manage(xcb_window_t w, bool isMapped);
@ -336,6 +333,19 @@ public:
void readApplicationMenuObjectPath(Xcb::StringProperty &property);
void checkApplicationMenuObjectPath();
struct SyncRequest {
xcb_sync_counter_t counter;
xcb_sync_int64_t value;
xcb_sync_alarm_t alarm;
xcb_timestamp_t lastTimestamp;
QTimer *timeout, *failsafeTimeout;
bool isPending;
};
const SyncRequest &getSyncRequest() const {
return syncRequest;
}
void handleSync();
static void cleanupX11();
public Q_SLOTS:
@ -563,14 +573,7 @@ private:
NET::Actions allowed_actions;
QSize client_size;
bool shade_geometry_change;
struct {
xcb_sync_counter_t counter;
xcb_sync_int64_t value;
xcb_sync_alarm_t alarm;
xcb_timestamp_t lastTimestamp;
QTimer *timeout, *failsafeTimeout;
bool isPending;
} syncRequest;
SyncRequest syncRequest;
static bool check_active_modal; ///< \see Client::checkActiveModal()
int sm_stacking_order;
friend struct ResetupRulesProcedure;

View file

@ -386,12 +386,6 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
case XCB_FOCUS_OUT:
return true; // always eat these, they would tell Qt that KWin is the active app
default:
if (eventType == Xcb::Extensions::self()->syncAlarmNotifyEvent() && Xcb::Extensions::self()->isSyncAvailable()) {
for (Client *c : clients)
c->syncEvent(reinterpret_cast< xcb_sync_alarm_notify_event_t* >(e));
for (Client *c : desktops)
c->syncEvent(reinterpret_cast< xcb_sync_alarm_notify_event_t* >(e));
}
break;
}
return false;
@ -1223,23 +1217,6 @@ void Client::keyPressEvent(uint key_code, xcb_timestamp_t time)
AbstractClient::keyPressEvent(key_code);
}
void Client::syncEvent(xcb_sync_alarm_notify_event_t* e)
{
if (e->alarm == syncRequest.alarm && e->counter_value.hi == syncRequest.value.hi && e->counter_value.lo == syncRequest.value.lo) {
setReadyForPainting();
setupWindowManagementInterface();
syncRequest.isPending = false;
if (syncRequest.failsafeTimeout)
syncRequest.failsafeTimeout->stop();
if (isResize()) {
if (syncRequest.timeout)
syncRequest.timeout->stop();
performMoveResize();
} else // setReadyForPainting does as well, but there's a small chance for resize syncs after the resize ended
addRepaintFull();
}
}
// ****************************************
// Unmanaged
// ****************************************

View file

@ -12,6 +12,7 @@ set(X11PLATFORM_SOURCES
xfixes_cursor_event_filter.cpp
effects_x11.cpp
effects_mouse_interception_x11_filter.cpp
sync_filter.cpp
)
if(X11_Xinput_FOUND)

View file

@ -0,0 +1,48 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2017 Martin Flöser <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "sync_filter.h"
#include "client.h"
#include "workspace.h"
#include "xcbutils.h"
namespace KWin
{
SyncFilter::SyncFilter()
: X11EventFilter(QVector<int>{Xcb::Extensions::self()->syncAlarmNotifyEvent()})
{
}
bool SyncFilter::event(xcb_generic_event_t *event)
{
auto e = reinterpret_cast< xcb_sync_alarm_notify_event_t* >(event);
auto client = workspace()->findClient(
[e] (const Client *c) {
const auto syncRequest = c->getSyncRequest();
return e->alarm == syncRequest.alarm && e->counter_value.hi == syncRequest.value.hi && e->counter_value.lo == syncRequest.value.lo;
}
);
if (client) {
client->handleSync();
}
return false;
}
}

View file

@ -0,0 +1,38 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2017 Martin Flöser <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SYNC_FILTER_H
#define KWIN_SYNC_FILTER_H
#include "x11eventfilter.h"
namespace KWin
{
class X11Cursor;
class SyncFilter : public X11EventFilter
{
public:
explicit SyncFilter();
bool event(xcb_generic_event_t *event) override;
};
}
#endif

View file

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "x11_platform.h"
#include "x11cursor.h"
#include "edge.h"
#include "sync_filter.h"
#include "windowselector.h"
#include <config-kwin.h>
#include <kwinconfig.h>
@ -70,6 +71,13 @@ X11StandalonePlatform::X11StandalonePlatform(QObject *parent)
}
}
#endif
connect(kwinApp(), &Application::workspaceCreated, this,
[this] {
if (Xcb::Extensions::self()->isSyncAvailable()) {
m_syncFilter = std::make_unique<SyncFilter>();
}
}
);
}
X11StandalonePlatform::~X11StandalonePlatform()

View file

@ -25,8 +25,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QObject>
#include <memory>
namespace KWin
{
class SyncFilter;
class XInputIntegration;
class WindowSelector;
class X11EventFilter;
@ -89,6 +92,7 @@ private:
Display *m_x11Display;
QScopedPointer<WindowSelector> m_windowSelector;
QScopedPointer<X11EventFilter> m_screenEdgesFilter;
std::unique_ptr<SyncFilter> m_syncFilter;
};