[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kwin] /: [Xcb::Wrapper] Introduce a Property and StringProperty Wrapper subclass
From: Martin_Gräßlin <mgraesslin () kde ! org>
Date: 2014-04-17 5:47:36
Message-ID: E1WafAe-0006wd-L4 () scm ! kde ! org
[Download RAW message or body]
Git commit b45eeae3526de4308ce1f8f6a53fd0cb44d828ef by Martin Gräßlin.
Committed on 15/04/2014 at 08:09.
Pushed by graesslin into branch 'master'.
[Xcb::Wrapper] Introduce a Property and StringProperty Wrapper subclass
The Xcb::Property can wrap the xcb_get_property call and provides
convenient access methods to read the value of the reply with checks
applied. For this it provides a templated ::value method for reading a
single value or reading an array. There's also a ::toBool and
> > toByteArray which performs the conversion directly with default values
for the type and format checks.
Xcb::TransientFor is changed to be derived from Property instead of
Wrapper directly, so that the reading of the property value can be
shared.
Xcb::StringProperty is a convenient wrapper derived from Property to
handle the reading of a string property providing a cast to QByteArray
operator. This replaces the ::getStringProperty from utils. Though the
separator functionality from ::getStringProperty is not provided as that
is only used in one function and handled there.
All the custom usages of xcb_get_property or getStringProperty are
replaced to use this new wrapper. That simplifies the code and ensures
that all properties are read in the same way.
REVIEW: 117574
M +2 -7 activation.cpp
M +93 -0 autotests/test_xcb_wrapper.cpp
M +32 -61 client.cpp
M +2 -9 effects.cpp
M +3 -6 shadow.cpp
M +9 -30 toplevel.cpp
M +0 -1 toplevel.h
M +0 -22 utils.cpp
M +0 -1 utils.h
M +193 -8 xcbutils.h
http://commits.kde.org/kwin/b45eeae3526de4308ce1f8f6a53fd0cb44d828ef
diff --git a/activation.cpp b/activation.cpp
index f8a9414..d98c7d9 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -674,13 +674,8 @@ void Client::updateUserTime(xcb_timestamp_t time)
xcb_timestamp_t Client::readUserCreationTime() const
{
- const xcb_get_property_cookie_t cookie = \
xcb_get_property_unchecked(connection(), false, window(),
- atoms->kde_net_wm_user_creation_time, XCB_ATOM_CARDINAL, 0, 10000);
- ScopedCPointer<xcb_get_property_reply_t> \
property(xcb_get_property_reply(connection(), cookie, NULL));
- if (property.isNull() || xcb_get_property_value_length(property.data()) == 0) {
- return -1;
- }
- return *(reinterpret_cast<xcb_timestamp_t*>(xcb_get_property_value(property.data())));
+ Xcb::Property prop(false, window(), atoms->kde_net_wm_user_creation_time, \
XCB_ATOM_CARDINAL, 0, 1); + return prop.value<xcb_timestamp_t>(-1);
}
void Client::demandAttention(bool set)
diff --git a/autotests/test_xcb_wrapper.cpp b/autotests/test_xcb_wrapper.cpp
index 769cd17..2ade4b0 100644
--- a/autotests/test_xcb_wrapper.cpp
+++ b/autotests/test_xcb_wrapper.cpp
@@ -23,6 +23,7 @@ along with this program. If not, see \
<http://www.gnu.org/licenses/>. // Qt
#include <QApplication>
#include <QtTest/QtTest>
+#include <netwm.h>
// xcb
#include <xcb/xcb.h>
@@ -47,6 +48,8 @@ private Q_SLOTS:
void testQueryTree();
void testCurrentInput();
void testTransientFor();
+ void testPropertyByteArray();
+ void testPropertyBool();
private:
void testEmpty(WindowGeometry &geometry);
void testGeometry(WindowGeometry &geometry, const QRect &rect);
@@ -275,6 +278,12 @@ void TestXcbWrapper::testTransientFor()
xcb_window_t compareWindow = XCB_WINDOW_NONE;
QVERIFY(!transient.getTransientFor(&compareWindow));
QCOMPARE(compareWindow, xcb_window_t(XCB_WINDOW_NONE));
+ bool ok = true;
+ QCOMPARE(transient.value<xcb_window_t>(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, \
&ok), xcb_window_t(XCB_WINDOW_NONE)); + QVERIFY(!ok);
+ ok = true;
+ QCOMPARE(transient.value<xcb_window_t>(XCB_WINDOW_NONE, &ok), \
xcb_window_t(XCB_WINDOW_NONE)); + QVERIFY(!ok);
// Create a Window with a transient for hint
Window transientWindow(createWindow());
@@ -284,11 +293,95 @@ void TestXcbWrapper::testTransientFor()
TransientFor realTransient(transientWindow);
QVERIFY(realTransient.getTransientFor(&compareWindow));
QCOMPARE(compareWindow, m_testWindow);
+ ok = false;
+ QCOMPARE(realTransient.value<xcb_window_t>(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, \
&ok), m_testWindow); + QVERIFY(ok);
+ ok = false;
+ QCOMPARE(realTransient.value<xcb_window_t>(XCB_WINDOW_NONE, &ok), m_testWindow);
+ QVERIFY(ok);
+ ok = false;
+ QCOMPARE(realTransient.value<xcb_window_t>(), m_testWindow);
+ QCOMPARE(realTransient.value<xcb_window_t*>(nullptr, &ok)[0], m_testWindow);
+ QVERIFY(ok);
+ QCOMPARE(realTransient.value<xcb_window_t*>()[0], m_testWindow);
// test for a not existing window
TransientFor doesntExist(XCB_WINDOW_NONE);
QVERIFY(!doesntExist.getTransientFor(&compareWindow));
}
+void TestXcbWrapper::testPropertyByteArray()
+{
+ Window testWindow(createWindow());
+ Property prop(false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000);
+ QCOMPARE(prop.toByteArray(), QByteArray());
+ bool ok = true;
+ QCOMPARE(prop.toByteArray(&ok), QByteArray());
+ QVERIFY(!ok);
+ ok = true;
+ QVERIFY(!prop.value<const char*>());
+ QCOMPARE(prop.value<const char*>("bar", &ok), "bar");
+ QVERIFY(!ok);
+ QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), \
QByteArray()); +
+ testWindow.changeProperty(XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 3, "foo");
+ prop = Property(false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, \
100000); + QCOMPARE(prop.toByteArray(), QByteArrayLiteral("foo"));
+ QCOMPARE(prop.toByteArray(&ok), QByteArrayLiteral("foo"));
+ QVERIFY(ok);
+ QCOMPARE(prop.value<const char*>(nullptr, &ok), "foo");
+ QVERIFY(ok);
+ QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), \
QByteArrayLiteral("foo")); +
+ // verify incorrect format and type
+ QCOMPARE(prop.toByteArray(32), QByteArray());
+ QCOMPARE(prop.toByteArray(8, XCB_ATOM_CARDINAL), QByteArray());
+
+ // verify empty property
+ testWindow.changeProperty(XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 0, nullptr);
+ prop = Property(false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, \
100000); + QCOMPARE(prop.toByteArray(), QByteArray());
+ QCOMPARE(prop.toByteArray(&ok), QByteArray());
+ QVERIFY(!ok);
+ QVERIFY(!prop.value<const char*>());
+ QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), \
QByteArray()); +}
+
+void TestXcbWrapper::testPropertyBool()
+{
+ Window testWindow(createWindow());
+ Atom blockCompositing(QByteArrayLiteral("_KDE_NET_WM_BLOCK_COMPOSITING"));
+ QVERIFY(blockCompositing != XCB_ATOM_NONE);
+ NETWinInfo info(QX11Info::connection(), testWindow, QX11Info::appRootWindow(), \
NET::Properties(), NET::WM2BlockCompositing); +
+ Property prop(false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, \
100000); + bool ok = true;
+ QVERIFY(!prop.toBool());
+ QVERIFY(!prop.toBool(&ok));
+ QVERIFY(!ok);
+
+ info.setBlockingCompositing(true);
+ xcb_flush(QX11Info::connection());
+ prop = Property(false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, \
100000); + QVERIFY(prop.toBool());
+ QVERIFY(prop.toBool(&ok));
+ QVERIFY(ok);
+
+ // incorrect type and format
+ QVERIFY(!prop.toBool(8));
+ QVERIFY(!prop.toBool(32, blockCompositing));
+ QVERIFY(!prop.toBool(32, blockCompositing, &ok));
+ QVERIFY(!ok);
+
+ // incorrect value:
+ uint32_t d[] = {1, 0};
+ testWindow.changeProperty(blockCompositing, XCB_ATOM_CARDINAL, 32, 2, d);
+ prop = Property(false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, \
100000); + QVERIFY(!prop.toBool());
+ ok = true;
+ QVERIFY(!prop.toBool(&ok));
+ QVERIFY(!ok);
+}
+
KWIN_TEST_MAIN(TestXcbWrapper)
#include "test_xcb_wrapper.moc"
diff --git a/client.cpp b/client.cpp
index dedffbe..0eb4086 100644
--- a/client.cpp
+++ b/client.cpp
@@ -2388,7 +2388,7 @@ void Client::checkActivities()
{
#ifdef KWIN_BUILD_ACTIVITIES
QStringList newActivitiesList;
- QByteArray prop = getStringProperty(window(), atoms->activities);
+ QByteArray prop = Xcb::StringProperty(window(), atoms->activities);
activitiesDefined = !prop.isEmpty();
if (QString::fromUtf8(prop) == Activities::nullUuid()) {
//copied from setOnAllActivities to avoid a redundant XChangeProperty.
@@ -2456,36 +2456,20 @@ KDecorationDefines::Position Client::titlebarPosition() const
void Client::updateFirstInTabBox()
{
// TODO: move into KWindowInfo
- xcb_connection_t *c = connection();
- const auto cookie = xcb_get_property_unchecked(c, false, m_client, \
atoms->kde_first_in_window_list,
- atoms->kde_first_in_window_list, \
0, 1);
- ScopedCPointer<xcb_get_property_reply_t> prop(xcb_get_property_reply(c, cookie, \
nullptr));
- if (!prop.isNull() && prop->format == 32 && prop->value_len == 1) {
- setFirstInTabBox(true);
- } else {
- setFirstInTabBox(false);
- }
+ Xcb::Property property(false, m_client, atoms->kde_first_in_window_list,
+ atoms->kde_first_in_window_list, 0, 1);
+ setFirstInTabBox(property.toBool(32, atoms->kde_first_in_window_list));
}
void Client::updateColorScheme()
{
// TODO: move into KWindowInfo
- xcb_connection_t *c = connection();
- const auto cookie = xcb_get_property_unchecked(c, false, m_client, \
atoms->kde_color_sheme,
- XCB_ATOM_STRING, 0, 10000);
- ScopedCPointer<xcb_get_property_reply_t> prop(xcb_get_property_reply(c, cookie, \
nullptr));
- auto resetToDefault = [this]() {
- m_palette = QApplication::palette();
- };
- QString path;
- if (!prop.isNull() && prop->format == 8 && prop->value_len > 0) {
- path = QString::fromUtf8(static_cast<const \
char*>(xcb_get_property_value(prop.data())));
- }
+ QString path = QString::fromUtf8(Xcb::StringProperty(m_client, \
atoms->kde_color_sheme)); path = rules()->checkDecoColor(path);
if (!path.isNull()) {
m_palette = \
KColorScheme::createApplicationPalette(KSharedConfig::openConfig(path)); } else {
- resetToDefault();
+ m_palette = QApplication::palette();
}
triggerDecorationRepaint();
}
@@ -2563,48 +2547,35 @@ xcb_window_t Client::frameId() const
void Client::updateShowOnScreenEdge()
{
- auto cookie = xcb_get_property_unchecked(connection(), false, window(), \
atoms->kde_screen_edge_show, XCB_ATOM_CARDINAL, 0, 1);
- ScopedCPointer<xcb_get_property_reply_t> \
reply(xcb_get_property_reply(connection(), cookie, nullptr));
-
- auto restore = [this]() {
+ Xcb::Property property(false, window(), atoms->kde_screen_edge_show, \
XCB_ATOM_CARDINAL, 0, 1); + const uint32_t value = \
property.value<uint32_t>(ElectricNone); + ElectricBorder border = ElectricNone;
+ switch (value) {
+ case 0:
+ border = ElectricTop;
+ break;
+ case 1:
+ border = ElectricRight;
+ break;
+ case 2:
+ border = ElectricBottom;
+ break;
+ case 3:
+ border = ElectricLeft;
+ break;
+ }
+ if (border != ElectricNone) {
+ hideClient(true);
+ ScreenEdges::self()->reserve(this, border);
+ } else if (!property.isNull() && property->type != XCB_ATOM_NONE) {
+ // property value is incorrect, delete the property
+ // so that the client knows that it is not hidden
+ xcb_delete_property(connection(), window(), atoms->kde_screen_edge_show);
+ } else {
+ // restore
// TODO: add proper unreserve
ScreenEdges::self()->reserve(this, ElectricNone);
hideClient(false);
- };
-
- if (!reply.isNull()) {
- if (reply->format == 32 && reply->type == XCB_ATOM_CARDINAL && \
reply->value_len == 1) {
- const uint32_t value = \
*reinterpret_cast<uint32_t*>(xcb_get_property_value(reply.data()));
- ElectricBorder border = ElectricNone;
- switch (value) {
- case 0:
- border = ElectricTop;
- break;
- case 1:
- border = ElectricRight;
- break;
- case 2:
- border = ElectricBottom;
- break;
- case 3:
- border = ElectricLeft;
- break;
- }
- if (border != ElectricNone) {
- hideClient(true);
- ScreenEdges::self()->reserve(this, border);
- } else {
- // property value is incorrect, delete the property
- // so that the client knows that it is not hidden
- xcb_delete_property(connection(), window(), \
atoms->kde_screen_edge_show);
- }
-
- } else if (reply->type == XCB_ATOM_NONE) {
- // the property got deleted, show the client again
- restore();
- }
- } else {
- restore();
}
}
diff --git a/effects.cpp b/effects.cpp
index 1963c48..4d88208 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -166,10 +166,8 @@ void ScreenLockerWatcher::setLocked(bool activated)
static QByteArray readWindowProperty(xcb_window_t win, xcb_atom_t atom, xcb_atom_t \
type, int format) {
uint32_t len = 32768;
- xcb_connection_t *c = connection();
for (;;) {
- const auto cookie = xcb_get_property_unchecked(c, false, win, atom, \
XCB_ATOM_ANY, 0, len);
- ScopedCPointer<xcb_get_property_reply_t> prop(xcb_get_property_reply(c, \
cookie, nullptr)); + Xcb::Property prop(false, win, atom, XCB_ATOM_ANY, 0, \
len); if (prop.isNull()) {
// get property failed
return QByteArray();
@@ -178,12 +176,7 @@ static QByteArray readWindowProperty(xcb_window_t win, \
xcb_atom_t atom, xcb_atom len *= 2;
continue;
}
- if (prop->type == type && prop->format == format) {
- return QByteArray(reinterpret_cast< const char* \
>(xcb_get_property_value(prop.data())),
- xcb_get_property_value_length(prop.data()));
- } else {
- return QByteArray();
- }
+ return prop.toByteArray(format, type);
}
}
diff --git a/shadow.cpp b/shadow.cpp
index 10c9594..ca13947 100644
--- a/shadow.cpp
+++ b/shadow.cpp
@@ -63,12 +63,9 @@ Shadow *Shadow::createShadow(Toplevel *toplevel)
QVector< uint32_t > Shadow::readX11ShadowProperty(xcb_window_t id)
{
QVector<uint32_t> ret;
- xcb_connection_t *c = connection();
- const auto cookie = xcb_get_property_unchecked(c, false, id, \
atoms->kde_net_wm_shadow,
- XCB_ATOM_CARDINAL, 0, 12);
- ScopedCPointer<xcb_get_property_reply_t> prop(xcb_get_property_reply(c, cookie, \
nullptr));
- if (!prop.isNull() && prop->type == XCB_ATOM_CARDINAL && prop->format == 32 ) {
- uint32_t* shadow = reinterpret_cast< uint32_t* \
>(xcb_get_property_value(prop.data())); + Xcb::Property property(false, id, \
> atoms->kde_net_wm_shadow, XCB_ATOM_CARDINAL, 0, 12);
+ uint32_t *shadow = property.value<uint32_t*>();
+ if (shadow) {
ret.reserve(12);
for (int i=0; i<12; ++i) {
ret << shadow[i];
diff --git a/toplevel.cpp b/toplevel.cpp
index a945757..b88ef04 100644
--- a/toplevel.cpp
+++ b/toplevel.cpp
@@ -145,24 +145,10 @@ QRect Toplevel::visibleRect() const
return r.translated(geometry().topLeft());
}
-/*!
- Returns WM_CLIENT_LEADER property for a given window.
- */
-xcb_window_t Toplevel::staticWmClientLeader(xcb_window_t w)
-{
- xcb_connection_t *c = connection();
- auto cookie = xcb_get_property_unchecked(c, false, w, atoms->wm_client_leader, \
XCB_ATOM_WINDOW, 0, 10000);
- ScopedCPointer<xcb_get_property_reply_t> prop(xcb_get_property_reply(c, cookie, \
nullptr));
- if (prop.isNull() || prop->value_len <= 0) {
- return w;
- }
- return static_cast<xcb_window_t*>(xcb_get_property_value(prop.data()))[0];
-}
-
-
void Toplevel::getWmClientLeader()
{
- wmClientLeaderWin = staticWmClientLeader(window());
+ Xcb::Property prop(false, window(), atoms->wm_client_leader, XCB_ATOM_WINDOW, 0, \
10000); + wmClientLeaderWin = prop.value<xcb_window_t>(window());
}
/*!
@@ -171,9 +157,9 @@ void Toplevel::getWmClientLeader()
*/
QByteArray Toplevel::sessionId() const
{
- QByteArray result = getStringProperty(window(), atoms->sm_client_id);
+ QByteArray result = Xcb::StringProperty(window(), atoms->sm_client_id);
if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin != window())
- result = getStringProperty(wmClientLeaderWin, atoms->sm_client_id);
+ result = Xcb::StringProperty(wmClientLeaderWin, atoms->sm_client_id);
return result;
}
@@ -183,9 +169,10 @@ QByteArray Toplevel::sessionId() const
*/
QByteArray Toplevel::wmCommand()
{
- QByteArray result = getStringProperty(window(), XCB_ATOM_WM_COMMAND, ' ');
+ QByteArray result = Xcb::StringProperty(window(), XCB_ATOM_WM_COMMAND);
if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin != window())
- result = getStringProperty(wmClientLeaderWin, XCB_ATOM_WM_COMMAND, ' ');
+ result = Xcb::StringProperty(wmClientLeaderWin, XCB_ATOM_WM_COMMAND);
+ result.replace(0, ' ');
return result;
}
@@ -438,16 +425,8 @@ xcb_window_t Toplevel::frameId() const
void Toplevel::getSkipCloseAnimation()
{
- auto cookie = xcb_get_property_unchecked(connection(), false, window(), \
atoms->kde_skip_close_animation, XCB_ATOM_CARDINAL, 0, 1);
- ScopedCPointer<xcb_get_property_reply_t> \
reply(xcb_get_property_reply(connection(), cookie, nullptr));
- bool newValue = false;
- if (!reply.isNull()) {
- if (reply->format == 32 && reply->type == XCB_ATOM_CARDINAL && \
reply->value_len == 1) {
- const uint32_t value = \
*reinterpret_cast<uint32_t*>(xcb_get_property_value(reply.data()));
- newValue = (value != 0);
- }
- }
- setSkipCloseAnimation(newValue);
+ Xcb::Property property(false, window(), atoms->kde_skip_close_animation, \
XCB_ATOM_CARDINAL, 0, 1); + setSkipCloseAnimation(property.toBool());
}
bool Toplevel::skipsCloseAnimation() const
diff --git a/toplevel.h b/toplevel.h
index 305f667..2fce2c1 100644
--- a/toplevel.h
+++ b/toplevel.h
@@ -438,7 +438,6 @@ protected:
bool m_isDamaged;
private:
- static xcb_window_t staticWmClientLeader(xcb_window_t);
// when adding new data members, check also copyToDeleted()
Xcb::Window m_client;
xcb_damage_damage_t damage_handle;
diff --git a/utils.cpp b/utils.cpp
index 88ab2d8..856818d 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -67,28 +67,6 @@ StrutRect::StrutRect(const StrutRect& other)
#endif
-QByteArray getStringProperty(xcb_window_t w, xcb_atom_t prop, char separator)
-{
- const xcb_get_property_cookie_t c = xcb_get_property_unchecked(connection(), \
false, w, prop,
- XCB_ATOM_STRING, \
0, 10000);
- ScopedCPointer<xcb_get_property_reply_t> \
property(xcb_get_property_reply(connection(), c, NULL));
- if (property.isNull() || property->type == XCB_ATOM_NONE) {
- return QByteArray();
- }
- char *data = static_cast<char*>(xcb_get_property_value(property.data()));
- int length = property->value_len;
- if (data && separator) {
- for (uint32_t i = 0; i < property->value_len; ++i) {
- if (!data[i] && i + 1 < property->value_len) {
- data[i] = separator;
- } else {
- length = i;
- }
- }
- }
- return QByteArray(data, length);
-}
-
#ifndef KCMRULES
/*
Updates xTime(). This used to simply fetch current timestamp from the server,
diff --git a/utils.h b/utils.h
index 198db92..e96adbf 100644
--- a/utils.h
+++ b/utils.h
@@ -122,7 +122,6 @@ enum ShadeMode {
template <typename T> using ScopedCPointer = QScopedPointer<T, \
QScopedPointerPodDeleter>;
-QByteArray getStringProperty(xcb_window_t w, xcb_atom_t prop, char separator = 0);
void updateXTime();
void grabXServer();
void ungrabXServer();
diff --git a/xcbutils.h b/xcbutils.h
index 61611b7..2762f2e 100644
--- a/xcbutils.h
+++ b/xcbutils.h
@@ -592,11 +592,199 @@ public:
};
XCB_WRAPPER_DATA(PropertyData, xcb_get_property, uint8_t, xcb_window_t, xcb_atom_t, \
xcb_atom_t, uint32_t, uint32_t)
-class TransientFor : public Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, \
xcb_atom_t, uint32_t, uint32_t> +class Property : public Wrapper<PropertyData, \
uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t> +{
+public:
+ Property()
+ : Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, \
uint32_t, uint32_t>() + , m_type(XCB_ATOM_NONE)
+ {
+ }
+ Property(const Property &other)
+ : Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, \
uint32_t, uint32_t>(other) + , m_type(other.m_type)
+ {
+ }
+ explicit Property(uint8_t _delete, xcb_window_t window, xcb_atom_t property, \
xcb_atom_t type, uint32_t long_offset, uint32_t long_length) + : \
Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, uint32_t, \
uint32_t>(window, _delete, window, property, type, long_offset, long_length) + \
, m_type(type) + {
+ }
+ Property &operator=(const Property &other) {
+ Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, \
uint32_t, uint32_t>::operator=(other); + m_type = other.m_type;
+ return *this;
+ }
+
+ /**
+ * @brief Overloaded method for convenience.
+ *
+ * Uses the type which got passed into the ctor and derives the format from the \
sizeof(T). + * Note: for the automatic format detection the size of the type T \
may not vary between + * architectures. Thus one needs to use e.g. uint32_t \
instead of long. In general all xcb + * data types can be used, all Xlib data \
types can not be used. + *
+ * @param defaultValue The default value to return in case of error
+ * @param ok Set to @c false in case of error, @c true in case of success
+ * @return The read value or @p defaultValue in error case
+ */
+ template <typename T>
+ inline typename std::enable_if<!std::is_pointer<T>::value, T>::type value(T \
defaultValue = T(), bool *ok = nullptr) { + return value<T>(sizeof(T) * 8, \
m_type, defaultValue, ok); + }
+ /**
+ * @brief Reads the property as a POD type.
+ *
+ * Returns the first value of the property data. In case of @p format or @p type \
mismatch + * the @p defaultValue is returned. The optional argument @p ok is set
+ * to @c false in case of error and to @c true in case of successful reading of
+ * the property.
+ *
+ * @param format The expected format of the property value, e.g. 32 for \
XCB_ATOM_CARDINAL + * @param type The expected type of the property value, e.g. \
XCB_ATOM_CARDINAL + * @param defaultValue The default value to return in case of \
error + * @param ok Set to @c false in case of error, @c true in case of success
+ * @return The read value or @p defaultValue in error case
+ **/
+ template <typename T>
+ inline typename std::enable_if<!std::is_pointer<T>::value, T>::type \
value(uint8_t format, xcb_atom_t type, T defaultValue = T(), bool *ok = nullptr) { + \
T *reply = value<T*>(format, type, nullptr, ok); + if (!reply) {
+ return defaultValue;
+ }
+ return reply[0];
+ }
+ /**
+ * @brief Overloaded method for convenience.
+ *
+ * Uses the type which got passed into the ctor and derives the format from the \
sizeof(T). + * Note: for the automatic format detection the size of the type T \
may not vary between + * architectures. Thus one needs to use e.g. uint32_t \
instead of long. In general all xcb + * data types can be used, all Xlib data \
types can not be used. + *
+ * @param defaultValue The default value to return in case of error
+ * @param ok Set to @c false in case of error, @c true in case of success
+ * @return The read value or @p defaultValue in error case
+ */
+ template <typename T>
+ inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(T \
defaultValue = nullptr, bool *ok = nullptr) { + return \
value<T>(sizeof(typename std::remove_pointer<T>::type) * 8, m_type, defaultValue, \
ok); + }
+ /**
+ * @brief Reads the property as an array of T.
+ *
+ * This method is an overload for the case that T is a pointer type.
+ *
+ * Return the property value casted to the pointer type T. In case of @p format
+ * or @p type mismatch the @p defaultValue is returned. Also if the value length
+ * is @c 0 the @p defaultValue is returned. The optional argument @p ok is set
+ * to @c false in case of error and to @c true in case of successful reading of
+ * the property.
+ *
+ * @param format The expected format of the property value, e.g. 32 for \
XCB_ATOM_CARDINAL + * @param type The expected type of the property value, e.g. \
XCB_ATOM_CARDINAL + * @param defaultValue The default value to return in case of \
error + * @param ok Set to @c false in case of error, @c true in case of success
+ * @return The read value or @p defaultValue in error case
+ **/
+ template <typename T>
+ inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(uint8_t \
format, xcb_atom_t type, T defaultValue = nullptr, bool *ok = nullptr) { + if \
(ok) { + *ok = false;
+ }
+ const PropertyData::reply_type *reply = data();
+ if (!reply) {
+ return defaultValue;
+ }
+ if (reply->type != type) {
+ return defaultValue;
+ }
+ if (reply->format != format) {
+ return defaultValue;
+ }
+ if (xcb_get_property_value_length(reply) == 0) {
+ return defaultValue;
+ }
+ if (ok) {
+ *ok = true;
+ }
+ return reinterpret_cast<T>(xcb_get_property_value(reply));
+ }
+ /**
+ * @brief Reads the property as string and returns a QByteArray.
+ *
+ * In case of error this method returns a null QByteArray.
+ **/
+ inline QByteArray toByteArray(uint8_t format = 8, xcb_atom_t type = \
XCB_ATOM_STRING, bool *ok = nullptr) { + const char *reply = value<const \
char*>(format, type, nullptr, ok); + if (!reply) {
+ return QByteArray();
+ }
+ return QByteArray(reply, xcb_get_property_value_length(data()));
+ }
+ /**
+ * @brief Overloaded method for convenience.
+ **/
+ inline QByteArray toByteArray(bool *ok) {
+ return toByteArray(8, m_type, ok);
+ }
+ /**
+ * @brief Reads the property as a boolean value.
+ *
+ * If the property reply length is @c 1 the first element is interpreted as a \
boolean + * value returning @c true for any value unequal to @c 0 and @c false \
otherwise. + *
+ * In case of error this method returns @c false. Thus it is not possible to \
distinguish + * between error case and a read @c false value. Use the optional \
argument @p ok to + * distinguish the error case.
+ *
+ * @param format Expected format. Defaults to 32.
+ * @param type Expected type Defaults to XCB_ATOM_CARDINAL.
+ * @param ok Set to @c false in case of error, @c true in case of success
+ * @return bool The first element interpreted as a boolean value or @c false in \
error case + * @see value
+ */
+ inline bool toBool(uint8_t format = 32, xcb_atom_t type = XCB_ATOM_CARDINAL, \
bool *ok = nullptr) { + bool *reply = value<bool*>(format, type, nullptr, ok);
+ if (!reply) {
+ return false;
+ }
+ if (data()->value_len != 1) {
+ if (ok) {
+ *ok = false;
+ }
+ return false;
+ }
+ return reply[0] != 0;
+ }
+ /**
+ * @brief Overloaded method for convenience.
+ **/
+ inline bool toBool(bool *ok) {
+ return toBool(32, m_type, ok);
+ }
+private:
+ xcb_atom_t m_type;
+};
+
+class StringProperty : public Property
+{
+public:
+ StringProperty() = default;
+ explicit StringProperty(xcb_window_t w, xcb_atom_t p)
+ : Property(false, w, p, XCB_ATOM_STRING, 0, 10000)
+ {
+ }
+ operator QByteArray() {
+ return toByteArray();
+ }
+};
+
+class TransientFor : public Property
{
public:
explicit TransientFor(WindowId window)
- : Wrapper<PropertyData, uint8_t, xcb_window_t, xcb_atom_t, xcb_atom_t, \
uint32_t, uint32_t>(window, 0, window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, \
1) + : Property(0, window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 0, 1)
{
}
@@ -606,15 +794,12 @@ public:
* @returns @c true on success, @c false otherwise
**/
inline bool getTransientFor(WindowId *prop) {
- if (isNull()) {
+ WindowId *windows = value<WindowId*>();
+ if (!windows) {
return false;
}
- const xcb_get_property_reply_t *reply = data();
- if (!reply || reply->type != XCB_ATOM_WINDOW || reply->format != 32 || \
reply->length == 0)
- return false;
-
- *prop = *reinterpret_cast<WindowId *>(xcb_get_property_value(reply));
+ *prop = *windows;
return true;
}
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic