~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/kernel/qdnd_x11.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-10-12 23:14:14 UTC
  • mto: (15.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20061012231414-y2oqbom5dy389os0
Tags: upstream-4.2.0
ImportĀ upstreamĀ versionĀ 4.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#include "qvector.h"
41
41
#include "qurl.h"
42
42
#include "qdebug.h"
 
43
#include "qimagewriter.h"
 
44
#include "qbuffer.h"
43
45
 
44
46
#include "qdnd_p.h"
45
47
#include "qt_x11_p.h"
327
329
 
328
330
            // As per Xdnd4, use XdndProxy
329
331
            XGrabServer(X11->display);
330
 
            WId proxy_id = xdndProxy(w->winId());
 
332
            Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
 
333
            WId proxy_id = xdndProxy(w->internalWinId());
331
334
 
332
335
            if (!proxy_id) {
333
336
                xdnd_widget = xdnd_data.desktop_proxy = new QWidget;
334
 
                proxy_id = xdnd_data.desktop_proxy->winId();
335
 
                XChangeProperty (X11->display, w->winId(), ATOM(XdndProxy),
 
337
                proxy_id = xdnd_data.desktop_proxy->internalWinId();
 
338
                XChangeProperty (X11->display, w->internalWinId(), ATOM(XdndProxy),
336
339
                                 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1);
337
340
                XChangeProperty (X11->display, proxy_id, ATOM(XdndProxy),
338
341
                                 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1);
343
346
            xdnd_widget = w->window();
344
347
        }
345
348
        if (xdnd_widget) {
346
 
            DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->winId();
 
349
            DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->internalWinId();
347
350
            Atom atm = (Atom)xdnd_version;
348
 
            XChangeProperty(X11->display, xdnd_widget->winId(), ATOM(XdndAware),
 
351
            Q_ASSERT(xdnd_widget->testAttribute(Qt::WA_WState_Created));
 
352
            XChangeProperty(X11->display, xdnd_widget->internalWinId(), ATOM(XdndAware),
349
353
                             XA_ATOM, 32, PropModeReplace, (unsigned char *)&atm, 1);
350
354
            return true;
351
355
        } else {
353
357
        }
354
358
    } else {
355
359
        if ((w->windowType() == Qt::Desktop)) {
356
 
            XDeleteProperty(X11->display, w->winId(), ATOM(XdndProxy));
 
360
            XDeleteProperty(X11->display, w->internalWinId(), ATOM(XdndProxy));
357
361
            delete xdnd_data.desktop_proxy;
358
362
            xdnd_data.desktop_proxy = 0;
359
363
        } else {
383
387
    return XInternAtom(display, mimeType, False);
384
388
}
385
389
 
 
390
//$$$
 
391
QString QX11Data::xdndMimeAtomToString(Atom a)
 
392
{
 
393
    QString atomName;
 
394
    if (a) {
 
395
        char *atom = XGetAtomName(display, a);
 
396
        atomName = QString::fromLatin1(atom);
 
397
        XFree(atom);
 
398
    }
 
399
    return atomName;
 
400
}
 
401
 
 
402
//$$$
 
403
Atom QX11Data::xdndMimeStringToAtom(const QString &mimeType)
 
404
{
 
405
    if (mimeType.isEmpty())
 
406
        return 0;
 
407
    return XInternAtom(display, mimeType.toLatin1().constData(), False);
 
408
}
 
409
 
 
410
//$$$ replace ccxdndAtomToString()
 
411
QStringList QX11Data::xdndMimeFormatsForAtom(Atom a)
 
412
{
 
413
    QStringList formats;
 
414
    if (a) {
 
415
        QString atomName = xdndMimeAtomToString(a);
 
416
        formats.append(atomName);
 
417
 
 
418
        // special cases for string type
 
419
        if (a == ATOM(UTF8_STRING) || a == XA_STRING
 
420
            || a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT))
 
421
            formats.append(QLatin1String("text/plain"));
 
422
 
 
423
        // special cases for uris
 
424
        if (atomName == QLatin1String("text/x-moz-url"))
 
425
            formats.append(QLatin1String("text/uri-list"));
 
426
 
 
427
        // special case for images
 
428
        if (a == XA_PIXMAP)
 
429
            formats.append(QLatin1String("image/ppm"));
 
430
    }
 
431
    return formats;
 
432
}
 
433
 
 
434
//$$$
 
435
bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat)
 
436
{
 
437
    bool ret = false;
 
438
    *atomFormat = a;
 
439
    *dataFormat = 8;
 
440
    QString atomName = xdndMimeAtomToString(a);
 
441
    if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) {
 
442
        *data = QInternalMimeData::renderDataHelper(atomName, mimeData);
 
443
        if (atomName == QLatin1String("application/x-color"))
 
444
            *dataFormat = 16;
 
445
        ret = true;
 
446
    } else {
 
447
        if ((a == ATOM(UTF8_STRING) || a == XA_STRING
 
448
            || a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT))
 
449
            && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) {
 
450
            if (a == ATOM(UTF8_STRING)){
 
451
                *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData);
 
452
                ret = true;
 
453
            } else if (a == XA_STRING) {
 
454
                *data = QString::fromUtf8(QInternalMimeData::renderDataHelper(
 
455
                        QLatin1String("text/plain"), mimeData)).toLocal8Bit();
 
456
                ret = true;
 
457
            } else if (a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT)) {
 
458
                // the ICCCM states that TEXT and COMPOUND_TEXT are in the
 
459
                // encoding of choice, so we choose the encoding of the locale
 
460
                QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper(
 
461
                                     QLatin1String("text/plain"), mimeData)).toLocal8Bit();
 
