Libplasma

effectwatcher.cpp
1/*
2 SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "effectwatcher_p.h"
8
9#include <X11/Xlib.h>
10
11namespace Plasma
12{
13EffectWatcher::EffectWatcher(const QString &property, QObject *parent)
14 : QObject(parent)
15 , m_property(XCB_ATOM_NONE)
16 , m_x11Interface(qGuiApp->nativeInterface<QNativeInterface::QX11Application>())
17{
18 init(property);
19}
20
21void EffectWatcher::init(const QString &property)
22{
23 if (!m_x11Interface) {
24 return;
25 }
27
28 xcb_connection_t *c = m_x11Interface->connection();
29 const QByteArray propertyName = property.toLatin1();
30 xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, propertyName.length(), propertyName.constData());
31 xcb_get_window_attributes_cookie_t winAttrCookie = xcb_get_window_attributes_unchecked(c, DefaultRootWindow(m_x11Interface->display()));
32
33 QScopedPointer<xcb_intern_atom_reply_t, QScopedPointerPodDeleter> atom(xcb_intern_atom_reply(c, atomCookie, nullptr));
34 if (!atom.isNull()) {
35 m_property = atom->atom;
36 }
37 m_effectActive = isEffectActive();
38
39 QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> attrs(xcb_get_window_attributes_reply(c, winAttrCookie, nullptr));
40 if (!attrs.isNull()) {
41 uint32_t events = attrs->your_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE;
42 xcb_change_window_attributes(c, DefaultRootWindow(m_x11Interface->display()), XCB_CW_EVENT_MASK, &events);
43 }
44}
45
46bool EffectWatcher::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
47{
48 Q_UNUSED(result);
49 // A faster comparison than eventType != "xcb_generic_event_t"
50 // given that eventType can only have the following values:
51 // "xcb_generic_event_t", "windows_generic_MSG" and "mac_generic_NSEvent"
52 // According to https://doc.qt.io/qt-5/qabstractnativeeventfilter.html
53 if (eventType[0] != 'x') {
54 return false;
55 }
56 xcb_generic_event_t *event = reinterpret_cast<xcb_generic_event_t *>(message);
57 uint response_type = event->response_type & ~0x80;
58 if (response_type != XCB_PROPERTY_NOTIFY || m_property == XCB_ATOM_NONE) {
59 return false;
60 }
61
62 xcb_property_notify_event_t *prop_event = reinterpret_cast<xcb_property_notify_event_t *>(event);
63 if (prop_event->atom == m_property) {
64 bool nowEffectActive = isEffectActive();
65 if (m_effectActive != nowEffectActive) {
66 m_effectActive = nowEffectActive;
67 Q_EMIT effectChanged(m_effectActive);
68 }
69 }
70 return false;
71}
72
73bool EffectWatcher::isEffectActive() const
74{
75 if (m_property == XCB_ATOM_NONE || !m_x11Interface) {
76 return false;
77 }
78 xcb_connection_t *c = m_x11Interface->connection();
79 xcb_list_properties_cookie_t propsCookie = xcb_list_properties_unchecked(c, DefaultRootWindow(m_x11Interface->display()));
80 QScopedPointer<xcb_list_properties_reply_t, QScopedPointerPodDeleter> props(xcb_list_properties_reply(c, propsCookie, nullptr));
81 if (props.isNull()) {
82 return false;
83 }
84 xcb_atom_t *atoms = xcb_list_properties_atoms(props.data());
85 for (int i = 0; i < props->atoms_len; ++i) {
86 if (atoms[i] == m_property) {
87 return true;
88 }
89 }
90 return false;
91}
92
93} // namespace Plasma
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
Namespace for everything in libplasma.
const char * constData() const const
qsizetype length() const const
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
QCoreApplication * instance()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:34:35 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.