diff --git a/client.h b/client.h --- a/client.h +++ b/client.h @@ -43,8 +43,6 @@ class KStartupInfoData; class KStartupInfoId; -struct xcb_sync_alarm_notify_event_t; - namespace KWin { @@ -121,7 +119,6 @@ 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 @@ 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 @@ 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; diff --git a/client.cpp b/client.cpp --- a/client.cpp +++ b/client.cpp @@ -2155,5 +2155,20 @@ 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 diff --git a/events.cpp b/events.cpp --- a/events.cpp +++ b/events.cpp @@ -386,12 +386,6 @@ 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 @@ 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 // **************************************** diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt --- a/plugins/platforms/x11/standalone/CMakeLists.txt +++ b/plugins/platforms/x11/standalone/CMakeLists.txt @@ -12,6 +12,7 @@ xfixes_cursor_event_filter.cpp effects_x11.cpp effects_mouse_interception_x11_filter.cpp + sync_filter.cpp ) if(X11_Xinput_FOUND) diff --git a/plugins/platforms/x11/standalone/sync_filter.h b/plugins/platforms/x11/standalone/sync_filter.h new file mode 100644 --- /dev/null +++ b/plugins/platforms/x11/standalone/sync_filter.h @@ -0,0 +1,38 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2017 Martin Flöser + +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 . +*********************************************************************/ +#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 diff --git a/plugins/platforms/x11/standalone/sync_filter.cpp b/plugins/platforms/x11/standalone/sync_filter.cpp new file mode 100644 --- /dev/null +++ b/plugins/platforms/x11/standalone/sync_filter.cpp @@ -0,0 +1,48 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2017 Martin Flöser + +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 . +*********************************************************************/ +#include "sync_filter.h" +#include "client.h" +#include "workspace.h" +#include "xcbutils.h" + +namespace KWin +{ + +SyncFilter::SyncFilter() + : X11EventFilter(QVector{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; +} + +} diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -25,8 +25,11 @@ #include +#include + namespace KWin { +class SyncFilter; class XInputIntegration; class WindowSelector; class X11EventFilter; @@ -89,6 +92,7 @@ Display *m_x11Display; QScopedPointer m_windowSelector; QScopedPointer m_screenEdgesFilter; + std::unique_ptr m_syncFilter; }; diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -20,6 +20,7 @@ #include "x11_platform.h" #include "x11cursor.h" #include "edge.h" +#include "sync_filter.h" #include "windowselector.h" #include #include @@ -70,6 +71,13 @@ } } #endif + connect(kwinApp(), &Application::workspaceCreated, this, + [this] { + if (Xcb::Extensions::self()->isSyncAvailable()) { + m_syncFilter = std::make_unique(); + } + } + ); } X11StandalonePlatform::~X11StandalonePlatform()