462
                char *list[] = { strData.data(), NULL };
 
463
 
 
464
                XICCEncodingStyle style = (a == ATOM(COMPOUND_TEXT))
 
465
                                        ? XCompoundTextStyle : XStdICCTextStyle;
 
466
                XTextProperty textprop;
 
467
                if (list[0] != NULL
 
468
                    && XmbTextListToTextProperty(X11->display, list, 1, style,
 
469
                                                 &textprop) == Success) {
 
470
                    *atomFormat = textprop.encoding;
 
471
                    *dataFormat = textprop.format;
 
472
                    *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8);
 
473
 
 
474
                    DEBUG("    textprop type %lx\n"
 
475
                    "    textprop name '%s'\n"
 
476
                    "    format %d\n"
 
477
                    "    %ld items\n"
 
478
                    "    %d bytes\n",
 
479
                    textprop.encoding,
 
480
                    X11->xdndMimeAtomToString(textprop.encoding).toLatin1().data(),
 
481
                    textprop.format, textprop.nitems, data->size());
 
482
 
 
483
                    XFree(textprop.value);
 
484
                }
 
485
            }
 
486
        } else if (atomName == QLatin1String("text/x-moz-url") &&
 
487
                   QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) {
 
488
            QByteArray uri = QInternalMimeData::renderDataHelper(
 
489
                             QLatin1String("text/uri-list"), mimeData).split('\n').first();
 
490
            QString mozUri = QString::fromLatin1(uri, uri.size());
 
491
            mozUri += QLatin1Char('\n');
 
492
            *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2);
 
493
            ret = true;
 
494
        } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) {
 
495
            QPixmap pm = qvariant_cast<QPixmap>(mimeData->imageData());
 
496
            if (a == XA_BITMAP && pm.depth() != 1) {
 
497
                QImage img = pm.toImage();
 
498
                img = img.convertToFormat(QImage::Format_MonoLSB);
 
499
                pm = QPixmap::fromImage(img);
 
500
            }
 
501
            QDragManager *dm = QDragManager::self();
 
502
            if (dm) {
 
503
                Pixmap handle = pm.handle();
 
504
                *data = QByteArray((const char *) &handle, sizeof(Pixmap));
 
505
                dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm;
 
506
                dm->xdndMimeTransferedPixmapIndex =
 
507
                            (dm->xdndMimeTransferedPixmapIndex + 1) % 2;
 
508
            }
 
509
        }
 
