[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwindowsystem] src: Add platform check to KSelectionOwner and KSelectionWatcher
From:       Martin_Gräßlin <mgraesslin () kde ! org>
Date:       2014-02-01 7:41:57
Message-ID: E1W9VDB-0002rc-Ic () scm ! kde ! org
[Download RAW message or body]

Git commit 77f8148cea518bc580707e66ae49d4452ccd612d by Martin Gräßlin.
Committed on 22/01/2014 at 15:10.
Pushed by graesslin into branch 'master'.

Add platform check to KSelectionOwner and KSelectionWatcher

These are highly X11 specific classes and don't make any sense on a
platform other than xcb and were potentially crashy by using QX11Info
without verifying that the platform is used.

The implementation will now only create the d-ptr in case that the
code is running on the xcb platform and ensures that no call to xcb
is done unconditionally. All methods perform an early return in case
the d-ptr is null. Non-void methods return a sensible default value
in this case.

REVIEW: 115230

M  +62   -7    src/kselectionowner.cpp
M  +4    -0    src/kselectionowner.h
M  +31   -3    src/kselectionwatcher.cpp
M  +4    -0    src/kselectionwatcher.h

http://commits.kde.org/kwindowsystem/77f8148cea518bc580707e66ae49d4452ccd612d

diff --git a/src/kselectionowner.cpp b/src/kselectionowner.cpp
index 3715267..90a0004 100644
--- a/src/kselectionowner.cpp
+++ b/src/kselectionowner.cpp
@@ -27,7 +27,8 @@ DEALINGS IN THE SOFTWARE.
 #include <config-kwindowsystem.h>
 
 #include <QtCore/QBasicTimer>
-#include <QtCore/QCoreApplication>
+#include <QDebug>
+#include <QGuiApplication>
 #include <QTimerEvent>
 #include <QAbstractNativeEventFilter>
 
@@ -99,6 +100,9 @@ public:
     static xcb_atom_t xa_targets;
     static xcb_atom_t xa_timestamp;
 
+    static Private *create(KSelectionOwner *owner, xcb_atom_t selection_P, int \
screen_P); +    static Private *create(KSelectionOwner *owner, const char \
*selection_P, int screen_P); +
 protected:
     bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) \
Q_DECL_OVERRIDE {  Q_UNUSED(result);
@@ -113,25 +117,45 @@ private:
     KSelectionOwner *owner;
 };
 
