Port EffectWatcher to XCB
Saves quite a lot of roundtrips to the XServer. Most important we fetch the atom only once which means we don't have to refetch when checking the property notify events. REVIEW: 112445
This commit is contained in:
parent
aee973edcd
commit
e50dbc413e
@ -115,7 +115,7 @@ add_library(KF5Plasma ${Plasma_LIB_SRCS})
|
||||
add_library(KF5::Plasma ALIAS KF5Plasma)
|
||||
|
||||
if(X11_FOUND)
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} Qt5::X11Extras ${X11_LIBRARIES})
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} Qt5::X11Extras ${X11_LIBRARIES} ${XCB_XCB_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(DL_LIBRARY)
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <QtX11Extras/QX11Info>
|
||||
|
||||
namespace Plasma
|
||||
@ -30,19 +28,26 @@ namespace Plasma
|
||||
|
||||
EffectWatcher::EffectWatcher(const QString& property, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_property(property)
|
||||
m_property(XCB_ATOM_NONE)
|
||||
{
|
||||
m_effectActive = isEffectActive();
|
||||
|
||||
QCoreApplication::instance()->installNativeEventFilter(this);
|
||||
|
||||
Display *dpy = QX11Info::display();
|
||||
Window root = DefaultRootWindow(dpy);
|
||||
XWindowAttributes attrs;
|
||||
//Don't reset eventual other masks already there
|
||||
XGetWindowAttributes(dpy, root, &attrs);
|
||||
attrs.your_event_mask |= PropertyChangeMask;
|
||||
XSelectInput(dpy, root, attrs.your_event_mask);
|
||||
xcb_connection_t *c = QX11Info::connection();
|
||||
const QByteArray propertyName = property.toLatin1();
|
||||
xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, propertyName.length(), propertyName.constData());
|
||||
xcb_get_window_attributes_cookie_t winAttrCookie = xcb_get_window_attributes_unchecked(c, QX11Info::appRootWindow());
|
||||
|
||||
QScopedPointer<xcb_intern_atom_reply_t, QScopedPointerPodDeleter> atom(xcb_intern_atom_reply(c, atomCookie, nullptr));
|
||||
if (!atom.isNull()) {
|
||||
m_property = atom->atom;
|
||||
}
|
||||
m_effectActive = isEffectActive();
|
||||
|
||||
QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> attrs(xcb_get_window_attributes_reply(c, winAttrCookie, nullptr));
|
||||
if (!attrs.isNull()) {
|
||||
uint32_t events = attrs->your_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
||||
xcb_change_window_attributes(c, QX11Info::appRootWindow(), XCB_CW_EVENT_MASK, &events);
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectWatcher::nativeEventFilter(const QByteArray& eventType, void *message, long *result)
|
||||
@ -52,13 +57,11 @@ bool EffectWatcher::nativeEventFilter(const QByteArray& eventType, void *message
|
||||
return false;
|
||||
xcb_generic_event_t* event = reinterpret_cast<xcb_generic_event_t *>(message);
|
||||
uint response_type = event->response_type & ~0x80;
|
||||
if (response_type != XCB_PROPERTY_NOTIFY)
|
||||
if (response_type != XCB_PROPERTY_NOTIFY || m_property == XCB_ATOM_NONE)
|
||||
return false;
|
||||
|
||||
xcb_property_notify_event_t* prop_event = reinterpret_cast<xcb_property_notify_event_t *>(event);
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom testAtom = XInternAtom(dpy, m_property.toLatin1(), False);
|
||||
if (prop_event->atom == testAtom) {
|
||||
if (prop_event->atom == m_property) {
|
||||
bool nowEffectActive = isEffectActive();
|
||||
if (m_effectActive != nowEffectActive) {
|
||||
m_effectActive = nowEffectActive;
|
||||
@ -70,17 +73,22 @@ bool EffectWatcher::nativeEventFilter(const QByteArray& eventType, void *message
|
||||
|
||||
bool EffectWatcher::isEffectActive() const
|
||||
{
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom testAtom = XInternAtom(dpy, m_property.toLatin1(), False);
|
||||
|
||||
bool nowEffectActive = false;
|
||||
int cnt;
|
||||
Atom *list = XListProperties(dpy, DefaultRootWindow(dpy), &cnt);
|
||||
if (list != NULL) {
|
||||
nowEffectActive = (qFind(list, list + cnt, testAtom) != list + cnt);
|
||||
XFree(list);
|
||||
if (m_property == XCB_ATOM_NONE) {
|
||||
return false;
|
||||
}
|
||||
return nowEffectActive;
|
||||
xcb_connection_t *c = QX11Info::connection();
|
||||
xcb_list_properties_cookie_t propsCookie = xcb_list_properties_unchecked(c, QX11Info::appRootWindow());
|
||||
QScopedPointer<xcb_list_properties_reply_t, QScopedPointerPodDeleter> props(xcb_list_properties_reply(c, propsCookie, nullptr));
|
||||
if (props.isNull()) {
|
||||
return false;
|
||||
}
|
||||
xcb_atom_t *atoms = xcb_list_properties_atoms(props.data());
|
||||
for (int i = 0; i < props->atoms_len; ++i) {
|
||||
if (atoms[i] == m_property) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
@ -43,7 +45,7 @@ Q_SIGNALS:
|
||||
void effectChanged(bool on);
|
||||
|
||||
private:
|
||||
QString m_property;
|
||||
xcb_atom_t m_property;
|
||||
bool m_effectActive;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user