From 6c77f863b5e7393ac314e8491ae86eaadec569e7 Mon Sep 17 00:00:00 2001
From: Stefan Becker <chemobejk@gmail.com>
Date: Mon, 25 May 2015 10:24:07 +0300
Subject: [PATCH] Forward QWidget windowRole to QPlatformWindow

- add windowRole() set/get interface to QPlatformWindow
- use new interface in QWidget windowRole methods
- xcb: provide implementation that sets WM_WINDOW_ROLE property

Task-number: QTBUG-45484
---
 src/gui/kernel/qplatformwindow.cpp       | 10 ++++++++++
 src/gui/kernel/qplatformwindow.h         |  3 +++
 src/plugins/platforms/xcb/qxcbwindow.cpp | 15 +++++++++++++++
 src/plugins/platforms/xcb/qxcbwindow.h   |  6 ++++++
 src/widgets/kernel/qwidget.cpp           | 17 ++++++++---------
 5 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 7543955..b394d2e 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -286,6 +286,16 @@ void QPlatformWindow::setWindowFilePath(const QString &filePath) { Q_UNUSED(file
 void QPlatformWindow::setWindowIcon(const QIcon &icon) { Q_UNUSED(icon); }
 
 /*!
+  Reimplement to set the window role to \a role
+*/
+void QPlatformWindow::setWindowRole(const QString &role) { Q_UNUSED(role); }
+
+/*!
+  Reimplement to get the window role
+*/
+QString QPlatformWindow::windowRole() const { return QString(); }
+
+/*!
   Reimplement to be able to let Qt raise windows to the top of the desktop
 */
 void QPlatformWindow::raise() { qWarning("This plugin does not support raise()"); }
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 5c351a6..9e30b76 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -90,9 +90,12 @@ public:
     virtual void setWindowTitle(const QString &title);
     virtual void setWindowFilePath(const QString &title);
     virtual void setWindowIcon(const QIcon &icon);
+    virtual void setWindowRole(const QString &role);
     virtual void raise();
     virtual void lower();
 
+    virtual QString windowRole() const;
+
     virtual bool isExposed() const;
     virtual bool isActive() const;
     virtual bool isEmbedded(const QPlatformWindow *parentWindow) const;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 0094278..f8c2ff8 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -256,6 +256,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
     , m_lastWindowStateEvent(-1)
     , m_syncState(NoSyncNeeded)
     , m_pendingSyncRequest(0)
+    , m_windowRole()
 {
     m_screen = static_cast<QXcbScreen *>(window->screen()->handle());
 
@@ -1455,6 +1456,20 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
     }
 }
 
+void QXcbWindow::setWindowRole(const QString &role)
+{
+    const QByteArray ba = role.toLatin1();
+    Q_XCB_CALL(xcb_change_property(xcb_connection(),
+                                   XCB_PROP_MODE_REPLACE,
+                                   m_window,
+                                   atom(QXcbAtom::WM_WINDOW_ROLE),
+                                   XCB_ATOM_STRING,
+                                   8,
+                                   ba.length(),
+                                   ba.constData()));
+    m_windowRole = role;
+}
+
 void QXcbWindow::raise()
 {
     const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 254421e..d26efe2 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -88,8 +88,12 @@ public:
 
     void setWindowTitle(const QString &title);
     void setWindowIcon(const QIcon &icon);
+    void setWindowRole(const QString &role);
     void raise();
     void lower();
+
+    QString windowRole() const Q_DECL_OVERRIDE { return m_windowRole; }
+
     void propagateSizeHints();
 
     void requestActivateWindow();
@@ -234,6 +238,8 @@ private:
     SyncState m_syncState;
 
     QXcbSyncWindowRequest *m_pendingSyncRequest;
+
+    QString m_windowRole;
 };
 
 QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index c99e15b..c186e4d 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6226,8 +6226,11 @@ void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
 
 QString QWidget::windowRole() const
 {
-    Q_D(const QWidget);
-    return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
+    if (const QWindow *window = windowHandle())
+        if (QPlatformWindow *platformWindow = window->handle())
+            return platformWindow->windowRole();
+
+    return QString();
 }
 
 /*!
@@ -6236,13 +6239,9 @@ QString QWidget::windowRole() const
 */
 void QWidget::setWindowRole(const QString &role)
 {
-#if defined(Q_WS_X11)
-    Q_D(QWidget);
-    d->topData()->role = role;
-    d->setWindowRole();
-#else
-    Q_UNUSED(role)
-#endif
+    if (const QWindow *window = windowHandle())
+        if (QPlatformWindow *platformWindow = window->handle())
+            return platformWindow->setWindowRole(role);
 }
 
 /*!
-- 
2.4.0