510
    }
 
511
    return data;
 
512
}
 
513
 
 
514
//$$$
 
515
QList<Atom> QX11Data::xdndMimeAtomsForFormat(const QString &format)
 
516
{
 
517
    QList<Atom> atoms;
 
518
    atoms.append(xdndMimeStringToAtom(format));
 
519
 
 
520
    // special cases for strings
 
521
    if (format == QLatin1String("text/plain")) {
 
522
        atoms.append(ATOM(UTF8_STRING));
 
523
        atoms.append(XA_STRING);
 
524
        atoms.append(ATOM(TEXT));
 
525
        atoms.append(ATOM(COMPOUND_TEXT));
 
526
    }
 
527
 
 
528
    // special cases for uris
 
529
    if (format == QLatin1String("text/uri-list")) {
 
530
        atoms.append(xdndMimeStringToAtom(QLatin1String("text/x-moz-url")));
 
531
    }
 
532
 
 
533
    //special cases for images
 
534
    if (format == QLatin1String("image/ppm"))
 
535
        atoms.append(XA_PIXMAP);
 
536
    if (format == QLatin1String("image/pbm"))
 
537
        atoms.append(XA_BITMAP);
 
538
 
 
539
    return atoms;
 
540
}
 
541
 
 
542
//$$$
 
543
QByteArray QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const QString &format)
 
544
{
 
545
    QString atomName = xdndMimeAtomToString(a);
 
546
    if (atomName == format)
 
547
        return data;
 
548
 
 
549
    // special cases for string types
 
550
    if (format == QLatin1String("text/plain")) {
 
551
        if (a == ATOM(UTF8_STRING))
 
552
            return data;
 
553
        if (a == XA_STRING)
 
554
            return QString::fromLatin1(data).toUtf8();
 
555
        if (a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT))
 
556
            // #### might be wrong for COMPUND_TEXT
 
557
            return QString::fromLocal8Bit(data, data.size()).toUtf8();
 
558
    }
 
559
 
 
560
    // special case for uri types
 
561
    if (format == QLatin1String("text/uri-list")) {
 
562
        if (atomName == QLatin1String("text/x-moz-url")) {
 
563
            // we expect this as utf16 <url><space><title>
 
564
            // the first part is a url that should only contain ascci char
 
565
            // so it should be safe to check that the second char is 0
 
566
            // to verify that it is utf16
 
567
            if (data.size() > 1 && data.at(1) == 0)
 
568
                return QString::fromUtf16(reinterpret_cast<const ushort *>(data.constData()),
 
569
                                data.size() / 2).split(QLatin1Char('\n')).first().toLatin1();
 
570
        }
 
571
    }
 
572
 
 
573
    // special cas for images
 
574
    if (format == QLatin1String("image/ppm")) {
 
575
        if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) {
 
576
            Pixmap xpm = *((Pixmap*)data.data());
 
577
            Display *dpy = display;
 
578
            Window r;
 
579
            int x,y;
 
580
            uint w,h,bw,d;
 
581
            if (!xpm)
 
582
                return QByteArray();
 
583
            XGetGeometry(dpy,xpm, &r,&x,&y,&w,&h,&bw,&d);
 
584
            QImageWriter imageWriter;
 
585
            GC gc = XCreateGC(dpy, xpm, 0, 0);
 
586
            QImage imageToWrite;
 
587
            if (d == 1) {
 
588
                QBitmap qbm(w,h);
 
589
                XCopyArea(dpy,xpm,qbm.handle(),gc,0,0,w,h,0,0);
 
590
                imageWriter.setFormat("PBMRAW");
 
591
                imageToWrite = qbm.toImage();
 
592
            } else {
 
593
                QPixmap qpm(w,h);
 
594
                XCopyArea(dpy,xpm,qpm.handle(),gc,0,0,w,h,0,0);
 
595
                imageWriter.setFormat("PPMRAW");
 
596
                imageToWrite = qpm.toImage();
 
597
            }
 
598
            XFreeGC(dpy,gc);
 
599
            QBuffer buf;
 
600
            buf.open(QIODevice::WriteOnly);
 
601
            imageWriter.setDevice(&buf);
 
602
            imageWriter.write(imageToWrite);
 
603
            return buf.buffer();
 
604
        }
 
