x11: Move event filter logic to kwinApp()
This allows the X11 platform plugin to create event filters before the workspace object is created.
This commit is contained in:
parent
7c55f5ed7d
commit
9e999fe2a1
6 changed files with 158 additions and 151 deletions
117
src/events.cpp
117
src/events.cpp
|
@ -141,129 +141,12 @@ static xcb_window_t findEventWindow(xcb_generic_event_t *event)
|
|||
}
|
||||
}
|
||||
|
||||
QVector<QByteArray> s_xcbEerrors({
|
||||
QByteArrayLiteral("Success"),
|
||||
QByteArrayLiteral("BadRequest"),
|
||||
QByteArrayLiteral("BadValue"),
|
||||
QByteArrayLiteral("BadWindow"),
|
||||
QByteArrayLiteral("BadPixmap"),
|
||||
QByteArrayLiteral("BadAtom"),
|
||||
QByteArrayLiteral("BadCursor"),
|
||||
QByteArrayLiteral("BadFont"),
|
||||
QByteArrayLiteral("BadMatch"),
|
||||
QByteArrayLiteral("BadDrawable"),
|
||||
QByteArrayLiteral("BadAccess"),
|
||||
QByteArrayLiteral("BadAlloc"),
|
||||
QByteArrayLiteral("BadColor"),
|
||||
QByteArrayLiteral("BadGC"),
|
||||
QByteArrayLiteral("BadIDChoice"),
|
||||
QByteArrayLiteral("BadName"),
|
||||
QByteArrayLiteral("BadLength"),
|
||||
QByteArrayLiteral("BadImplementation"),
|
||||
QByteArrayLiteral("Unknown")});
|
||||
|
||||
|
||||
void Workspace::registerEventFilter(X11EventFilter *filter)
|
||||
{
|
||||
if (filter->isGenericEvent()) {
|
||||
m_genericEventFilters.append(new X11EventFilterContainer(filter));
|
||||
} else {
|
||||
m_eventFilters.append(new X11EventFilterContainer(filter));
|
||||
}
|
||||
}
|
||||
|
||||
static X11EventFilterContainer *takeEventFilter(X11EventFilter *eventFilter,
|
||||
QList<QPointer<X11EventFilterContainer>> &list)
|
||||
{
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
X11EventFilterContainer *container = list.at(i);
|
||||
if (container->filter() == eventFilter) {
|
||||
return list.takeAt(i);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Workspace::unregisterEventFilter(X11EventFilter *filter)
|
||||
{
|
||||
X11EventFilterContainer *container = nullptr;
|
||||
if (filter->isGenericEvent()) {
|
||||
container = takeEventFilter(filter, m_genericEventFilters);
|
||||
} else {
|
||||
container = takeEventFilter(filter, m_eventFilters);
|
||||
}
|
||||
delete container;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles workspace specific XCB event
|
||||
*/
|
||||
bool Workspace::workspaceEvent(xcb_generic_event_t *e)
|
||||
{
|
||||
const uint8_t eventType = e->response_type & ~0x80;
|
||||
if (!eventType) {
|
||||
// let's check whether it's an error from one of the extensions KWin uses
|
||||
xcb_generic_error_t *error = reinterpret_cast<xcb_generic_error_t*>(e);
|
||||
const QVector<Xcb::ExtensionData> extensions = Xcb::Extensions::self()->extensions();
|
||||
for (const auto &extension : extensions) {
|
||||
if (error->major_code == extension.majorOpcode) {
|
||||
QByteArray errorName;
|
||||
if (error->error_code < s_xcbEerrors.size()) {
|
||||
errorName = s_xcbEerrors.at(error->error_code);
|
||||
} else if (error->error_code >= extension.errorBase) {
|
||||
const int index = error->error_code - extension.errorBase;
|
||||
if (index >= 0 && index < extension.errorCodes.size()) {
|
||||
errorName = extension.errorCodes.at(index);
|
||||
}
|
||||
}
|
||||
if (errorName.isEmpty()) {
|
||||
errorName = QByteArrayLiteral("Unknown");
|
||||
}
|
||||
qCWarning(KWIN_CORE, "XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d (%s)",
|
||||
int(error->error_code), errorName.constData(),
|
||||
int(error->sequence), int(error->resource_id),
|
||||
int(error->major_code), extension.name.constData(),
|
||||
int(error->minor_code),
|
||||
extension.opCodes.size() > error->minor_code ? extension.opCodes.at(error->minor_code).constData() : "Unknown");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eventType == XCB_GE_GENERIC) {
|
||||
xcb_ge_generic_event_t *ge = reinterpret_cast<xcb_ge_generic_event_t *>(e);
|
||||
|
||||
// We need to make a shadow copy of the event filter list because an activated event
|
||||
// filter may mutate it by removing or installing another event filter.
|
||||
const auto eventFilters = m_genericEventFilters;
|
||||
|
||||
for (X11EventFilterContainer *container : eventFilters) {
|
||||
if (!container) {
|
||||
continue;
|
||||
}
|
||||
X11EventFilter *filter = container->filter();
|
||||
if (filter->extension() == ge->extension && filter->genericEventTypes().contains(ge->event_type) && filter->event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We need to make a shadow copy of the event filter list because an activated event
|
||||
// filter may mutate it by removing or installing another event filter.
|
||||
const auto eventFilters = m_eventFilters;
|
||||
|
||||
for (X11EventFilterContainer *container : eventFilters) {
|
||||
if (!container) {
|
||||
continue;
|
||||
}
|
||||
X11EventFilter *filter = container->filter();
|
||||
if (filter->eventTypes().contains(eventType) && filter->event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (effects && static_cast< EffectsHandlerImpl* >(effects)->hasKeyboardGrab()
|
||||
&& (eventType == XCB_KEY_PRESS || eventType == XCB_KEY_RELEASE))
|
||||
return false; // let Qt process it, it'll be intercepted again in eventFilter()
|
||||
|
|
141
src/main.cpp
141
src/main.cpp
|
@ -25,6 +25,7 @@
|
|||
#include "screenlockerwatcher.h"
|
||||
#include "sm.h"
|
||||
#include "workspace.h"
|
||||
#include "x11eventfilter.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <kwineffects.h>
|
||||
|
@ -357,6 +358,134 @@ void Application::destroyColorManager()
|
|||
#endif
|
||||
}
|
||||
|
||||
void Application::registerEventFilter(X11EventFilter *filter)
|
||||
{
|
||||
if (filter->isGenericEvent()) {
|
||||
m_genericEventFilters.append(new X11EventFilterContainer(filter));
|
||||
} else {
|
||||
m_eventFilters.append(new X11EventFilterContainer(filter));
|
||||
}
|
||||
}
|
||||
|
||||
static X11EventFilterContainer *takeEventFilter(X11EventFilter *eventFilter,
|
||||
QList<QPointer<X11EventFilterContainer>> &list)
|
||||
{
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
X11EventFilterContainer *container = list.at(i);
|
||||
if (container->filter() == eventFilter) {
|
||||
return list.takeAt(i);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Application::unregisterEventFilter(X11EventFilter *filter)
|
||||
{
|
||||
X11EventFilterContainer *container = nullptr;
|
||||
if (filter->isGenericEvent()) {
|
||||
container = takeEventFilter(filter, m_genericEventFilters);
|
||||
} else {
|
||||
container = takeEventFilter(filter, m_eventFilters);
|
||||
}
|
||||
delete container;
|
||||
}
|
||||
|
||||
bool Application::dispatchEvent(xcb_generic_event_t *event)
|
||||
{
|
||||
static const QVector<QByteArray> s_xcbEerrors({
|
||||
QByteArrayLiteral("Success"),
|
||||
QByteArrayLiteral("BadRequest"),
|
||||
QByteArrayLiteral("BadValue"),
|
||||
QByteArrayLiteral("BadWindow"),
|
||||
QByteArrayLiteral("BadPixmap"),
|
||||
QByteArrayLiteral("BadAtom"),
|
||||
QByteArrayLiteral("BadCursor"),
|
||||
QByteArrayLiteral("BadFont"),
|
||||
QByteArrayLiteral("BadMatch"),
|
||||
QByteArrayLiteral("BadDrawable"),
|
||||
QByteArrayLiteral("BadAccess"),
|
||||
QByteArrayLiteral("BadAlloc"),
|
||||
QByteArrayLiteral("BadColor"),
|
||||
QByteArrayLiteral("BadGC"),
|
||||
QByteArrayLiteral("BadIDChoice"),
|
||||
QByteArrayLiteral("BadName"),
|
||||
QByteArrayLiteral("BadLength"),
|
||||
QByteArrayLiteral("BadImplementation"),
|
||||
QByteArrayLiteral("Unknown")
|
||||
});
|
||||
|
||||
kwinApp()->updateX11Time(event);
|
||||
|
||||
const uint8_t x11EventType = event->response_type & ~0x80;
|
||||
if (!x11EventType) {
|
||||
// let's check whether it's an error from one of the extensions KWin uses
|
||||
xcb_generic_error_t *error = reinterpret_cast<xcb_generic_error_t*>(event);
|
||||
const QVector<Xcb::ExtensionData> extensions = Xcb::Extensions::self()->extensions();
|
||||
for (const auto &extension : extensions) {
|
||||
if (error->major_code == extension.majorOpcode) {
|
||||
QByteArray errorName;
|
||||
if (error->error_code < s_xcbEerrors.size()) {
|
||||
errorName = s_xcbEerrors.at(error->error_code);
|
||||
} else if (error->error_code >= extension.errorBase) {
|
||||
const int index = error->error_code - extension.errorBase;
|
||||
if (index >= 0 && index < extension.errorCodes.size()) {
|
||||
errorName = extension.errorCodes.at(index);
|
||||
}
|
||||
}
|
||||
if (errorName.isEmpty()) {
|
||||
errorName = QByteArrayLiteral("Unknown");
|
||||
}
|
||||
qCWarning(KWIN_CORE, "XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d (%s)",
|
||||
int(error->error_code), errorName.constData(),
|
||||
int(error->sequence), int(error->resource_id),
|
||||
int(error->major_code), extension.name.constData(),
|
||||
int(error->minor_code),
|
||||
extension.opCodes.size() > error->minor_code ? extension.opCodes.at(error->minor_code).constData() : "Unknown");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x11EventType == XCB_GE_GENERIC) {
|
||||
xcb_ge_generic_event_t *ge = reinterpret_cast<xcb_ge_generic_event_t *>(event);
|
||||
|
||||
// We need to make a shadow copy of the event filter list because an activated event
|
||||
// filter may mutate it by removing or installing another event filter.
|
||||
const auto eventFilters = m_genericEventFilters;
|
||||
|
||||
for (X11EventFilterContainer *container : eventFilters) {
|
||||
if (!container) {
|
||||
continue;
|
||||
}
|
||||
X11EventFilter *filter = container->filter();
|
||||
if (filter->extension() == ge->extension && filter->genericEventTypes().contains(ge->event_type) && filter->event(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We need to make a shadow copy of the event filter list because an activated event
|
||||
// filter may mutate it by removing or installing another event filter.
|
||||
const auto eventFilters = m_eventFilters;
|
||||
|
||||
for (X11EventFilterContainer *container : eventFilters) {
|
||||
if (!container) {
|
||||
continue;
|
||||
}
|
||||
X11EventFilter *filter = container->filter();
|
||||
if (filter->eventTypes().contains(x11EventType) && filter->event(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (workspace()) {
|
||||
return workspace()->workspaceEvent(event);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Application::updateX11Time(xcb_generic_event_t *event)
|
||||
{
|
||||
xcb_timestamp_t time = XCB_TIME_CURRENT_TIME;
|
||||
|
@ -434,16 +563,10 @@ void Application::updateX11Time(xcb_generic_event_t *event)
|
|||
bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
|
||||
{
|
||||
Q_UNUSED(result)
|
||||
if (eventType != "xcb_generic_event_t") {
|
||||
return false;
|
||||
if (eventType == "xcb_generic_event_t") {
|
||||
return kwinApp()->dispatchEvent(static_cast<xcb_generic_event_t *>(message));
|
||||
}
|
||||
auto event = static_cast<xcb_generic_event_t *>(message);
|
||||
kwinApp()->updateX11Time(event);
|
||||
if (!Workspace::self()) {
|
||||
// Workspace not yet created
|
||||
return false;
|
||||
}
|
||||
return Workspace::self()->workspaceEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool s_useLibinput = false;
|
||||
|
|
20
src/main.h
20
src/main.h
|
@ -27,6 +27,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
class Platform;
|
||||
class X11EventFilter;
|
||||
|
||||
class XcbEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
|
@ -34,6 +35,19 @@ public:
|
|||
bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override;
|
||||
};
|
||||
|
||||
class X11EventFilterContainer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit X11EventFilterContainer(X11EventFilter *filter);
|
||||
|
||||
X11EventFilter *filter() const;
|
||||
|
||||
private:
|
||||
X11EventFilter *m_filter;
|
||||
};
|
||||
|
||||
class KWIN_EXPORT Application : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -96,6 +110,10 @@ public:
|
|||
void setupCommandLine(QCommandLineParser *parser);
|
||||
void processCommandLine(QCommandLineParser *parser);
|
||||
|
||||
void registerEventFilter(X11EventFilter *filter);
|
||||
void unregisterEventFilter(X11EventFilter *filter);
|
||||
bool dispatchEvent(xcb_generic_event_t *event);
|
||||
|
||||
xcb_timestamp_t x11Time() const {
|
||||
return m_x11Time;
|
||||
}
|
||||
|
@ -255,6 +273,8 @@ protected:
|
|||
static int crashes;
|
||||
|
||||
private:
|
||||
QList<QPointer<X11EventFilterContainer>> m_eventFilters;
|
||||
QList<QPointer<X11EventFilterContainer>> m_genericEventFilters;
|
||||
QScopedPointer<XcbEventFilter> m_eventFilter;
|
||||
bool m_configLock;
|
||||
KSharedConfigPtr m_config;
|
||||
|
|
|
@ -194,6 +194,7 @@ void ApplicationX11::lostSelection()
|
|||
destroyWorkspace();
|
||||
// Remove windowmanager privileges
|
||||
Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE);
|
||||
removeNativeX11EventFilter();
|
||||
quit();
|
||||
}
|
||||
|
||||
|
|
|
@ -56,19 +56,6 @@ class X11Client;
|
|||
class X11EventFilter;
|
||||
enum class Predicate;
|
||||
|
||||
class X11EventFilterContainer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit X11EventFilterContainer(X11EventFilter *filter);
|
||||
|
||||
X11EventFilter *filter() const;
|
||||
|
||||
private:
|
||||
X11EventFilter *m_filter;
|
||||
};
|
||||
|
||||
class KWIN_EXPORT Workspace : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -384,10 +371,6 @@ public:
|
|||
* @returns Whether we have a Compositor and it is active (Scene created)
|
||||
*/
|
||||
bool compositing() const;
|
||||
|
||||
void registerEventFilter(X11EventFilter *filter);
|
||||
void unregisterEventFilter(X11EventFilter *filter);
|
||||
|
||||
void markXStackingOrderAsDirty();
|
||||
|
||||
void quickTileWindow(QuickTileMode mode);
|
||||
|
@ -669,9 +652,6 @@ private:
|
|||
friend class StackingUpdatesBlocker;
|
||||
|
||||
QScopedPointer<KillWindow> m_windowKiller;
|
||||
|
||||
QList<QPointer<X11EventFilterContainer>> m_eventFilters;
|
||||
QList<QPointer<X11EventFilterContainer>> m_genericEventFilters;
|
||||
QScopedPointer<X11EventFilter> m_movingClientFilter;
|
||||
QScopedPointer<X11EventFilter> m_syncAlarmFilter;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
#include "x11eventfilter.h"
|
||||
#include <workspace.h>
|
||||
#include "main.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ X11EventFilter::X11EventFilter(const QVector<int> &eventTypes)
|
|||
: m_eventTypes(eventTypes)
|
||||
, m_extension(0)
|
||||
{
|
||||
Workspace::self()->registerEventFilter(this);
|
||||
kwinApp()->registerEventFilter(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,13 +29,13 @@ X11EventFilter::X11EventFilter(int eventType, int opcode, int genericEventType)
|
|||
X11EventFilter::X11EventFilter(int eventType, int opcode, const QVector< int > &genericEventTypes)
|
||||
: m_eventTypes(QVector<int>{eventType}), m_extension(opcode), m_genericEventTypes(genericEventTypes)
|
||||
{
|
||||
Workspace::self()->registerEventFilter(this);
|
||||
kwinApp()->registerEventFilter(this);
|
||||
}
|
||||
|
||||
X11EventFilter::~X11EventFilter()
|
||||
{
|
||||
if (auto w = Workspace::self()) {
|
||||
w->unregisterEventFilter(this);
|
||||
if (kwinApp()) {
|
||||
kwinApp()->unregisterEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue