Added clipboard support.
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Fri, 6 May 2011 16:37:10 +0000 (18:37 +0200)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>
Mon, 9 May 2011 08:29:57 +0000 (10:29 +0200)
examples/qml-compositor/qml-compositor.pro
examples/qwidget-compositor/qt-compositor.pro
src/qt-compositor/wayland_wrapper/wayland_wrapper.pri
src/qt-compositor/wayland_wrapper/wlcompositor.cpp
src/qt-compositor/wayland_wrapper/wlcompositor.h
src/qt-compositor/wayland_wrapper/wlselection.cpp [new file with mode: 0644]
src/qt-compositor/wayland_wrapper/wlselection.h [new file with mode: 0644]

index 8fb49fb..7e6032c 100644 (file)
@@ -12,6 +12,8 @@ CONFIG += use_pkgconfig
 
 DESTDIR=$$PWD/../../bin/
 
+QT += core-private gui-private declarative-private opengl-private
+
 LIBS += -L ../../lib
 
 QT += declarative
index bd921a4..c2089af 100644 (file)
@@ -6,6 +6,8 @@ INCLUDEPATH += .
 # comment out the following to not use pkg-config in the pri files
 CONFIG += use_pkgconfig
 
+QT += core-private gui-private
+
 DESTDIR=$$PWD/../../bin/
 
 include (../../src/qt-compositor/qt-compositor.pri)
index c65dffb..3d4fae5 100644 (file)
@@ -3,11 +3,13 @@ HEADERS += \
     $$PWD/wldisplay.h \
     $$PWD/wloutput.h \
     $$PWD/wlshmbuffer.h \
-    $$PWD/wlsurface.h
+    $$PWD/wlsurface.h \
+    ../../src/qt-compositor/wayland_wrapper/wlselection.h
 
 SOURCES += \
     $$PWD/wlcompositor.cpp \
     $$PWD/wldisplay.cpp \
     $$PWD/wloutput.cpp \
     $$PWD/wlshmbuffer.cpp \
-    $$PWD/wlsurface.cpp
+    $$PWD/wlsurface.cpp \
+    ../../src/qt-compositor/wayland_wrapper/wlselection.cpp
index c6b1f41..3e8111c 100644 (file)
@@ -44,6 +44,7 @@
 #include "wldisplay.h"
 #include "wlshmbuffer.h"
 #include "wlsurface.h"
+#include "wlselection.h"
 #include "waylandcompositor.h"
 
 #include <QApplication>
@@ -150,10 +151,9 @@ void shell_selection(struct wl_client *client,
                      struct wl_shell *shell,
                      uint32_t id)
 {
-    Q_UNUSED(client);
-    Q_UNUSED(shell);
-    Q_UNUSED(id);
     qDebug() << "shellSelection";
+    Q_UNUSED(shell);
+    Selection::instance()->create(client, id);
 }
 
 const static struct wl_shell_interface shell_interface = {
@@ -163,6 +163,13 @@ const static struct wl_shell_interface shell_interface = {
     shell_selection
 };
 
+static Compositor *compositor;
+
+Compositor *Compositor::instance()
+{
+    return compositor;
+}
+
 Compositor::Compositor(WaylandCompositor *qt_compositor)
     : m_display(new Display)
     , m_shm(m_display)
@@ -173,6 +180,8 @@ Compositor::Compositor(WaylandCompositor *qt_compositor)
     , m_keyFocusSurface(0)
     , m_directRenderSurface(0)
 {
+    compositor = this;
+
 #if defined (QT_COMPOSITOR_WAYLAND_GL)
     m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor);
 #endif
@@ -227,7 +236,10 @@ void Compositor::createSurface(struct wl_client *client, int id)
 
     m_qt_compositor->surfaceCreated(surface->handle());
 
+    QList<struct wl_client *> prevClientList = clients();
     m_surfaces << surface;
+    if (!prevClientList.contains(client))
+        emit clientAdded(client);
 }
 
 struct wl_client *Compositor::getClientFromWinId(uint winId) const
@@ -357,6 +369,16 @@ bool Compositor::setDirectRenderSurface(Surface *surface)
     return false;
 }
 
