Support for generic window properties
authorLasse Holmstedt <lasse.holmstedt@nokia.com>
Wed, 31 Aug 2011 08:00:10 +0000 (10:00 +0200)
committerLasse Holmstedt <lasse.holmstedt@nokia.com>
Tue, 6 Sep 2011 07:47:09 +0000 (09:47 +0200)
Wayland surfaces can now contain window-specific properties,
which are read/writable from both server and client side.

Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/qt-compositor/compositor_api/waylandsurface.cpp
src/qt-compositor/compositor_api/waylandsurface.h
src/qt-compositor/wayland_wrapper/wlcompositor.cpp
src/qt-compositor/wayland_wrapper/wlcompositor.h
src/qt-compositor/wayland_wrapper/wlsurface.cpp
src/qt-compositor/wayland_wrapper/wlsurface.h
src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c
src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h
src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp
src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h
src/qt-compositor/windowmanagerprotocol/windowmanager.xml

index bb8104f..f16a03f 100644 (file)
@@ -83,6 +83,18 @@ QByteArray WaylandSurface::authenticationToken() const
     return d->surface->authenticationToken();
 }
 
+QVariantMap WaylandSurface::windowProperties() const
+{
+    Q_D(const WaylandSurface);
+    return d->surface->windowProperties();
+}
+
+void WaylandSurface::setWindowProperty(const QString &name, const QVariant &value)
+{
+    Q_D(WaylandSurface);
+    d->surface->setWindowProperty(name, value);
+}
+
 void WaylandSurface::sendMousePressEvent(const QPoint &pos, Qt::MouseButton button)
 {
     Q_D(WaylandSurface);
index 4c46565..dd6685b 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <QtCore/QScopedPointer>
 #include <QtGui/QImage>
+#include <QtCore/QVariantMap>
 
 #ifdef QT_COMPOSITOR_WAYLAND_GL
 #include <QtOpenGL/QGLContext>
@@ -101,6 +102,8 @@ public:
     Wayland::Surface *handle() const;
     qint64 processId() const;
     QByteArray authenticationToken() const;
+    QVariantMap windowProperties() const;
+    void setWindowProperty(const QString &name, const QVariant &value);
 
 signals:
     void mapped(const QSize &size);
index 65c074f..f76701e 100644 (file)
@@ -216,6 +216,9 @@ Compositor::Compositor(WaylandCompositor *qt_compositor)
         m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor);
 #endif
     m_windowManagerWaylandProtocol = new WindowManagerServerIntegration(this);
+    connect(m_windowManagerWaylandProtocol,
+            SIGNAL(windowPropertyChanged(wl_client*,wl_surface*,QString,QVariant)),
+            SLOT(windowPropertyChanged(wl_client*,wl_surface*,QString,QVariant)));
 
     if (wl_compositor_init(base(), &compositor_interface, m_display->handle())) {
         fprintf(stderr, "Fatal: Error initializing compositor\n");
@@ -268,7 +271,7 @@ void Compositor::createSurface(struct wl_client *client, int id)
     addClientResource(client, &surface->base()->resource, id, &wl_surface_interface,
             &surface_interface, destroy_surface);
 
-        m_windowManagerWaylandProtocol->updateOrientation(client);
+    m_windowManagerWaylandProtocol->updateOrientation(client);
     m_qt_compositor->surfaceCreated(surface->handle());
 
     QList<struct wl_client *> prevClientList = clients();
@@ -325,6 +328,15 @@ void Compositor::processWaylandEvents()
         fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret);
 }
 
+void Compositor::windowPropertyChanged(wl_client *client, wl_surface *changedSurface, const QString &name, const QVariant &value)
+{
+    for(int i = 0; i < m_surfaces.length(); ++i) {
+        Surface *surface = m_surfaces[i];
+        if (surface->clientHandle() == client && surface->base() == changedSurface) {
+            surface->setWindowProperty(name, value, false);
+        }
+    }
+}
 
 void Compositor::surfaceDestroyed(Surface *surface)
 {
index be63a94..39404bc 100644 (file)
@@ -114,6 +114,7 @@ signals:
 
 private slots:
     void processWaylandEvents();
+    void windowPropertyChanged(wl_client *client, wl_surface *surface, const QString &name, const QVariant &value);
 
 private:
     Display *m_display;
index 9aae731..def50b4 100644 (file)
@@ -117,6 +117,7 @@ public:
     wl_buffer *directRenderBuffer;
     qint64 processId;
     QByteArray authenticationToken;
+    QVariantMap windowProperties;
 
 private:
     struct wl_buffer *surfaceBuffer;
@@ -273,6 +274,27 @@ QByteArray Surface::authenticationToken() const
     return WindowManagerServerIntegration::instance()->managedClient(d->client)->authenticationToken();
 }
 
+QVariantMap Surface::windowProperties() const
+{
+    Q_D(const Surface);
+    return d->windowProperties;
+}
+
+QVariant Surface::windowProperty(const QString &propertyName) const
+{
+    Q_D(const Surface);
+    QVariantMap props = d->windowProperties;
+    return props.value(propertyName);
+}
+
+void Surface::setWindowProperty(const QString &name, const QVariant &value, bool writeUpdateToClient)
+{
+    Q_D(Surface);
+    d->windowProperties.insert(name, value);
+    if (writeUpdateToClient)
+        WindowManagerServerIntegration::instance()->setWindowProperty(d->client, base(), name, value);
+}
+
 uint32_t toWaylandButton(Qt::MouseButton button)
 {
     switch (button) {
index 9633f43..c921496 100644 (file)
@@ -105,6 +105,10 @@ public:
     void setProcessId(qint64 processId);
     QByteArray authenticationToken() const;
 
+    QVariantMap windowProperties() const;
+    QVariant windowProperty(const QString &propertyName) const;
+    void setWindowProperty(const QString &name, const QVariant &value, bool writeUpdateToClient = true);
+
     void setSurfaceCreationFinished(bool isCreated);
 
 protected:
index fcafacd..1d231f5 100644 (file)
@@ -1,38 +1,29 @@
-/*
- * Copyright © 2010 Kristian Høgsberg
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-
 #include <stdlib.h>
 #include <stdint.h>
 #include "wayland-util.h"
 
+extern const struct wl_interface wl_surface_interface;
+
+static const struct wl_interface *types[] = {
+       NULL,
+       &wl_surface_interface,
+       NULL,
+       NULL,
+       &wl_surface_interface,
+       NULL,
+       NULL,
+};
+
 static const struct wl_message wl_windowmanager_requests[] = {
-       { "map_client_to_process", "u", NULL },
-       { "authenticate_with_token", "s", NULL },
+       { "map_client_to_process", "u", types + 0 },
+       { "authenticate_with_token", "s", types + 0 },
+       { "update_generic_property", "osa", types + 1 },
 };
 
 static const struct wl_message wl_windowmanager_events[] = {
-       { "client_onscreen_visibility", "i", NULL },
-       { "set_screen_rotation", "i", NULL },
+       { "client_onscreen_visibility", "i", types + 0 },
+       { "set_screen_rotation", "i", types + 0 },
+       { "set_generic_property", "osa", types + 4 },
 };
 
 WL_EXPORT const struct wl_interface wl_windowmanager_interface = {
index acc94ec..e1e55e8 100644 (file)
@@ -1,26 +1,3 @@
-/*
- * Copyright © 2010 Kristian Høgsberg
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-
 #ifndef WAYLAND_WINDOWMANAGER_SERVER_PROTOCOL_H
 #define WAYLAND_WINDOWMANAGER_SERVER_PROTOCOL_H
 
@@ -45,10 +22,16 @@ struct wl_windowmanager_interface {
        void (*authenticate_with_token)(struct wl_client *client,
                                        struct wl_windowmanager *wl_windowmanager,
                                        const char *processid);
+       void (*update_generic_property)(struct wl_client *client,
+                                       struct wl_windowmanager *wl_windowmanager,
+                                       struct wl_surface *surface,
+                                       const char *name,
+                                       struct wl_array *value);
 };
 
 #define WL_WINDOWMANAGER_CLIENT_ONSCREEN_VISIBILITY    0
 #define WL_WINDOWMANAGER_SET_SCREEN_ROTATION   1
+#define WL_WINDOWMANAGER_SET_GENERIC_PROPERTY  2
 
 #ifdef  __cplusplus
 }
index 5fb9ea0..8df72ee 100644 (file)
@@ -61,13 +61,11 @@ public:
 
     void mapClientToProcess(wl_client *client, uint32_t processId)
     {
-        //qDebug() << "COMPOSITOR:" << Q_FUNC_INFO << client << processId;
         WindowManagerServerIntegration::instance()->mapClientToProcess(client, processId);
     }
 
     void authenticateWithToken(wl_client *client, const char *authenticationToken)
     {
-        //qDebug() << "COMPOSITOR:" << Q_FUNC_INFO << client << authenticationToken;
         WindowManagerServerIntegration::instance()->authenticateWithToken(client, authenticationToken);
     }
 
@@ -76,6 +74,11 @@ public:
         WindowManagerServerIntegration::instance()->changeScreenVisibility(client, visible);
     }
 
+    void updateWindowProperty(wl_client *client, wl_surface *surface, const char *name, struct wl_array *value)
+    {
+        WindowManagerServerIntegration::instance()->updateWindowProperty(client, surface, name, value);
+    }
+
 };
 
 void map_client_to_process(wl_client *client, struct wl_windowmanager *windowMgr, uint32_t processId)
@@ -88,9 +91,15 @@ void authenticate_with_token(wl_client *client, struct wl_windowmanager *windowM
     reinterpret_cast<WindowManagerObject *>(windowMgr)->authenticateWithToken(client, wl_authentication_token);
 }
 
+void update_generic_property(wl_client *client, struct wl_windowmanager *windowMgr, wl_surface *surface, const char *name, struct wl_array *value)
+{
+    reinterpret_cast<WindowManagerObject *>(windowMgr)->updateWindowProperty(client, surface, name, value);
+}
+
 const static struct wl_windowmanager_interface windowmanager_interface = {
     map_client_to_process,
-    authenticate_with_token
+    authenticate_with_token,
+    update_generic_property
 };
 
 WindowManagerServerIntegration *WindowManagerServerIntegration::m_instance = 0;
@@ -141,16 +150,42 @@ void WindowManagerServerIntegration::changeScreenVisibility(wl_client *client, i
                          WL_WINDOWMANAGER_CLIENT_ONSCREEN_VISIBILITY, visible);
 }
 
+void WindowManagerServerIntegration::setScreenOrientation(wl_client *client, qint32 orientationInDegrees)
+{
+    m_orientationInDegrees = orientationInDegrees;
+    wl_client_post_event(client, m_windowManagerObject->base(),
+                         WL_WINDOWMANAGER_SET_SCREEN_ROTATION, orientationInDegrees);
+}
+
 void WindowManagerServerIntegration::updateOrientation(wl_client *client)
 {
     setScreenOrientation(client, m_orientationInDegrees);
 }
 
-void WindowManagerServerIntegration::setScreenOrientation(wl_client *client, qint32 orientationInDegrees)
+// client -> server
+void WindowManagerServerIntegration::updateWindowProperty(wl_client *client, wl_surface *surface, const char *name, struct wl_array *value)
 {
-    m_orientationInDegrees = orientationInDegrees;
+    QVariant variantValue;
+    QByteArray byteValue((const char*)value->data, value->size);
+    QDataStream ds(&byteValue, QIODevice::ReadOnly);
+    ds >> variantValue;
+
+    emit windowPropertyChanged(client, surface, QString(name), variantValue);
+}
+
+// server -> client
+void WindowManagerServerIntegration::setWindowProperty(wl_client *client, wl_surface *surface, const QString &name, const QVariant &value)
+{
+    QByteArray byteValue;
+    QDataStream ds(&byteValue, QIODevice::WriteOnly);
+    ds << value;
+    wl_array data;
+    data.size = byteValue.size();
+    data.data = (void*) byteValue.constData();
+    data.alloc = 0;
+
     wl_client_post_event(client, m_windowManagerObject->base(),
-                         WL_WINDOWMANAGER_SET_SCREEN_ROTATION, orientationInDegrees);
+                         WL_WINDOWMANAGER_SET_GENERIC_PROPERTY, surface, name.toLatin1().constData(), &data);
 }
 
 WaylandManagedClient *WindowManagerServerIntegration::managedClient(wl_client *client) const
index be7c609..dc1e97b 100644 (file)
@@ -47,7 +47,7 @@
 
 #include <QObject>
 #include <QMap>
-
+#include <QVariant>
 
 struct wl_client;
 
@@ -73,9 +73,12 @@ public:
     void setScreenOrientation(wl_client *client, qint32 orientationInDegrees);
     void updateOrientation(wl_client *client);
 
+    void updateWindowProperty(wl_client *client, struct wl_surface *surface, const char *name, struct wl_array *value);
+    void setWindowProperty(wl_client *client, struct wl_surface *surface, const QString &name, const QVariant &value);
 
 signals:
     void clientAuthenticated(wl_client *client);
+    void windowPropertyChanged(wl_client *client, struct wl_surface *surface, const QString &name, const QVariant &value);
 
 private:
     void mapClientToProcess(wl_client *client, uint32_t processId);
@@ -97,8 +100,8 @@ public:
     WaylandManagedClient();
     qint64 processId() const;
     QByteArray authenticationToken() const;
+    // ## TODO must be moved to Surface
     bool isVisibleOnScreen() const { return m_isVisibleOnScreen; }
-    qint32 orientation() const;
 
 private:
     qint64 m_processId;
index 7356e42..f69f658 100644 (file)
         <event name="set_screen_rotation">
             <arg name="rotation" type="int"/>
         </event>
+
+        <!--sends a generic property to the client -->
+        <event name="set_generic_property">
+            <arg name="surface" type="object" interface="wl_surface"/>
+            <arg name="name" type="string"/>
+            <arg name="value" type="array"/>
+        </event>
+
+        <!-- update generic property from client to server -->
+        <request name="update_generic_property">
+            <arg name="surface" type="object" interface="wl_surface"/>
+            <arg name="name" type="string"/>
+            <arg name="value" type="array"/>
+        </request>
     </interface>
 </protocol>