diff options
author | Gunnar Sletta <gunnar.sletta@nokia.com> | 2011-09-13 10:46:23 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@nokia.com> | 2011-09-13 10:46:23 +0200 |
commit | 21a2ce41a8efb6c5ab4ab2674458309bc9f031b7 (patch) | |
tree | 927045bf52f3367551cb4af17aa6b5738408c1bb /src/qt-compositor/wayland_wrapper/wldrag.cpp | |
parent | e47eb9057bf08834885ba6ef5e593d6f1844405c (diff) | |
parent | af711da1389c86c969d4872ec0936a90c46e1343 (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.cpp | 271 |
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) +{ +} + +} |