+QList<struct wl_client *> Compositor::clients() const
+{
+    QList<struct wl_client *> list;
+    foreach (Surface *surface, m_surfaces) {
+        struct wl_client *client = surface->base()->client;
+        if (!list.contains(client))
+            list.append(client);
+    }
+    return list;
+}
 
 }
 
@@ -364,4 +386,3 @@ wl_input_device * Wayland::Compositor::defaultInputDevice()
 {
     return &m_input;
 }
-
index ac107d9..8964472 100644 (file)
@@ -94,6 +94,16 @@ public:
 
     wl_input_device *defaultInputDevice();
     WaylandCompositor *qtCompositor() const { return m_qt_compositor; }
+
+    struct wl_display *wl_display() { return m_display->handle(); }
+
+    static Compositor *instance();
+
+    QList<struct wl_client *> clients() const;
+
+signals:
+    void clientAdded(wl_client *client);
+
 private slots:
     void processWaylandEvents();
 
diff --git a/src/qt-compositor/wayland_wrapper/wlselection.cpp b/src/qt-compositor/wayland_wrapper/wlselection.cpp
new file mode 100644 (file)
index 0000000..86f15ba
--- /dev/null
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact:  Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#include "wlselection.h"
+#include "wlcompositor.h"
+#include <wayland-util.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace Wayland {
+
+void Selection::send(struct wl_client *client,
+                     struct wl_selection_offer *offer,
+                     const char *mime_type, int fd)
+{
+    Q_UNUSED(client);
+    struct wl_selection *selection = container_of(offer, struct wl_selection, selection_offer);
+    wl_client_post_event(selection->client,
+                         &selection->resource.object,
+                         WL_SELECTION_SEND, mime_type, fd);
+    close(fd);
+}
+
+const struct wl_selection_offer_interface Selection::selectionOfferInterface = {
+    Selection::send
+};
+
+void Selection::selOffer(struct wl_client *client,
+                         struct wl_selection *selection,
+                         const char *type)
+{
+    Q_UNUSED(client);
+    Q_UNUSED(selection);
+    instance()->m_offerList.append(QString::fromLatin1(type));
+}
+
+void Selection::selActivate(struct wl_client *client,
+                            struct wl_selection *selection,
+                            struct wl_input_device *device,
+                            uint32_t time)
+{
+    Q_UNUSED(client);
+    Q_UNUSED(device);
+    Q_UNUSED(time);
+    Selection *self = Selection::instance();
+
+    selection->selection_offer.object.interface = &wl_selection_offer_interface;
+    selection->selection_offer.object.implementation = (void (**)()) &selectionOfferInterface;
+    wl_display_add_object(Compositor::instance()->wl_display(), &selection->selection_offer.object);
+
+    QList<struct wl_client *> clients = Compositor::instance()->clients();
+    if (self->m_currentSelection) {
+        if (!clients.contains(self->m_currentSelection->client))
+            self->m_currentSelection = 0;
+        else
+            wl_client_post_event(self->m_currentSelection->client,
+                                 &self->m_currentSelection->resource.object,
+                                 WL_SELECTION_CANCELLED);
+    }
+    self->m_currentSelection = selection;
+
+    if (self->m_currentOffer) {
+        foreach (struct wl_client *client, clients) {
+            wl_client_post_event(client, &self->m_currentOffer->object,
+                                 WL_SELECTION_OFFER_KEYBOARD_FOCUS, 0);
+        }
+    }
+    self->m_currentOffer = &selection->selection_offer;
+    foreach (struct wl_client *client, clients) {
+        wl_client_post_global(client, &selection->selection_offer.object);
+    }
+    foreach (struct wl_client *client, clients) {
+        foreach (const QString &mimeType, self->m_offerList) {
+            QByteArray mimeTypeBa = mimeType.toLatin1();
+            wl_client_post_event(client, &selection->selection_offer.object,
+                                 WL_SELECTION_OFFER_OFFER, mimeTypeBa.constData());
+        }
+    }
+    foreach (struct wl_client *client, clients) {
+        wl_client_post_event(client, &selection->selection_offer.object,
+                             WL_SELECTION_OFFER_KEYBOARD_FOCUS, selection->input_device);
+    }
+}
+
+void Selection::selDestroy(struct wl_client *client, struct wl_selection *selection)
+{
+    wl_resource_destroy(&selection->resource, client);
+}
+
+const struct wl_selection_interface Selection::selectionInterface = {
+    Selection::selOffer,
+    Selection::selActivate,
+    Selection::selDestroy
+};
+
+void Selection::destroySelection(struct wl_resource *resource, struct wl_client *client)
+{
+    Q_UNUSED(client);
+    struct wl_selection *selection = container_of(resource, struct wl_selection, resource);
+    Selection *self = Selection::instance();
+    if (self->m_currentSelection == selection)
+        self->m_currentSelection = 0;
+    if (self->m_currentOffer == &selection->selection_offer) {
+        QList<struct wl_client *> clients = Compositor::instance()->clients();
+        foreach (struct wl_client *client, clients) {
+            wl_client_post_event(client, &selection->selection_offer.object,
+                                 WL_SELECTION_OFFER_KEYBOARD_FOCUS, 0);
+        }
+        self->m_currentOffer = 0;
+        self->m_offerList.clear();
+    }
+    delete selection;
+}
+
+void Selection::create(struct wl_client *client, uint32_t id)
+{
+    struct wl_selection *selection = new struct wl_selection;
+    m_offerList.clear();
+    memset(selection, 0, sizeof *selection);
+    selection->resource.object.id = id;
+    selection->resource.object.interface = &wl_selection_interface;
+    selection->resource.object.implementation = (void (**)()) &selectionInterface;
+    selection->resource.destroy = destroySelection;
+    selection->client = client;
+    selection->input_device = Compositor::instance()->inputDevice();
+    wl_client_add_resource(client, &selection->resource);
+}
+
+void Selection::onClientAdded(wl_client *client)
+{
+    if (m_currentSelection && m_currentOffer) {
+        wl_client_post_global(client, &m_currentOffer->object);
+        foreach (const QString &mimeType, m_offerList) {
+            QByteArray mimeTypeBa = mimeType.toLatin1();
+            wl_client_post_event(client, &m_currentOffer->object,
+                                 WL_SELECTION_OFFER_OFFER, mimeTypeBa.constData());
+        }
+        wl_client_post_event(client, &m_currentOffer->object,
+                             WL_SELECTION_OFFER_KEYBOARD_FOCUS, m_currentSelection->input_device);
+    }
+}
+
+Q_GLOBAL_STATIC(Selection, globalInstance)
+
+Selection *Selection::instance()
+{
+    return globalInstance();
+}
+
+Selection::Selection()
+    : m_currentSelection(0), m_currentOffer(0)
+{
+    connect(Compositor::instance(), SIGNAL(clientAdded(wl_client*)), SLOT(onClientAdded(wl_client*)));
+}
+
+}
diff --git a/src/qt-compositor/wayland_wrapper/wlselection.h b/src/qt-compositor/wayland_wrapper/wlselection.h
new file mode 100644 (file)
index 0000000..761444c
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact:  Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#ifndef WLSELECTION_H
+#define WLSELECTION_H
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <wayland-server.h>
+
+namespace Wayland {
+
+class Selection : public QObject
+{
+    Q_OBJECT
+
+public:
+    static Selection *instance();
+    Selection();
+    void create(struct wl_client *client, uint32_t id);
+
+private slots:
+    void onClientAdded(wl_client *client);
+
+private:
+    static void destroySelection(struct wl_resource *resource, struct wl_client *client);
+    static void selOffer(struct wl_client *client,
+                         struct wl_selection *selection,
+                         const char *type);
+    static void selActivate(struct wl_client *client,
+                            struct wl_selection *selection,
+                            struct wl_input_device *device,
+                            uint32_t time);
+    static void selDestroy(struct wl_client *client, struct wl_selection *selection);
+    static const struct wl_selection_interface selectionInterface;
+    static void send(struct wl_client *client,
+                     struct wl_selection_offer *offer,
+                     const char *mime_type, int fd);
+    static const struct wl_selection_offer_interface selectionOfferInterface;
+
+    QStringList m_offerList;
+    struct wl_selection *m_currentSelection;
+    struct wl_selection_offer *m_currentOffer;
+};
+
+}
+
+#endif // WLSELECTION_H