605
    }
 
606
    return QByteArray();
 
607
}
 
608
 
 
609
//$$$ middle of xdndObtainData
 
610
Atom QX11Data::xdndMimeAtomForFormat(const QString &format, const QList<Atom> &atoms)
 
611
{
 
612
    Atom a = xdndMimeStringToAtom(format);
 
613
    if (a && atoms.contains(a))
 
614
        return a;
 
615
 
 
616
    // find matches for string types
 
617
    if (format == QLatin1String("text/plain")) {
 
618
        if (atoms.contains(ATOM(UTF8_STRING)))
 
619
            return ATOM(UTF8_STRING);
 
620
        if (atoms.contains(ATOM(COMPOUND_TEXT)))
 
621
            return XA_STRING;
 
622
        if (atoms.contains(ATOM(TEXT)))
 
623
            return XA_STRING;
 
624
        if (atoms.contains(XA_STRING))
 
625
            return XA_STRING;
 
626
    }
 
627
 
 
628
    // find mathes for uri types
 
629
    if (format == QLatin1String("text/uri-list")) {
 
630
        Atom a = xdndMimeStringToAtom(QLatin1String("text/x-moz-url"));
 
631
        if (a && atoms.contains(a))
 
632
            return a;
 
633
    }
 
634
 
 
635
    // find match for image
 
636
    if (format == QLatin1String("image/ppm")) {
 
637
        if (atoms.contains(XA_PIXMAP))
 
638
            return XA_PIXMAP;
 
639
    }
 
640
 
 
641
    return 0;
 
642
}
386
643
 
387
644
void QX11Data::xdndSetup() {
388
645
    QCursorData::initialize();
546
803
    response.window = qt_xdnd_dragsource_xid;
547
804
    response.format = 32;
548
805
    response.message_type = ATOM(XdndStatus);
549
 
    response.data.l[0] = w->winId();
 
806
    response.data.l[0] = w->internalWinId();
550
807
    response.data.l[1] = 0; // flags
551
808
    response.data.l[2] = 0; // x, y
552
809
    response.data.l[3] = 0; // w, h
611
868
                response.data.l[0] = 0;
612
869
                last_target_accepted_action = Qt::IgnoreAction;
613
870
            }
614
 
            answerRect = me.answerRect().intersect(c->rect());
 
871
            answerRect = me.answerRect().intersected(c->rect());
615
872
        }
616
873
        answerRect = QRect(c->mapToGlobal(answerRect.topLeft()), answerRect.size());
617
874
 
835
1092
        finished.message_type = ATOM(XdndFinished);
836
1093
        DNDDEBUG << "xdndHandleDrop"
837
1094
             << "qt_xdnd_current_widget" << qt_xdnd_current_widget
838
 
             << (qt_xdnd_current_widget ? qt_xdnd_current_widget->winId() : 0)
 
1095
             << (qt_xdnd_current_widget ? qt_xdnd_current_widget->internalWinId() : 0)
839
1096
             << "t_xdnd_current_widget->window()"
840
1097
             << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window() : 0)
841
 
             << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window()->winId() : 0);
842
 
        finished.data.l[0] = qt_xdnd_current_widget?qt_xdnd_current_widget->window()->winId():0;
 
1098
             << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window()->internalWinId() : 0);
 
1099
        finished.data.l[0] = qt_xdnd_current_widget?qt_xdnd_current_widget->window()->internalWinId():0;
843
1100
        finished.data.l[1] = de.isAccepted() ? 1 : 0; // flags
844
1101
        finished.data.l[2] = qtaction_to_xdndaction(global_accepted_action);
845
1102
        XSendEvent(X11->display, qt_xdnd_dragsource_xid, False,
910
1167
        move(QCursor::pos());
911
1168
    } else if (e->timerId() == transaction_expiry_timer) {
912
1169
        for (int i = 0; i < X11->dndDropTransactions.count(); ++i) {
913
 
            X11->dndDropTransactions.at(i).object->deleteLater();
 
1170
            const QXdndDropTransaction &t = X11->dndDropTransactions.at(i);
 
1171
            if (t.targetWidget) {
 
1172
                // dnd within the same process, don't delete these
 
1173
                continue;
 
1174
            }
 
1175
            t.object->deleteLater();
 
1176
            X11->dndDropTransactions.removeAt(i--);
914
1177
        }
915
 
        X11->dndDropTransactions.clear();
916
1178
 
917
1179
        killTimer(transaction_expiry_timer);
918
1180
        transaction_expiry_timer = -1;
1031
1293
    killTimer(heartbeat);
1032
1294
    heartbeat = -1;
1033
1295
    beingCancelled = true;
 
1296
    qt_xdnd_dragging = false;
1034
1297
 
1035
1298
    if (qt_xdnd_current_target)
1036
1299
        qt_xdnd_send_leave();
1054
1317
static
1055
1318
Window findRealWindow(const QPoint & pos, Window w, int md)
1056
1319
{
1057
 
    if (xdnd_data.deco && w == xdnd_data.deco->winId())
 
1320
    if (xdnd_data.deco && w == xdnd_data.deco->internalWinId())
1058
1321
        return 0;
1059
1322
 
1060
1323
    if (md) {
1172
1435
                break;
1173
1436
            }
1174
1437
        }
1175
 
        if (xdnd_data.deco && (!target || target == xdnd_data.deco->winId())) {
 
1438
        if (xdnd_data.deco && (!target || target == xdnd_data.deco->internalWinId())) {
1176
1439
            DNDDEBUG << "need to find real window";
1177
1440
            target = findRealWindow(globalPos, rootwin, 6);
1178
1441
            DNDDEBUG << "real window found" << QWidget::find(target) << target;
1223
1486
        qt_xdnd_current_target = target;
1224
1487
        qt_xdnd_current_proxy_target = proxy_target;
1225
1488
        if (target) {
1226
 
            QVector<Atom> type;
 
1489
            QVector<Atom> types;
1227
1490
            int flags = target_version << 24;
1228
1491
            QStringList fmts = QInternalMimeData::formatsHelper(dragPrivate()->data);
1229
1492
            for (int i = 0; i < fmts.size(); ++i) {
1230
 
                type.append(X11->xdndStringToAtom(fmts.at(i).toLatin1().data()));
1231
 
                if (fmts.at(i) == QLatin1String("text/plain")){
1232
 
                    type.append(ATOM(UTF8_STRING));
1233
 
                    type.append(XA_STRING);
 
1493
                QList<Atom> atoms = X11->xdndMimeAtomsForFormat(fmts.at(i));
 
1494
                for (int j = 0; j < atoms.size(); ++j) {
 
1495
                    if (!types.contains(atoms.at(j)))
 
1496
                        types.append(atoms.at(j));
1234
1497
                }
1235
1498
            }
1236
 
            if (type.size() > 3) {
 
1499
            if (types.size() > 3) {
1237
1500
                XChangeProperty(X11->display,
1238
 
                                dragPrivate()->source->winId(), ATOM(XdndTypelist),
 
1501
                                dragPrivate()->source->internalWinId(), ATOM(XdndTypelist),
1239
1502
                                XA_ATOM, 32, PropModeReplace,
1240
 
                                (unsigned char *)type.data(),
1241
 
                                type.size());
 
1503
                                (unsigned char *)types.data(),
 
1504
                                types.size());
1242
1505
                flags |= 0x0001;
1243
1506
            }
1244
1507
            XClientMessageEvent enter;
1246
1509
            enter.window = target;
1247
1510
            enter.format = 32;
1248
1511
            enter.message_type = ATOM(XdndEnter);
1249
 
            enter.data.l[0] = dragPrivate()->source->winId();
 
1512
            enter.data.l[0] = dragPrivate()->source->internalWinId();
1250
1513
            enter.data.l[1] = flags;
1251
 
            enter.data.l[2] = type.size()>0 ? type.at(0) : 0;
1252
 
            enter.data.l[3] = type.size()>1 ? type.at(1) : 0;
1253
 
            enter.data.l[4] = type.size()>2 ? type.at(2) : 0;
 
1514
            enter.data.l[2] = types.size()>0 ? types.at(0) : 0;
 
1515
            enter.data.l[3] = types.size()>1 ? types.at(1) : 0;
 
1516
            enter.data.l[4] = types.size()>2 ? types.at(2) : 0;
1254
1517
            // provisionally set the rectangle to 5x5 pixels...
1255
1518
            qt_xdnd_source_sameanswer = QRect(globalPos.x() - 2,
1256
1519
                                              globalPos.y() -2 , 5, 5);
1275
1538
        move.format = 32;
1276
1539
        move.message_type = ATOM(XdndPosition);
1277
1540
        move.window = target;
1278
 
        move.data.l[0] = dragPrivate()->source->winId();
 
1541
        move.data.l[0] = dragPrivate()->source->internalWinId();
1279
1542
        move.data.l[1] = 0; // flags
1280
1543
        move.data.l[2] = (globalPos.x() << 16) + globalPos.y();
1281
1544
        move.data.l[3] = X11->time;
1304
1567
    Q_ASSERT(heartbeat != -1);
1305
1568
    killTimer(heartbeat);
1306
1569
    heartbeat = -1;
 
1570
    qt_xdnd_dragging = false;
 
1571
 
1307
1572
    if (!qt_xdnd_current_target)
1308
1573
        return;
1309
1574
 
1315
1580
    drop.window = qt_xdnd_current_target;
1316
1581
    drop.format = 32;
1317
1582
    drop.message_type = ATOM(XdndDrop);
1318
 
    drop.data.l[0] = dragPrivate()->source->winId();
 
1583
    drop.data.l[0] = dragPrivate()->source->internalWinId();
1319
1584
    drop.data.l[1] = 0; // flags
1320
1585
    drop.data.l[2] = X11->time;
1321
1586
 
1331
1596
        X11->time,
1332
1597
        qt_xdnd_current_target,
1333
1598
        qt_xdnd_current_proxy_target,
 
1599
        w,
1334
1600
        current_embedding_widget,
1335
1601
        object
1336
1602
    };
1392
1658
    evt.xselection.display = req->display;
1393
1659
    evt.xselection.requestor = req->requestor;
1394
1660
    evt.xselection.selection = req->selection;
1395
 
    evt.xselection.target = req->target;
 
1661
    evt.xselection.target = XNone;
1396
1662
    evt.xselection.property = XNone;
1397
1663
    evt.xselection.time = req->time;
1398
 
    QByteArray format;
1399
 
    if (req->target == XA_STRING || req->target == ATOM(UTF8_STRING))
1400
 
        format = "text/plain";
1401
 
    else
1402
 
        format = X11->xdndAtomToString(req->target);
1403
1664
 
1404
1665
    QDragManager *manager = QDragManager::self();
1405
1666
    QDrag *currentObject = manager->object;
1421
1682
            at = findXdndDropTransactionByWindow(req->requestor);
1422
1683
        }
1423
1684
        if (at == -1 && req->time == CurrentTime) {
1424
 
            // bastards! previous Qt versions always requested the data on a child of the target window
 
1685
            // previous Qt versions always requested the data on a child of the target window
1425
1686
            // using CurrentTime... but it could be asking for either drop data or the current drag's data
1426
1687
            Window target = findXdndAwareParent(req->requestor);
1427
1688
            if (target) {
1442
1703
        manager->object = 0;
1443
1704
    }
1444
1705
    if (manager->object) {
1445
 
        QDragPrivate* dp = QDragManager::self()->dragPrivate();
1446
 
        if (!format.isEmpty() && QInternalMimeData::hasFormatHelper(QLatin1String(format), dp->data)) {
1447
 
            QByteArray a = QInternalMimeData::renderDataHelper(QLatin1String(format), dp->data);
1448
 
            int dataFormat = 8;
1449
 
            int dataSize = a.size();
1450
 
            if (format == "application/x-color") {
1451
 
                dataFormat = 16;
1452
 
                dataSize = a.size() / 2;
1453
 
            }
 
1706
        Atom atomFormat = req->target;
 
1707
        int dataFormat = 0;
 
1708
        QByteArray data;
 
1709
        if (X11->xdndMimeDataForAtom(req->target, manager->dragPrivate()->data,
 
1710
                                     &data, &atomFormat, &dataFormat)) {
 
1711
            int dataSize = data.size() / (dataFormat / 8);
1454
1712
            XChangeProperty (X11->display, req->requestor, req->property,
1455
 
                             req->target, dataFormat, PropModeReplace,
1456
 
                             (unsigned char *)a.data(), dataSize);
 
1713
                             atomFormat, dataFormat, PropModeReplace,
 
1714
                             (unsigned char *)data.data(), dataSize);
1457
1715
            evt.xselection.property = req->property;
 
1716
            evt.xselection.target = atomFormat;
1458
1717
        }
1459
1718
    }
1460
1719
 
1482
1741
        return result;
1483
1742
    }
1484
1743
 
1485
 
 
1486
 
    Atom a = X11->xdndStringToAtom(format);
1487
 
    if (!a)
1488
 
        return result;
1489
 
 
1490
 
    // if a is not provided then find best match
 
1744
    QList<Atom> atoms;
1491
1745
    int i = 0;
1492
 
    bool found = false;
1493
1746
    while ((qt_xdnd_types[i])) {
1494
 
        if (qt_xdnd_types[i] == a) {
1495
 
            found = true;
1496
 
            break;
1497
 
        }
 
1747
        atoms.append(qt_xdnd_types[i]);
1498
1748
        ++i;
1499
1749
    }
1500
 
    if (!found && strcmp(format, "text/plain") == 0) {
1501
 
        int i = 0;
1502
 
        while ((qt_xdnd_types[i])) {
1503
 
            if (qt_xdnd_types[i] == ATOM(UTF8_STRING)) {
1504
 
                a = ATOM(UTF8_STRING);
1505
 
                break;
1506
 
            } else if (qt_xdnd_types[i] == XA_STRING) {
1507
 
                a = XA_STRING;
1508
 
                break;
1509
 
            }
1510
 
            ++i;
1511
 
        }
1512
 
    }
 
1750
    Atom a = X11->xdndMimeAtomForFormat(QLatin1String(format), atoms);
 
1751
    if (!a)
 
1752
        return result;
 
1753
 
1513
1754
    if (XGetSelectionOwner(X11->display, ATOM(XdndSelection)) == XNone)
1514
1755
        return result; // should never happen?
1515
1756
 
1517
1758
    if (!qt_xdnd_current_widget || (qt_xdnd_current_widget->windowType() == Qt::Desktop))
1518
1759
        tw = new QWidget;
1519
1760
 
1520
 
    XConvertSelection(X11->display, ATOM(XdndSelection), a, ATOM(XdndSelection), tw->winId(),
 
1761
    XConvertSelection(X11->display, ATOM(XdndSelection), a, ATOM(XdndSelection), tw->internalWinId(),
1521
1762
                      qt_xdnd_target_current_time);
1522
1763
    XFlush(X11->display);
1523
1764
 
1524
1765
    XEvent xevent;
1525
 
    bool got=X11->clipboardWaitForEvent(tw->winId(), SelectionNotify, &xevent, 5000);
 
1766
    bool got=X11->clipboardWaitForEvent(tw->internalWinId(), SelectionNotify, &xevent, 5000);
1526
1767
    if (got) {
1527
1768
        Atom type;
1528
1769
 
1529
 
        if (X11->clipboardReadProperty(tw->winId(), ATOM(XdndSelection), true, &result, 0, &type, 0, false)) {
 
1770
        if (X11->clipboardReadProperty(tw->internalWinId(), ATOM(XdndSelection), true, &result, 0, &type, 0, false)) {
1530
1771
            if (type == ATOM(INCR)) {
1531
1772
                int nbytes = result.size() >= 4 ? *((int*)result.data()) : 0;
1532
 
                result = X11->clipboardReadIncrementalProperty(tw->winId(), ATOM(XdndSelection), nbytes, false);
 
1773
                result = X11->clipboardReadIncrementalProperty(tw->internalWinId(), ATOM(XdndSelection), nbytes, false);
1533
1774
            } else if (type != a && type != XNone) {
1534
1775
                DEBUG("Qt clipboard: unknown atom %ld", type);
1535
1776
            }
1538
1779
    if (!qt_xdnd_current_widget || (qt_xdnd_current_widget->windowType() == Qt::Desktop))
1539
1780
        delete tw;
1540
1781
 
1541
 
    return result;
 
1782
    return X11->xdndMimeConvertToFormat(a, result, QLatin1String(format));
1542
1783
}
1543
1784
 
1544
1785
 
1588
1829
            if (started > now) // crossed midnight
1589
1830
                started = now;
1590
1831
 
1591
 
            // sleep 50ms, so we don't use up CPU cycles all the time.
 
1832
            // sleep 50 ms, so we don't use up CPU cycles all the time.
1592
1833
            struct timeval usleep_tv;
1593
1834
            usleep_tv.tv_sec = 0;
1594
1835
            usleep_tv.tv_usec = 50000;
1605
1846
    updatePixmap();
1606
1847
 
1607
1848
    qApp->installEventFilter(this);
1608
 
    XSetSelectionOwner(X11->display, ATOM(XdndSelection), dragPrivate()->source->window()->winId(), X11->time);
 
1849
    XSetSelectionOwner(X11->display, ATOM(XdndSelection), dragPrivate()->source->window()->internalWinId(), X11->time);
1609
1850
    global_accepted_action = Qt::CopyAction;
1610
1851
    qt_xdnd_source_sameanswer = QRect();
1611
1852
    move(QCursor::pos());
1705
1946
    } else {
1706
1947
        int i = 0;
1707
1948
        while ((qt_xdnd_types[i])) {
1708
 
           QString f = QLatin1String(X11->xdndAtomToString(qt_xdnd_types[i]));
1709
 
           if (!formats.contains(f))
1710
 
               formats.append(f);
 
1949
            QStringList formatsForAtom = X11->xdndMimeFormatsForAtom(qt_xdnd_types[i]);
 
1950
            for (int j = 0; j < formatsForAtom.size(); ++j) {
 
1951
                if (!formats.contains(formatsForAtom.at(j)))
 
1952
                    formats.append(formatsForAtom.at(j));
 
1953
            }
1711
1954
            ++i;
1712
1955
        }
1713
1956
    }