summaryrefslogtreecommitdiffstats
path: root/src/qt-compositor/wayland_wrapper/wldrag.cpp
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-09-13 10:46:23 +0200
committerGunnar Sletta <gunnar.sletta@nokia.com>2011-09-13 10:46:23 +0200
commit21a2ce41a8efb6c5ab4ab2674458309bc9f031b7 (patch)
tree927045bf52f3367551cb4af17aa6b5738408c1bb /src/qt-compositor/wayland_wrapper/wldrag.cpp
parente47eb9057bf08834885ba6ef5e593d6f1844405c (diff)
parentaf711da1389c86c969d4872ec0936a90c46e1343 (diff)
Merge branch 'refactor'
Conflicts: src/qt-compositor/compositor_api/waylandcompositor.cpp src/qt-compositor/wayland_wrapper/wloutput.cpp
Diffstat (limited to 'src/qt-compositor/wayland_wrapper/wldrag.cpp')
-rw-r--r--src/qt-compositor/wayland_wrapper/wldrag.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/qt-compositor/wayland_wrapper/wldrag.cpp b/src/qt-compositor/wayland_wrapper/wldrag.cpp
new file mode 100644
index 0000000..734d617
--- /dev/null
+++ b/src/qt-compositor/wayland_wrapper/wldrag.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** 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 "wldrag.h"
+#include "wlcompositor.h"
+#include "wlsurface.h"
+#include <wayland-util.h>
+#include <string.h>
+#include <unistd.h>
+#include <QDebug>
+
+namespace Wayland {
+
+void Drag::dragOfferAccept(struct wl_client *client,
+ struct wl_drag_offer *offer, uint32_t time, const char *type)
+{
+ qDebug() << "dragOfferAccept" << client << offer << type;
+ Q_UNUSED(time);
+ Drag *self = Drag::instance();
+ struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
+ drag->target = client;
+ QString wantedType = QString::fromLatin1(type);
+ if (!self->m_offerList.contains(wantedType)) {
+ qWarning("dragOfferAccept: Client accepted type '%s' that has not been offered",
+ qPrintable(type));
+ type = 0;
+ }
+ wl_client_post_event(drag->source->client, &drag->resource.object,
+ WL_DRAG_TARGET, type);
+}
+
+void Drag::dragOfferReceive(struct wl_client *client,
+ struct wl_drag_offer *offer, int fd)
+{
+ qDebug() << "dragOfferReceive" << client << offer << fd;
+ Q_UNUSED(client);
+ struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
+ wl_client_post_event(drag->source->client, &drag->resource.object,
+ WL_DRAG_FINISH, fd);
+ close(fd);
+}
+
+void Drag::dragOfferReject(struct wl_client *client, struct wl_drag_offer *offer)
+{
+ qDebug() << "dragOfferReject" << client << offer;
+ Q_UNUSED(client);
+ struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
+ if (drag->target == client)
+ drag->target = 0;
+ wl_client_post_event(drag->source->client, &drag->resource.object,
+ WL_DRAG_REJECT);
+}
+
+const struct wl_drag_offer_interface Drag::dragOfferInterface = {
+ Drag::dragOfferAccept,
+ Drag::dragOfferReceive,
+ Drag::dragOfferReject
+};
+
+void Drag::dragOffer(struct wl_client *client, struct wl_drag *drag, const char *type)
+{
+ qDebug() << "dragOffer" << client << drag << type;
+ Q_UNUSED(client);
+ Q_UNUSED(drag);
+ instance()->m_offerList.append(QString::fromLatin1(type));
+}
+
+void Drag::dragActivate(struct wl_client *client,
+ struct wl_drag *drag,
+ struct wl_surface *surface,
+ struct wl_input_device *device, uint32_t time)
+{
+ qDebug() << "dragActivate" << client << drag << surface;
+ Q_UNUSED(client);
+ Q_UNUSED(device);
+ Q_UNUSED(time);
+ Drag *self = Drag::instance();
+ drag->source = surface;
+ drag->drag_offer.object.interface = &wl_drag_offer_interface;
+ drag->drag_offer.object.implementation = (void (**)()) &dragOfferInterface;
+ wl_display *dpy = Compositor::instance()->wl_display();
+ wl_display_add_object(dpy, &drag->drag_offer.object);
+ wl_display_add_global(dpy, &drag->drag_offer.object, 0);
+ Surface *focus = Compositor::instance()->pointerFocus();
+ QPoint pos;
+ if (focus)
+ pos = focus->lastMousePos();
+ // ### Sending local as global, which is wrong, but oh well.
+ self->setPointerFocus(surface, pos, pos);
+}
+
+void Drag::setPointerFocus(wl_surface *surface, const QPoint &global, const QPoint &local)
+{
+ if (!m_drag)
+ return;
+
+ if (m_drag->drag_focus == surface)
+ return;
+
+ uint timestamp = Compositor::currentTimeMsecs();
+ if (m_drag->drag_focus
+ && (!surface || m_drag->drag_focus->client != surface->client)) {
+ qDebug() << "WL_DRAG_OFFER_POINTER_FOCUS with null";
+ wl_client_post_event(m_drag->drag_focus->client,
+ &m_drag->drag_offer.object,
+ WL_DRAG_OFFER_POINTER_FOCUS,
+ timestamp, 0, 0, 0, 0, 0);
+ }
+ if (surface
+ && (!m_drag->drag_focus || m_drag->drag_focus->client != surface->client)) {
+ wl_client_post_global(surface->client,
+ &m_drag->drag_offer.object);
+ foreach (const QString &format, m_offerList) {
+ QByteArray mimeTypeBa = format.toLatin1();
+ qDebug() << "WL_DRAG_OFFER_OFFER" << mimeTypeBa;
+ wl_client_post_event(surface->client, &m_drag->drag_offer.object,
+ WL_DRAG_OFFER_OFFER, mimeTypeBa.constData());
+ }
+ }
+
+ if (surface) {
+ qDebug() << "WL_DRAG_OFFER_POINTER_FOCUS" << surface << global << local;
+ wl_client_post_event(surface->client,
+ &m_drag->drag_offer.object,
+ WL_DRAG_OFFER_POINTER_FOCUS,
+ timestamp, surface,
+ global.x(), global.y(), local.x(), local.y());
+ Compositor::instance()->m_dragActive = true;
+ }
+
+ m_drag->drag_focus = surface;
+ m_drag->target = 0;
+}
+
+void Drag::dragDestroy(struct wl_client *client, struct wl_drag *drag)
+{
+ qDebug() << "dragDestroy";
+ wl_resource_destroy(&drag->resource, client, Compositor::currentTimeMsecs());
+}
+
+const struct wl_drag_interface Drag::dragInterface = {
+ Drag::dragOffer,
+ Drag::dragActivate,
+ Drag::dragDestroy
+};
+
+void Drag::destroyDrag(struct wl_resource *resource, struct wl_client *client)
+{
+ Q_UNUSED(client);
+ struct wl_drag *drag = container_of(resource, struct wl_drag, resource);
+ wl_display *dpy = Compositor::instance()->wl_display();
+ wl_display_remove_global(dpy, &drag->drag_offer.object);
+ delete drag;
+}
+
+void Drag::create(struct wl_client *client, uint32_t id)
+{
+ Q_UNUSED(client);
+ m_offerList.clear();
+ wl_drag *drag = new wl_drag;
+ memset(drag, 0, sizeof *drag);
+ drag->resource.object.id = id;
+ drag->resource.object.interface = &wl_drag_interface;
+ drag->resource.object.implementation = (void (**)()) &dragInterface;
+ drag->resource.destroy = destroyDrag;
+ wl_client_add_resource(client, &drag->resource);
+ m_drag = drag;
+}
+
+void Drag::done(bool sending)
+{
+ qDebug() << "drag done";
+ Compositor::instance()->m_dragActive = false;
+ if (!sending) {
+ setPointerFocus(0, QPoint(), QPoint());
+ // ### hack: Send a pointerFocus with null surface to the source too, this is
+ // mandatory even if the previous pointerFocus went to the same client, otherwise
+ // Qt will not know the drag is over without a drop.
+ wl_client_post_event(m_drag->source->client,
+ &m_drag->drag_offer.object,
+ WL_DRAG_OFFER_POINTER_FOCUS,
+ Compositor::instance()->currentTimeMsecs(),
+ 0, 0, 0, 0, 0);
+ }
+ m_drag = 0;
+}
+
+void Drag::dragMove(const QPoint &global, const QPoint &local, Surface *surface)
+{
+ if (!m_drag)
+ return;
+// qDebug() << "dragMove" << global << local << surface;
+ if (surface) {
+ setPointerFocus(surface->base(), global, local);
+ uint timestamp = Compositor::currentTimeMsecs();
+ wl_client_post_event(surface->base()->client,
+ &m_drag->drag_offer.object,
+ WL_DRAG_OFFER_MOTION,
+ timestamp,
+ global.x(), global.y(), local.x(), local.y());
+ } else {
+ setPointerFocus(0, global, local);
+ }
+}
+
+void Drag::dragEnd()
+{
+ qDebug() << "dragEnd";
+ if (!m_drag)
+ return;
+ if (m_drag->target) {
+ qDebug() << "WL_DRAG_OFFER_DROP" << m_drag->target;
+ wl_client_post_event(m_drag->target,
+ &m_drag->drag_offer.object,
+ WL_DRAG_OFFER_DROP);
+ done(true);
+ } else {
+ done(false);
+ }
+}
+
+Q_GLOBAL_STATIC(Drag, globalInstance)
+
+Drag *Drag::instance()
+{
+ return globalInstance();
+}
+
+Drag::Drag()
+ : m_drag(0)
+{
+}
+
+}