+KSelectionOwner::Private* KSelectionOwner::Private::create(KSelectionOwner *owner, \
xcb_atom_t selection_P, int screen_P) +{
+    if (QGuiApplication::platformName() == QStringLiteral("xcb")) {
+        return new Private(owner, selection_P, screen_P);
+    }
+    qWarning() << "Trying to use KSelectionOwner on a non-X11 platform! This is an \
application bug."; +    return Q_NULLPTR;
+}
+
+KSelectionOwner::Private *KSelectionOwner::Private::create(KSelectionOwner *owner, \
const char *selection_P, int screen_P) +{
+    if (QGuiApplication::platformName() == QStringLiteral("xcb")) {
+        return new Private(owner, intern_atom(QX11Info::connection(), selection_P), \
screen_P); +    }
+    qWarning() << "Trying to use KSelectionOwner on a non-X11 platform! This is an \
application bug."; +    return Q_NULLPTR;
+}
+
 KSelectionOwner::KSelectionOwner(xcb_atom_t selection_P, int screen_P, QObject \
*parent_P)  :   QObject(parent_P),
-        d(new Private(this, selection_P, screen_P))
+        d(Private::create(this, selection_P, screen_P))
 {
 }
 
 KSelectionOwner::KSelectionOwner(const char *selection_P, int screen_P, QObject \
*parent_P)  :   QObject(parent_P),
-        d(new Private(this, intern_atom(QX11Info::connection(), selection_P), \
screen_P)) +        d(Private::create(this, selection_P, screen_P))
 {
 }
 
 KSelectionOwner::~KSelectionOwner()
 {
-    release();
-    if (d->window != XCB_WINDOW_NONE) {
-        xcb_destroy_window(QX11Info::connection(), d->window); // also makes the \
selection not owned +    if (d) {
+        release();
+        if (d->window != XCB_WINDOW_NONE) {
+            xcb_destroy_window(QX11Info::connection(), d->window); // also makes the \
selection not owned +        }
+        delete d;
     }
-    delete d;
 }
 
 void KSelectionOwner::Private::claimSucceeded()
@@ -213,6 +237,9 @@ void KSelectionOwner::Private::timeout()
 
 void KSelectionOwner::claim(bool force_P, bool force_kill_P)
 {
+    if (!d) {
+        return;
+    }
     Q_ASSERT(d->state == Private::Idle);
 
     if (Private::manager_atom == XCB_NONE) {
@@ -258,6 +285,9 @@ void KSelectionOwner::claim(bool force_P, bool force_kill_P)
 // destroy resource first
 void KSelectionOwner::release()
 {
+    if (!d) {
+        return;
+    }
     if (d->timestamp == XCB_CURRENT_TIME) {
         return;
     }
@@ -272,6 +302,9 @@ void KSelectionOwner::release()
 
 xcb_window_t KSelectionOwner::ownerWindow() const
 {
+    if (!d) {
+        return XCB_WINDOW_NONE;
+    }
     if (d->timestamp == XCB_CURRENT_TIME) {
         return XCB_NONE;
     }
@@ -281,12 +314,18 @@ xcb_window_t KSelectionOwner::ownerWindow() const
 
 void KSelectionOwner::setData(uint32_t extra1_P, uint32_t extra2_P)
 {
+    if (!d) {
+        return;
+    }
     d->extra1 = extra1_P;
     d->extra2 = extra2_P;
 }
 
 bool KSelectionOwner::filterEvent(void *ev_P)
 {
+    if (!d) {
+        return false;
+    }
     xcb_generic_event_t *event = reinterpret_cast<xcb_generic_event_t *>(ev_P);
     const uint response_type = event->response_type & ~0x80;
 
@@ -368,6 +407,10 @@ bool KSelectionOwner::filterEvent(void *ev_P)
 
 void KSelectionOwner::timerEvent(QTimerEvent *event)
 {
+    if (!d) {
+        QObject::timerEvent(event);
+        return;
+    }
     if (event->timerId() == d->timer.timerId()) {
         d->timer.stop();
         d->timeout();
@@ -386,6 +429,9 @@ bool KSelectionOwner::handleMessage(XEvent *)
 
 void KSelectionOwner::filter_selection_request(void *event)
 {
+    if (!d) {
+        return;
+    }
     xcb_selection_request_event_t *ev = \
reinterpret_cast<xcb_selection_request_event_t *>(event);  
     if (d->timestamp == XCB_CURRENT_TIME || ev->selection != d->selection) {
@@ -457,6 +503,9 @@ void KSelectionOwner::filter_selection_request(void *event)
 
 bool KSelectionOwner::handle_selection(xcb_atom_t target_P, xcb_atom_t property_P, \
xcb_window_t requestor_P)  {
+    if (!d) {
+        return false;
+    }
     if (target_P == Private::xa_timestamp) {
         // qDebug() << "Handling timestamp request";
         xcb_change_property(QX11Info::connection(), requestor_P, property_P, \
XCB_ATOM_INTEGER, 32, @@ -474,6 +523,9 @@ bool \
KSelectionOwner::handle_selection(xcb_atom_t target_P, xcb_atom_t property_  
 void KSelectionOwner::replyTargets(xcb_atom_t property_P, xcb_window_t requestor_P)
 {
+    if (!d) {
+        return;
+    }
     xcb_atom_t atoms[3] = { Private::xa_multiple, Private::xa_timestamp, \
Private::xa_targets };  
     xcb_change_property(QX11Info::connection(), requestor_P, property_P, \
XCB_ATOM_ATOM, 32, XCB_PROP_MODE_REPLACE, @@ -489,6 +541,9 @@ bool \
KSelectionOwner::genericReply(xcb_atom_t, xcb_atom_t, xcb_window_t)  
 void KSelectionOwner::getAtoms()
 {
+    if (!d) {
+        return;
+    }
     if (Private::manager_atom != XCB_NONE) {
         return;
     }
diff --git a/src/kselectionowner.h b/src/kselectionowner.h
index 512bd5e..b5d358a 100644
--- a/src/kselectionowner.h
+++ b/src/kselectionowner.h
@@ -38,6 +38,10 @@ DEALINGS IN THE SOFTWARE.
  the selection ownership. Signal lostOwnership() is emitted when the selection
  is claimed by another owner.
  @short ICCCM manager selection owner
+
+ This class is only useful on the xcb platform. On other platforms the code is not
+ functional. In case you inherit from this class ensure that you don't use xcb \
and/or + XLib without verifying the platform.
 */
 class KWINDOWSYSTEM_EXPORT KSelectionOwner
     : public QObject
diff --git a/src/kselectionwatcher.cpp b/src/kselectionwatcher.cpp
index 87e0a96..2539fca 100644
--- a/src/kselectionwatcher.cpp
+++ b/src/kselectionwatcher.cpp
@@ -27,7 +27,7 @@ DEALINGS IN THE SOFTWARE.
 #include <config-kwindowsystem.h>
 
 #include <QtCore/QObject>
-#include <QtCore/QCoreApplication>
+#include <QGuiApplication>
 #include <QAbstractNativeEventFilter>
 
 #include <qx11info_x11.h>
@@ -80,6 +80,9 @@ public:
     xcb_window_t selection_owner;
     static xcb_atom_t manager_atom;
 
+    static Private *create(KSelectionWatcher *watcher, xcb_atom_t selection_P, int \
screen_P); +    static Private *create(KSelectionWatcher *watcher, const char \
*selection_P, int screen_P); +
 protected:
     bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) \
Q_DECL_OVERRIDE {  Q_UNUSED(result);
@@ -95,16 +98,32 @@ private:
     KSelectionWatcher *watcher;
 };
 
+KSelectionWatcher::Private *KSelectionWatcher::Private::create(KSelectionWatcher \
*watcher, xcb_atom_t selection_P, int screen_P) +{
+    if (QGuiApplication::platformName() == QStringLiteral("xcb")) {
+        return new Private(watcher, selection_P, screen_P);
+    }
+    return Q_NULLPTR;
+}
+
+KSelectionWatcher::Private *KSelectionWatcher::Private::create(KSelectionWatcher \
*watcher, const char *selection_P, int screen_P) +{
+    if (QGuiApplication::platformName() == QStringLiteral("xcb")) {
+        return new Private(watcher, intern_atom(QX11Info::connection(), \
selection_P), screen_P); +    }
+    return Q_NULLPTR;
+}
+
 KSelectionWatcher::KSelectionWatcher(xcb_atom_t selection_P, int screen_P, QObject \
*parent_P)  :   QObject(parent_P),
-        d(new Private(this, selection_P, screen_P))
+        d(Private::create(this, selection_P, screen_P))
 {
     init();
 }
 
 KSelectionWatcher::KSelectionWatcher(const char *selection_P, int screen_P, QObject \
*parent_P)  :   QObject(parent_P),
-        d(new Private(this, intern_atom(QX11Info::connection(), selection_P), \
screen_P)) +        d(Private::create(this, selection_P, screen_P))
 {
     init();
 }
@@ -116,6 +135,9 @@ KSelectionWatcher::~KSelectionWatcher()
 
 void KSelectionWatcher::init()
 {
+    if (!d) {
+        return;
+    }
     if (Private::manager_atom == XCB_NONE) {
         xcb_connection_t *c = QX11Info::connection();
 
@@ -142,6 +164,9 @@ void KSelectionWatcher::init()
 
 xcb_window_t KSelectionWatcher::owner()
 {
+    if (!d) {
+        return XCB_WINDOW_NONE;
+    }
     xcb_connection_t *c = QX11Info::connection();
 
     xcb_window_t current_owner = get_selection_owner(c, d->selection);
@@ -178,6 +203,9 @@ xcb_window_t KSelectionWatcher::owner()
 
 void KSelectionWatcher::filterEvent(void *ev_P)
 {
+    if (!d) {
+        return;
+    }
     xcb_generic_event_t *event = reinterpret_cast<xcb_generic_event_t *>(ev_P);
     const uint response_type = event->response_type & ~0x80;
     if (response_type == XCB_CLIENT_MESSAGE) {
diff --git a/src/kselectionwatcher.h b/src/kselectionwatcher.h
index 798fe70..f3b15a0 100644
--- a/src/kselectionwatcher.h
+++ b/src/kselectionwatcher.h
@@ -37,6 +37,10 @@ DEALINGS IN THE SOFTWARE.
  and emits lostOwner() when the selection ownership is given up. To find
  out current owner of the selection, owner() can be used.
  @short ICCCM manager selection watching
+
+ This class is only useful on the xcb platform. On other platforms the code is not
+ functional. In case you inherit from this class ensure that you don't use xcb \
and/or + XLib without verifying the platform.
 */
 class KWINDOWSYSTEM_EXPORT KSelectionWatcher
     : public QObject


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic