/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qxcbdrag.h"
#include <xcb/xcb.h>
#include "qxcbconnection.h"
#include "qxcbclipboard.h"
#include "qxcbmime.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
#include "qwindow.h"
#include "qxcbcursor.h"
#include <private/qdnd_p.h>
#include <qdebug.h>
#include <qevent.h>
#include <qguiapplication.h>
#include <qrect.h>
#include <qpainter.h>
#include <qtimer.h>

#include <qpa/qwindowsysteminterface.h>

#include <private/qguiapplication_p.h>
#include <private/qshapedpixmapdndwindow_p.h>
#include <private/qsimpledrag_p.h>
#include <private/qhighdpiscaling_p.h>

QT_BEGIN_NAMESPACE

const int xdnd_version = 5;

static inline xcb_window_t xcb_window(QPlatformWindow *w)
{
    return static_cast<QXcbWindow *>(w)->xcb_window();
}

static inline xcb_window_t xcb_window(QWindow *w)
{
    return static_cast<QXcbWindow *>(w->handle())->xcb_window();
}

static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
{
    xcb_window_t proxy = XCB_NONE;

    auto reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(),
                             false, w, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1);

    if (reply && reply->type == XCB_ATOM_WINDOW)
        proxy = *((xcb_window_t *)xcb_get_property_value(reply.get()));

    if (proxy == XCB_NONE)
        return proxy;

    // exists and is real?
    reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(),
                        false, proxy, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1);

    if (reply && reply->type == XCB_ATOM_WINDOW) {
        xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply.get()));
        if (proxy != p)
            proxy = 0;
    } else {
        proxy = 0;
    }

    return proxy;
}

class QXcbDropData : public QXcbMime
{
public:
    QXcbDropData(QXcbDrag *d);
    ~QXcbDropData();

protected:
    bool hasFormat_sys(const QString &mimeType) const override;
    QStringList formats_sys() const override;
    QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const override;

    QVariant xdndObtainData(const QByteArray &format, QMetaType::Type requestedType) const;

    QXcbDrag *drag;
};


QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)
{
    m_dropData = new QXcbDropData(this);

    init();
    cleanup_timer = -1;
}

QXcbDrag::~QXcbDrag()
{
    delete m_dropData;
}

void QXcbDrag::init()
{
    currentWindow.clear();

    accepted_drop_action = Qt::IgnoreAction;

    xdnd_dragsource = XCB_NONE;

    waiting_for_status = false;
    current_target = XCB_NONE;
    current_proxy_target = XCB_NONE;

    source_time = XCB_CURRENT_TIME;
    target_time = XCB_CURRENT_TIME;

    QXcbCursor::queryPointer(connection(), &current_virtual_desktop, nullptr);
    drag_types.clear();

    //current_embedding_widget = 0;

    dropped = false;
    canceled = false;

    source_sameanswer = QRect();
}

bool QXcbDrag::eventFilter(QObject *o, QEvent *e)
{
    /* We are setting a mouse grab on the QShapedPixmapWindow in order not to
     * lose the grab when the virtual desktop changes, but
     * QBasicDrag::eventFilter() expects the events to be coming from the
     * window where the drag was started. */
    if (initiatorWindow && o == shapedPixmapWindow())
        o = initiatorWindow.data();
    return QBasicDrag::eventFilter(o, e);
}

void QXcbDrag::startDrag()
{
    init();

#ifndef QT_NO_CLIPBOARD
    qCDebug(lcQpaXDnd) << "starting drag where source:" << connection()->clipboard()->owner();
    xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(),
                            atom(QXcbAtom::XdndSelection), connection()->time());
#endif

    QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
    for (int i = 0; i < fmts.size(); ++i) {
        QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
        for (int j = 0; j < atoms.size(); ++j) {
            if (!drag_types.contains(atoms.at(j)))
                drag_types.append(atoms.at(j));
        }
    }
#ifndef QT_NO_CLIPBOARD
    if (drag_types.size() > 3)
        xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(),
                            atom(QXcbAtom::XdndTypelist),
                            XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());
#endif

    setUseCompositing(current_virtual_desktop->compositingActive());
    setScreen(current_virtual_desktop->screens().constFirst()->screen());
    initiatorWindow = QGuiApplicationPrivate::currentMouseWindow;
    QBasicDrag::startDrag();
    if (connection()->mouseGrabber() == nullptr)
        shapedPixmapWindow()->setMouseGrabEnabled(true);

    auto nativePixelPos = QHighDpi::toNativePixels(QCursor::pos(), initiatorWindow.data());
    move(nativePixelPos, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
}

void QXcbDrag::endDrag()
{
    QBasicDrag::endDrag();
    if (!dropped && !canceled && canDrop()) {
        // Set executed drop action when dropping outside application.
        setExecutedDropAction(accepted_drop_action);
    }
    initiatorWindow.clear();
}

Qt::DropAction QXcbDrag::defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const
{
    if (currentDrag() || drop_actions.isEmpty())
        return QBasicDrag::defaultAction(possibleActions, modifiers);

    return toDropAction(drop_actions.first());
}

void QXcbDrag::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
{
    if (event->window != xdnd_dragsource || event->atom != atom(QXcbAtom::XdndActionList))
        return;

    readActionList();
}

static
bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType)
{
    bool interacts = false;
    auto reply = Q_XCB_REPLY(xcb_shape_get_rectangles, connection, w, shapeType);
    if (reply) {
        xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply.get());
        if (rectangles) {
            const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply.get());
            for (int i = 0; !interacts && i < nRectangles; ++i) {
                interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
            }
        }
    }

    return interacts;
}

xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md, bool ignoreNonXdndAwareWindows)
{
    if (w == shapedPixmapWindow()->handle()->winId())
        return 0;

    if (md) {
        auto reply = Q_XCB_REPLY(xcb_get_window_attributes, xcb_connection(), w);
        if (!reply)
            return 0;

        if (reply->map_state != XCB_MAP_STATE_VIEWABLE)
            return 0;

        auto greply = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), w);
        if (!greply)
            return 0;

        QRect windowRect(greply->x, greply->y, greply->width, greply->height);
        if (windowRect.contains(pos)) {
            bool windowContainsMouse = !ignoreNonXdndAwareWindows;
            {
                auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
                                         false, w, connection()->atom(QXcbAtom::XdndAware),
                                         XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
                bool isAware = reply && reply->type != XCB_NONE;
                if (isAware) {
                    const QPoint relPos = pos - windowRect.topLeft();
                    // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we
                    // need to check both here so that in the case one is set and the other is not we still get the correct result.
                    if (connection()->hasInputShape())
                        windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_INPUT);
                    if (windowContainsMouse && connection()->hasXShape())
                        windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_BOUNDING);
                    if (!connection()->hasInputShape() && !connection()->hasXShape())
                        windowContainsMouse = true;
                    if (windowContainsMouse)
                        return w;
                }
            }

            auto reply = Q_XCB_REPLY(xcb_query_tree, xcb_connection(), w);
            if (!reply)
                return 0;
            int nc = xcb_query_tree_children_length(reply.get());
            xcb_window_t *c = xcb_query_tree_children(reply.get());

            xcb_window_t r = 0;
            for (uint i = nc; !r && i--;)
                r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows);

            if (r)
                return r;

            // We didn't find a client window!  Just use the
            // innermost window.

            // No children!
            if (!windowContainsMouse)
                return 0;
            else
                return w;
        }
    }
    return 0;
}

bool QXcbDrag::findXdndAwareTarget(const QPoint &globalPos, xcb_window_t *target_out)
{
    xcb_window_t rootwin = current_virtual_desktop->root();
    auto translate = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
                                 rootwin, rootwin, globalPos.x(), globalPos.y());
    if (!translate)
        return false;

    xcb_window_t target = translate->child;
    int lx = translate->dst_x;
    int ly = translate->dst_y;

    if (target && target != rootwin) {
        xcb_window_t src = rootwin;
        while (target != 0) {
            qCDebug(lcQpaXDnd) << "checking target for XdndAware" << target;

            auto translate = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
                                         src, target, lx, ly);
            if (!translate) {
                target = 0;
                break;
            }
            lx = translate->dst_x;
            ly = translate->dst_y;
            src = target;
            xcb_window_t child = translate->child;

            auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, target,
                                     atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
            bool aware = reply && reply->type != XCB_NONE;
            if (aware) {
                qCDebug(lcQpaXDnd) << "found XdndAware on" << target;
                break;
            }

            target = child;
        }

        if (!target || target == shapedPixmapWindow()->handle()->winId()) {
            qCDebug(lcQpaXDnd) << "need to find real window";
            target = findRealWindow(globalPos, rootwin, 6, true);
            if (target == 0)
                target = findRealWindow(globalPos, rootwin, 6, false);
            qCDebug(lcQpaXDnd) << "real window found" << target;
        }
    }

    *target_out = target;
    return true;
}

void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
    // currentDrag() might be deleted while 'drag' is progressing
    if (!currentDrag()) {
        cancel();
        return;
    }
    // The source sends XdndEnter and XdndPosition to the target.
    if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
        return;

    QXcbVirtualDesktop *virtualDesktop = nullptr;
    QPoint cursorPos;
    QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos);
    QXcbScreen *screen = virtualDesktop->screenAt(cursorPos);
    QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen);

    if (virtualDesktop != current_virtual_desktop) {
        setUseCompositing(virtualDesktop->compositingActive());
        recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos);
        if (connection()->mouseGrabber() == nullptr)
            shapedPixmapWindow()->setMouseGrabEnabled(true);

        current_virtual_desktop = virtualDesktop;
    } else {
        QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos);
    }

    xcb_window_t target;
    if (!findXdndAwareTarget(globalPos, &target))
        return;

    QXcbWindow *w = nullptr;
    if (target) {
        w = connection()->platformWindowFromId(target);
        if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)
            w = nullptr;
    } else {
        w = nullptr;
        target = current_virtual_desktop->root();
    }

    xcb_window_t proxy_target = xdndProxy(connection(), target);
    if (!proxy_target)
        proxy_target = target;
    int target_version = 1;

    if (proxy_target) {
        auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
                                 false, proxy_target,
                                 atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
        if (!reply || reply->type == XCB_NONE) {
            target = 0;
        } else {
            target_version = *(uint32_t *)xcb_get_property_value(reply.get());
            target_version = qMin(xdnd_version, target_version ? target_version : 1);
        }
    }

    if (target != current_target) {
        if (current_target)
            send_leave();

        current_target = target;
        current_proxy_target = proxy_target;
        if (target) {
            int flags = target_version << 24;
            if (drag_types.size() > 3)
                flags |= 0x0001;

            xcb_client_message_event_t enter;
            enter.response_type = XCB_CLIENT_MESSAGE;
            enter.sequence = 0;
            enter.window = target;
            enter.format = 32;
            enter.type = atom(QXcbAtom::XdndEnter);
#ifndef QT_NO_CLIPBOARD
            enter.data.data32[0] = connection()->clipboard()->owner();
#else
            enter.data.data32[0] = 0;
#endif
            enter.data.data32[1] = flags;
            enter.data.data32[2] = drag_types.size() > 0 ? drag_types.at(0) : 0;
            enter.data.data32[3] = drag_types.size() > 1 ? drag_types.at(1) : 0;
            enter.data.data32[4] = drag_types.size() > 2 ? drag_types.at(2) : 0;
            // provisionally set the rectangle to 5x5 pixels...
            source_sameanswer = QRect(globalPos.x() - 2, globalPos.y() - 2 , 5, 5);

            qCDebug(lcQpaXDnd) << "sending XdndEnter to target:" << target;

            if (w)
                handleEnter(w, &enter, current_proxy_target);
            else if (target)
                xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);
            waiting_for_status = false;
        }
    }

    if (waiting_for_status)
        return;

    if (target) {
        waiting_for_status = true;
        // The source sends a ClientMessage of type XdndPosition. This tells the target the
        // position of the mouse and the action that the user requested.
        xcb_client_message_event_t move;
        move.response_type = XCB_CLIENT_MESSAGE;
        move.sequence = 0;
        move.window = target;
        move.format = 32;
        move.type = atom(QXcbAtom::XdndPosition);
#ifndef QT_NO_CLIPBOARD
        move.data.data32[0] = connection()->clipboard()->owner();
#else
        move.data.data32[0] = 0;
#endif
        move.data.data32[1] = 0; // flags
        move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();
        move.data.data32[3] = connection()->time();
        const auto supportedActions = currentDrag()->supportedActions();
        const auto requestedAction = defaultAction(supportedActions, mods);
        move.data.data32[4] = toXdndAction(requestedAction);

        qCDebug(lcQpaXDnd) << "sending XdndPosition to target:" << target;

        source_time = connection()->time();

        if (w) {
            handle_xdnd_position(w, &move, b, mods);
        } else {
            setActionList(requestedAction, supportedActions);
            xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
        }
    }

    static const bool isUnity = qgetenv("XDG_CURRENT_DESKTOP").toLower() == "unity";
    if (isUnity && xdndCollectionWindow == XCB_NONE) {
        QString name = QXcbWindow::windowTitle(connection(), target);
        if (name == QStringLiteral("XdndCollectionWindowImp"))
            xdndCollectionWindow = target;
    }
    if (target == xdndCollectionWindow) {
        setCanDrop(false);
        updateCursor(Qt::IgnoreAction);
    }
}

void QXcbDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
    // XdndDrop is sent from source to target to complete the drop.
    QBasicDrag::drop(globalPos, b, mods);

    if (!current_target)
        return;

    xcb_client_message_event_t drop;
    drop.response_type = XCB_CLIENT_MESSAGE;
    drop.sequence = 0;
    drop.window = current_target;
    drop.format = 32;
    drop.type = atom(QXcbAtom::XdndDrop);
#ifndef QT_NO_CLIPBOARD
    drop.data.data32[0] = connection()->clipboard()->owner();
#else
    drop.data.data32[0] = 0;
#endif
    drop.data.data32[1] = 0; // flags
    drop.data.data32[2] = connection()->time();

    drop.data.data32[3] = 0;
    drop.data.data32[4] = currentDrag()->supportedActions();

    QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);

    if (w && w->window()->type() == Qt::Desktop) // && !w->acceptDrops()
        w = nullptr;

    Transaction t = {
        connection()->time(),
        current_target,
        current_proxy_target,
        w,
//        current_embeddig_widget,
        currentDrag(),
        QTime::currentTime()
    };
    transactions.append(t);

    // timer is needed only for drops that came from other processes.
    if (!t.targetWindow && cleanup_timer == -1) {
        cleanup_timer = startTimer(XdndDropTransactionTimeout);
    }

    qCDebug(lcQpaXDnd) << "sending drop to target:" << current_target;

    if (w) {
        handleDrop(w, &drop, b, mods);
    } else {
        xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
    }
}

Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const
{
    if (a == atom(QXcbAtom::XdndActionCopy) || a == 0)
        return Qt::CopyAction;
    if (a == atom(QXcbAtom::XdndActionLink))
        return Qt::LinkAction;
    if (a == atom(QXcbAtom::XdndActionMove))
        return Qt::MoveAction;
    return Qt::CopyAction;
}

Qt::DropActions QXcbDrag::toDropActions(const QVector<xcb_atom_t> &atoms) const
{
    Qt::DropActions actions;
    for (const auto actionAtom : atoms) {
        if (actionAtom != atom(QXcbAtom::XdndActionAsk))
            actions |= toDropAction(actionAtom);
    }
    return actions;
}

xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const
{
    switch (a) {
    case Qt::CopyAction:
        return atom(QXcbAtom::XdndActionCopy);
    case Qt::LinkAction:
        return atom(QXcbAtom::XdndActionLink);
    case Qt::MoveAction:
    case Qt::TargetMoveAction:
        return atom(QXcbAtom::XdndActionMove);
    case Qt::IgnoreAction:
        return XCB_NONE;
    default:
        return atom(QXcbAtom::XdndActionCopy);
    }
}

void QXcbDrag::readActionList()
{
    drop_actions.clear();
    auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource,
                             atom(QXcbAtom::XdndActionList), XCB_ATOM_ATOM,
                             0, 1024);
    if (reply && reply->type != XCB_NONE && reply->format == 32) {
        int length = xcb_get_property_value_length(reply.get()) / 4;

        xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get());
        for (int i = 0; i < length; ++i)
            drop_actions.append(atoms[i]);
    }
}

void QXcbDrag::setActionList(Qt::DropAction requestedAction, Qt::DropActions supportedActions)
{
#ifndef QT_NO_CLIPBOARD
    QVector<xcb_atom_t> actions;
    if (requestedAction != Qt::IgnoreAction)
        actions.append(toXdndAction(requestedAction));

    auto checkAppend = [this, requestedAction, supportedActions, &actions](Qt::DropAction action) {
        if (requestedAction != action && supportedActions & action)
            actions.append(toXdndAction(action));
    };

    checkAppend(Qt::CopyAction);
    checkAppend(Qt::MoveAction);
    checkAppend(Qt::LinkAction);

    if (current_actions != actions) {
        xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(),
                            atom(QXcbAtom::XdndActionList),
                            XCB_ATOM_ATOM, 32, actions.size(), actions.constData());
        current_actions = actions;
    }
#endif
}

void QXcbDrag::startListeningForActionListChanges()
{
    connection()->addWindowEventListener(xdnd_dragsource, this);
    const uint32_t event_mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
    xcb_change_window_attributes(xcb_connection(), xdnd_dragsource, XCB_CW_EVENT_MASK, event_mask);
}

void QXcbDrag::stopListeningForActionListChanges()
{
    const uint32_t event_mask[] = { XCB_EVENT_MASK_NO_EVENT };
    xcb_change_window_attributes(xcb_connection(), xdnd_dragsource, XCB_CW_EVENT_MASK, event_mask);
    connection()->removeWindowEventListener(xdnd_dragsource);
}

int QXcbDrag::findTransactionByWindow(xcb_window_t window)
{
    int at = -1;
    for (int i = 0; i < transactions.count(); ++i) {
        const Transaction &t = transactions.at(i);
        if (t.target == window || t.proxy_target == window) {
            at = i;
            break;
        }
    }
    return at;
}

int QXcbDrag::findTransactionByTime(xcb_timestamp_t timestamp)
{
    int at = -1;
    for (int i = 0; i < transactions.count(); ++i) {
        const Transaction &t = transactions.at(i);
        if (t.timestamp == timestamp) {
            at = i;
            break;
        }
    }
    return at;
}

#if 0
// for embedding only
static QWidget* current_embedding_widget  = 0;
static xcb_client_message_event_t last_enter_event;


static bool checkEmbedded(QWidget* w, const XEvent* xe)
{
    if (!w)
        return false;

    if (current_embedding_widget != 0 && current_embedding_widget != w) {
        current_target = ((QExtraWidget*)current_embedding_widget)->extraData()->xDndProxy;
        current_proxy_target = current_target;
        qt_xdnd_send_leave();
        current_target = 0;
        current_proxy_target = 0;
        current_embedding_widget = 0;
    }

    QWExtra* extra = ((QExtraWidget*)w)->extraData();
    if (extra && extra->xDndProxy != 0) {

        if (current_embedding_widget != w) {

            last_enter_event.xany.window = extra->xDndProxy;
            XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, &last_enter_event);
            current_embedding_widget = w;
        }

        ((XEvent*)xe)->xany.window = extra->xDndProxy;
        XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, (XEvent*)xe);
        if (currentWindow != w) {
            currentWindow = w;
        }
        return true;
    }
    current_embedding_widget = 0;
    return false;
}
#endif

void QXcbDrag::handleEnter(QPlatformWindow *, const xcb_client_message_event_t *event, xcb_window_t proxy)
{
    // The target receives XdndEnter.
    qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndEnter";

    xdnd_types.clear();

    int version = (int)(event->data.data32[1] >> 24);
    if (version > xdnd_version)
        return;

    xdnd_dragsource = event->data.data32[0];
    startListeningForActionListChanges();
    readActionList();

    if (!proxy)
        proxy = xdndProxy(connection(), xdnd_dragsource);
    current_proxy_target = proxy ? proxy : xdnd_dragsource;

    if (event->data.data32[1] & 1) {
        // get the types from XdndTypeList
        auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource,
                                 atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM,
                                 0, xdnd_max_type);
        if (reply && reply->type != XCB_NONE && reply->format == 32) {
            int length = xcb_get_property_value_length(reply.get()) / 4;
            if (length > xdnd_max_type)
                length = xdnd_max_type;

            xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get());
            xdnd_types.reserve(length);
            for (int i = 0; i < length; ++i)
                xdnd_types.append(atoms[i]);
        }
    } else {
        // get the types from the message
        for(int i = 2; i < 5; i++) {
            if (event->data.data32[i])
                xdnd_types.append(event->data.data32[i]);
        }
    }
    for(int i = 0; i < xdnd_types.length(); ++i)
        qCDebug(lcQpaXDnd) << "    " << connection()->atomName(xdnd_types.at(i));
}

void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e,
                                    Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
    // The target receives XdndPosition. The target window must determine which widget the mouse
    // is in and ask it whether or not it will accept the drop.
    qCDebug(lcQpaXDnd) << "target:" << e->window << "received XdndPosition";

    QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
    Q_ASSERT(w);
    QRect geometry = w->geometry();
    p -= geometry.topLeft();

    if (!w || !w->window() || (w->window()->type() == Qt::Desktop))
        return;

    if (Q_UNLIKELY(e->data.data32[0] != xdnd_dragsource)) {
        qCDebug(lcQpaXDnd, "xdnd drag position from unexpected source (%x not %x)",
                e->data.data32[0], xdnd_dragsource);
        return;
    }

    currentPosition = p;
    currentWindow = w->window();

    // timestamp from the source
    if (e->data.data32[3] != XCB_NONE) {
        target_time = e->data.data32[3];
    }

    QMimeData *dropData = nullptr;
    Qt::DropActions supported_actions = Qt::IgnoreAction;
    if (currentDrag()) {
        dropData = currentDrag()->mimeData();
        supported_actions = currentDrag()->supportedActions();
    } else {
        dropData = m_dropData;
        supported_actions = toDropActions(drop_actions);
        if (e->data.data32[4] != atom(QXcbAtom::XdndActionAsk))
            supported_actions |= Qt::DropActions(toDropAction(e->data.data32[4]));
    }

    auto buttons = currentDrag() ? b : connection()->queryMouseButtons();
    auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers();

    QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(
                w->window(), dropData, p, supported_actions, buttons, modifiers);

    // ### FIXME ? - answerRect appears to be unused.
    QRect answerRect(p + geometry.topLeft(), QSize(1,1));
    answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);

    // The target sends a ClientMessage of type XdndStatus. This tells the source whether or not
    // it will accept the drop, and, if so, what action will be taken. It also includes a rectangle
    // that means "don't send another XdndPosition message until the mouse moves out of here".
    xcb_client_message_event_t response;
    response.response_type = XCB_CLIENT_MESSAGE;
    response.sequence = 0;
    response.window = xdnd_dragsource;
    response.format = 32;
    response.type = atom(QXcbAtom::XdndStatus);
    response.data.data32[0] = xcb_window(w);
    response.data.data32[1] = qt_response.isAccepted(); // flags
    response.data.data32[2] = 0; // x, y
    response.data.data32[3] = 0; // w, h
    response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // action

    accepted_drop_action = qt_response.acceptedAction();

    if (answerRect.left() < 0)
        answerRect.setLeft(0);
    if (answerRect.right() > 4096)
        answerRect.setRight(4096);
    if (answerRect.top() < 0)
        answerRect.setTop(0);
    if (answerRect.bottom() > 4096)
        answerRect.setBottom(4096);
    if (answerRect.width() < 0)
        answerRect.setWidth(0);
    if (answerRect.height() < 0)
        answerRect.setHeight(0);

    // reset
    target_time = XCB_CURRENT_TIME;

    qCDebug(lcQpaXDnd) << "sending XdndStatus to source:" << xdnd_dragsource;

#ifndef QT_NO_CLIPBOARD
    if (xdnd_dragsource == connection()->clipboard()->owner())
        handle_xdnd_status(&response);
    else
#endif
        xcb_send_event(xcb_connection(), false, current_proxy_target,
                       XCB_EVENT_MASK_NO_EVENT, (const char *)&response);
}

namespace
{
    class ClientMessageScanner {
    public:
        ClientMessageScanner(xcb_atom_t a) : atom(a) {}
        xcb_atom_t atom;
        bool operator() (xcb_generic_event_t *event, int type) const {
            if (type != XCB_CLIENT_MESSAGE)
                return false;
            auto clientMessage = reinterpret_cast<xcb_client_message_event_t *>(event);
            return clientMessage->type == atom;
        }
    };
}

void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event)
{
    xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
    ClientMessageScanner scanner(atom(QXcbAtom::XdndPosition));
    while (auto nextEvent = connection()->eventQueue()->peek(scanner)) {
        if (lastEvent != event)
            free(lastEvent);
        lastEvent = reinterpret_cast<xcb_client_message_event_t *>(nextEvent);
    }

    handle_xdnd_position(w, lastEvent);
    if (lastEvent != event)
        free(lastEvent);
}

void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event)
{
    // The source receives XdndStatus. It can use the action to change the cursor to indicate
    // whether or not the user's requested action will be performed.
    qCDebug(lcQpaXDnd) << "source:" << event->window << "received XdndStatus";
    waiting_for_status = false;
    // ignore late status messages
    if (event->data.data32[0] && event->data.data32[0] != current_target)
        return;

    const bool dropPossible = event->data.data32[1];
    setCanDrop(dropPossible);

    if (dropPossible) {
        accepted_drop_action = toDropAction(event->data.data32[4]);
        updateCursor(accepted_drop_action);
    } else {
        updateCursor(Qt::IgnoreAction);
    }

    if ((event->data.data32[1] & 2) == 0) {
        QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff);
        QSize s((event->data.data32[3] & 0xffff0000) >> 16, event->data.data32[3] & 0x0000ffff);
        source_sameanswer = QRect(p, s);
    } else {
        source_sameanswer = QRect();
    }
}

void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
{
    if (
#ifndef QT_NO_CLIPBOARD
            event->window != connection()->clipboard()->owner() ||
#endif
            !drag())
        return;

    xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
    xcb_generic_event_t *nextEvent;
    ClientMessageScanner scanner(atom(QXcbAtom::XdndStatus));
    while ((nextEvent = connection()->eventQueue()->peek(scanner))) {
        if (lastEvent != event)
            free(lastEvent);
        lastEvent = (xcb_client_message_event_t *)nextEvent;
    }

    handle_xdnd_status(lastEvent);
    if (lastEvent != event)
        free(lastEvent);
}

void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event)
{
    // If the target receives XdndLeave, it frees any cached data and forgets the whole incident.
    qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndLeave";

    if (!currentWindow || w != currentWindow.data()->handle()) {
        stopListeningForActionListChanges();
        return; // sanity
    }

    // ###
//    if (checkEmbedded(current_embedding_widget, event)) {
//        current_embedding_widget = 0;
//        currentWindow.clear();
//        return;
//    }

    if (event->data.data32[0] != xdnd_dragsource) {
        // This often happens - leave other-process window quickly
        qCDebug(lcQpaXDnd, "xdnd drag leave from unexpected source (%x not %x",
                event->data.data32[0], xdnd_dragsource);
    }

    stopListeningForActionListChanges();

    QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, { }, { });
}

void QXcbDrag::send_leave()
{
    // XdndLeave is sent from the source to the target to cancel the drop.
    if (!current_target)
        return;

    xcb_client_message_event_t leave;
    leave.response_type = XCB_CLIENT_MESSAGE;
    leave.sequence = 0;
    leave.window = current_target;
    leave.format = 32;
    leave.type = atom(QXcbAtom::XdndLeave);
#ifndef QT_NO_CLIPBOARD
    leave.data.data32[0] = connection()->clipboard()->owner();
#else
    leave.data.data32[0] = 0;
#endif
    leave.data.data32[1] = 0; // flags
    leave.data.data32[2] = 0; // x, y
    leave.data.data32[3] = 0; // w, h
    leave.data.data32[4] = 0; // just null

    QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);

    if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)
        w = nullptr;

    qCDebug(lcQpaXDnd) << "sending XdndLeave to target:" << current_target;

    if (w)
        handleLeave(w, (const xcb_client_message_event_t *)&leave);
    else
        xcb_send_event(xcb_connection(), false,current_proxy_target,
                       XCB_EVENT_MASK_NO_EVENT, (const char *)&leave);
}

void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event,
                          Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
    // Target receives XdndDrop. Once it is finished processing the drop, it sends XdndFinished.
    qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndDrop";

    if (!currentWindow) {
        stopListeningForActionListChanges();
        xdnd_dragsource = 0;
        return; // sanity
    }

    const uint32_t *l = event->data.data32;

    if (l[0] != xdnd_dragsource) {
        qCDebug(lcQpaXDnd, "xdnd drop from unexpected source (%x not %x", l[0], xdnd_dragsource);
        return;
    }

    // update the "user time" from the timestamp in the event.
    if (l[2] != 0)
        target_time = l[2];

    Qt::DropActions supported_drop_actions;
    QMimeData *dropData = nullptr;
    if (currentDrag()) {
        dropData = currentDrag()->mimeData();
        supported_drop_actions = Qt::DropActions(l[4]);
    } else {
        dropData = m_dropData;
        supported_drop_actions = accepted_drop_action | toDropActions(drop_actions);
    }

    if (!dropData)
        return;
    // ###
    //        int at = findXdndDropTransactionByTime(target_time);
    //        if (at != -1)
    //            dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
    // if we can't find it, then use the data in the drag manager

    auto buttons = currentDrag() ? b : connection()->queryMouseButtons();
    auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers();

    QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(
                currentWindow.data(), dropData, currentPosition, supported_drop_actions,
                buttons, modifiers);

    setExecutedDropAction(response.acceptedAction());

    xcb_client_message_event_t finished;
    finished.response_type = XCB_CLIENT_MESSAGE;
    finished.sequence = 0;
    finished.window = xdnd_dragsource;
    finished.format = 32;
    finished.type = atom(QXcbAtom::XdndFinished);
    finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
    finished.data.data32[1] = response.isAccepted(); // flags
    finished.data.data32[2] = toXdndAction(response.acceptedAction());

    qCDebug(lcQpaXDnd) << "sending XdndFinished to source:" << xdnd_dragsource;

    xcb_send_event(xcb_connection(), false, current_proxy_target,
                   XCB_EVENT_MASK_NO_EVENT, (char *)&finished);

    stopListeningForActionListChanges();

    dropped = true;
}

void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
{
    // Source receives XdndFinished when target is done processing the drop data.
    qCDebug(lcQpaXDnd) << "source:" << event->window << "received XdndFinished";

#ifndef QT_NO_CLIPBOARD
    if (event->window != connection()->clipboard()->owner())
        return;
#endif

    const unsigned long *l = (const unsigned long *)event->data.data32;
    if (l[0]) {
        int at = findTransactionByWindow(l[0]);
        if (at != -1) {

            Transaction t = transactions.takeAt(at);
            if (t.drag)
                t.drag->deleteLater();
//            QDragManager *manager = QDragManager::self();

//            Window target = current_target;
//            Window proxy_target = current_proxy_target;
//            QWidget *embedding_widget = current_embedding_widget;
//            QDrag *currentObject = manager->object;

//            current_target = t.target;
//            current_proxy_target = t.proxy_target;
//            current_embedding_widget = t.embedding_widget;
//            manager->object = t.object;

//            if (!passive)
//                (void) checkEmbedded(currentWindow, xe);

//            current_embedding_widget = 0;
//            current_target = 0;
//            current_proxy_target = 0;

//            current_target = target;
//            current_proxy_target = proxy_target;
//            current_embedding_widget = embedding_widget;
//            manager->object = currentObject;
        } else {
            qWarning("QXcbDrag::handleFinished - drop data has expired");
        }
    }
    waiting_for_status = false;
}

void QXcbDrag::timerEvent(QTimerEvent* e)
{
    if (e->timerId() == cleanup_timer) {
        bool stopTimer = true;
        for (int i = 0; i < transactions.count(); ++i) {
            const Transaction &t = transactions.at(i);
            if (t.targetWindow) {
                // dnd within the same process, don't delete, these are taken care of
                // in handleFinished()
                continue;
            }
            QTime currentTime = QTime::currentTime();
            int delta = t.time.msecsTo(currentTime);
            if (delta > XdndDropTransactionTimeout) {
                /* delete transactions which are older than XdndDropTransactionTimeout. It could mean
                 one of these:
                 - client has crashed and as a result we have never received XdndFinished
                 - showing dialog box on drop event where user's response takes more time than XdndDropTransactionTimeout (QTBUG-14493)
                 - dnd takes unusually long time to process data
                 */
                if (t.drag)
                    t.drag->deleteLater();
                transactions.removeAt(i--);
            } else {
                stopTimer = false;
            }

        }
        if (stopTimer && cleanup_timer != -1) {
            killTimer(cleanup_timer);
            cleanup_timer = -1;
        }
    }
}

void QXcbDrag::cancel()
{
    qCDebug(lcQpaXDnd) << "dnd was canceled";

    QBasicDrag::cancel();
    if (current_target)
        send_leave();

    // remove canceled object
    if (currentDrag())
        currentDrag()->deleteLater();

    canceled = true;
}

static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
{
    xcb_window_t target = 0;
    forever {
        // check if window has XdndAware
        auto gpReply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), false, window,
                                   c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
        bool aware = gpReply && gpReply->type != XCB_NONE;
        if (aware) {
            target = window;
            break;
        }

        // try window's parent
        auto qtReply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, c->xcb_connection(), window);
        if (!qtReply)
            break;
        xcb_window_t root = qtReply->root;
        xcb_window_t parent = qtReply->parent;
        if (window == root)
            break;
        window = parent;
    }
    return target;
}

void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event)
{
    qCDebug(lcQpaXDnd) << "handle selection request from target:" << event->requestor;
    q_padded_xcb_event<xcb_selection_notify_event_t> notify = {};
    notify.response_type = XCB_SELECTION_NOTIFY;
    notify.requestor = event->requestor;
    notify.selection = event->selection;
    notify.target = XCB_NONE;
    notify.property = XCB_NONE;
    notify.time = event->time;

    // which transaction do we use? (note: -2 means use current currentDrag())
    int at = -1;

    // figure out which data the requestor is really interested in
    if (currentDrag() && event->time == source_time) {
        // requestor wants the current drag data
        at = -2;
    } else {
        // if someone has requested data in response to XdndDrop, find the corresponding transaction. the
        // spec says to call xcb_convert_selection() using the timestamp from the XdndDrop
        at = findTransactionByTime(event->time);
        if (at == -1) {
            // no dice, perhaps the client was nice enough to use the same window id in
            // xcb_convert_selection() that we sent the XdndDrop event to.
            at = findTransactionByWindow(event->requestor);
        }

        if (at == -1) {
            xcb_window_t target = findXdndAwareParent(connection(), event->requestor);
            if (target) {
                if (event->time == XCB_CURRENT_TIME && current_target == target)
                    at = -2;
                else
                    at = findTransactionByWindow(target);
            }
        }
    }

    QDrag *transactionDrag = nullptr;
    if (at >= 0) {
        transactionDrag = transactions.at(at).drag;
    } else if (at == -2) {
        transactionDrag = currentDrag();
    }

    if (transactionDrag) {
        xcb_atom_t atomFormat = event->target;
        int dataFormat = 0;
        QByteArray data;
        if (QXcbMime::mimeDataForAtom(connection(), event->target, transactionDrag->mimeData(),
                                     &data, &atomFormat, &dataFormat)) {
            int dataSize = data.size() / (dataFormat / 8);
            xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, event->requestor, event->property,
                                atomFormat, dataFormat, dataSize, (const void *)data.constData());
            notify.property = event->property;
            notify.target = atomFormat;
        }
    }

    xcb_window_t proxy_target = xdndProxy(connection(), event->requestor);
    if (!proxy_target)
        proxy_target = event->requestor;

    xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
}


bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
{
    // Windows announce that they support the XDND protocol by creating a window property XdndAware.
    if (on) {
        QXcbWindow *window = nullptr;
        if (w->window()->type() == Qt::Desktop) {
            if (desktop_proxy) // *WE* already have one.
                return false;

            QXcbConnectionGrabber grabber(connection());

            // As per Xdnd4, use XdndProxy
            xcb_window_t proxy_id = xdndProxy(connection(), w->xcb_window());

            if (!proxy_id) {
                desktop_proxy = new QWindow;
                window = static_cast<QXcbWindow *>(desktop_proxy->handle());
                proxy_id = window->xcb_window();
                xcb_atom_t xdnd_proxy = atom(QXcbAtom::XdndProxy);
                xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, w->xcb_window(), xdnd_proxy,
                                    XCB_ATOM_WINDOW, 32, 1, &proxy_id);
                xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, proxy_id, xdnd_proxy,
                                    XCB_ATOM_WINDOW, 32, 1, &proxy_id);
            }

        } else {
            window = w;
        }
        if (window) {
            qCDebug(lcQpaXDnd) << "setting XdndAware for" << window->xcb_window();
            xcb_atom_t atm = xdnd_version;
            xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window->xcb_window(),
                                atom(QXcbAtom::XdndAware), XCB_ATOM_ATOM, 32, 1, &atm);
            return true;
        } else {
            return false;
        }
    } else {
        if (w->window()->type() == Qt::Desktop) {
            xcb_delete_property(xcb_connection(), w->xcb_window(), atom(QXcbAtom::XdndProxy));
            delete desktop_proxy;
            desktop_proxy = nullptr;
        } else {
            qCDebug(lcQpaXDnd) << "not deleting XDndAware";
        }
        return true;
    }
}

bool QXcbDrag::ownsDragObject() const
{
    return true;
}

QXcbDropData::QXcbDropData(QXcbDrag *d)
    : QXcbMime(),
      drag(d)
{
}

QXcbDropData::~QXcbDropData()
{
}

QVariant QXcbDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const
{
    QByteArray mime = mimetype.toLatin1();
    QVariant data = xdndObtainData(mime, QMetaType::Type(requestedType));
    return data;
}

QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QMetaType::Type requestedType) const
{
    QByteArray result;

    QXcbConnection *c = drag->connection();
    QXcbWindow *xcb_window = c->platformWindowFromId(drag->xdnd_dragsource);
    if (xcb_window && drag->currentDrag() && xcb_window->window()->type() != Qt::Desktop) {
        QMimeData *data = drag->currentDrag()->mimeData();
        if (data->hasFormat(QLatin1String(format)))
            result = data->data(QLatin1String(format));
        return result;
    }

    QVector<xcb_atom_t> atoms = drag->xdnd_types;
    QByteArray encoding;
    xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding);
    if (a == XCB_NONE)
        return result;

#ifndef QT_NO_CLIPBOARD
    if (c->clipboard()->getSelectionOwner(drag->atom(QXcbAtom::XdndSelection)) == XCB_NONE)
        return result; // should never happen?

    xcb_atom_t xdnd_selection = c->atom(QXcbAtom::XdndSelection);
    result = c->clipboard()->getSelection(xdnd_selection, a, xdnd_selection, drag->targetTime());
#endif

    return mimeConvertToFormat(c, a, result, QLatin1String(format), requestedType, encoding);
}

bool QXcbDropData::hasFormat_sys(const QString &format) const
{
    return formats().contains(format);
}

QStringList QXcbDropData::formats_sys() const
{
    QStringList formats;
    for (int i = 0; i < drag->xdnd_types.size(); ++i) {
        QString f = mimeAtomToString(drag->connection(), drag->xdnd_types.at(i));
        if (!formats.contains(f))
            formats.append(f);
    }
    return formats;
}

QT_END_NAMESPACE
