예제 #1
0
void QClipboard::setMimeData(QMimeData* src, Mode mode)
{
    if (mode != Clipboard) return;

    QClipboardData *d = clipboardData();

    /* Propagate text data to other QWSClients */

    QString newText;
    if( src != 0 )
	newText = src->text();
    QString oldText;
    if( d->source() != 0 )
	oldText = d->source()->text();

    d->setSource(src);

    if( oldText != newText ) {
	if( d->source() == 0 ) {
	    qwsSetClipboardText( QString() );
	} else {
	    qwsSetClipboardText( d->source()->text() );
	}
    }

    emitChanged(QClipboard::Clipboard);
}
예제 #2
0
const QMimeData* QClipboard::mimeData(Mode mode) const
{
    if (mode != Clipboard) return 0;

    QClipboardData *d = clipboardData();
    // Try and get data from QWSProperty if no mime data has been set on us.
    if( !d->source() ) {
	QString t = qwsClipboardText();
	if( !t.isEmpty() ) {
	    QMimeData* nd = new QMimeData;
	    nd->setText( t );
	    d->setSource( nd );
	}
    }
    return d->source();
}
예제 #3
0
const QMimeData* QClipboard::mimeData(Mode mode) const
{
    if (mode != Clipboard) return 0;
    QClipboardData *d = clipboardData();
    bool dataExists(false);
    if (d)
    {
        TRAPD(err,{
            RFs fs = qt_s60GetRFs();
            CClipboard* cb = CClipboard::NewForReadingLC(fs);
            Q_ASSERT(cb);
            //stream for qt
            RStoreReadStream stream;
            TStreamId stid = (cb->StreamDictionary()).At(KQtCbDataStream);
            if (stid != 0) {
                stream.OpenLC(cb->Store(),stid);
                QT_TRYCATCH_LEAVING(readFromStreamLX(d->source(),stream));
                CleanupStack::PopAndDestroy(&stream);
                dataExists = true;
            }
            else {
                //symbian clipboard
                RStoreReadStream symbianStream;
                TStreamId symbianStId = (cb->StreamDictionary()).At(KClipboardUidTypePlainText);
                if (symbianStId != 0) {
                    symbianStream.OpenLC(cb->Store(), symbianStId);
                    QT_TRYCATCH_LEAVING(readSymbianStoreLX(d->source(), cb));
                    CleanupStack::PopAndDestroy(&symbianStream);
                    dataExists = true;
                }
            }
            CleanupStack::PopAndDestroy(cb);
        });
        if (err != KErrNone){
            qDebug()<< "clipboard is empty/err: " << err;
        }

        if (dataExists) {
            return d->source();
        }
    }
const QMimeData* QClipboard::mimeData(Mode mode) const
{
    if (mode != Clipboard) return 0;
    QClipboardData *d = clipboardData();
    if (d)
    {
        TRAPD(err,{
            RFs fs = qt_s60GetRFs();
            CClipboard* cb = CClipboard::NewForReadingLC(fs);
            Q_ASSERT(cb);
            RStoreReadStream stream;
            TStreamId stid = (cb->StreamDictionary()).At(KQtCbDataStream);
            stream.OpenLC(cb->Store(),stid);
            QT_TRYCATCH_LEAVING(readFromStreamLX(d->source(),stream));
            CleanupStack::PopAndDestroy(2,cb);
            return d->source();
        });
        if (err != KErrNone){
            qDebug()<< "clipboard is empty/err: " << err;
        }

    }
예제 #5
0
bool QClipboard::event(QEvent *e)
{
    static bool recursionWatch = false;
    if (e->type() != QEvent::Clipboard || recursionWatch)
        return QObject::event(e);

    recursionWatch = true;
    QWSPropertyNotifyEvent *event = (QWSPropertyNotifyEvent *)(((QClipboardEvent *)e)->data());
    if (event && event->simpleData.state == QWSPropertyNotifyEvent::PropertyNewValue) {
	QClipboardData *d = clipboardData();
	QString t = qwsClipboardText();
	if( (d->source() == 0 && !t.isEmpty()) || (d->source() != 0 && d->source()->text() != t) ) {
	    if( !d->source() )
		d->setSource(new QMimeData);
	    d->source()->setText( t );
	    emitChanged(QClipboard::Clipboard);
	}
    }

    recursionWatch = false;
    return true;
}
예제 #6
0
파일: qclipboard_x11.cpp 프로젝트: BGmot/Qt
const QMimeData* QClipboard::mimeData(Mode mode) const
{
    QClipboardData *d = 0;
    switch (mode) {
    case Selection:
        d = selectionData();
        break;
    case Clipboard:
        d = clipboardData();
        break;
    default:
        qWarning("QClipboard::mimeData: unsupported mode '%d'", mode);
        return 0;
    }

    if (! d->source() && ! timer_event_clear) {
        if (mode == Selection) {
            if (! selection_watcher)
                selection_watcher = new QClipboardWatcher(mode);
            d->setSource(selection_watcher);
        } else {
            if (! clipboard_watcher)
                clipboard_watcher = new QClipboardWatcher(mode);
            d->setSource(clipboard_watcher);
        }

        if (! timer_id) {
            // start a zero timer - we will clear cached data when the timer
            // times out, which will be the next time we hit the event loop...
            // that way, the data is cached long enough for calls within a single
            // loop/function, but the data doesn't linger around in case the selection
            // changes
            QClipboard *that = ((QClipboard *) this);
            timer_id = that->startTimer(0);
        }
    }

    return d->source();
}
예제 #7
0
파일: qclipboard_x11.cpp 프로젝트: BGmot/Qt
bool QClipboard::event(QEvent *e)
{
    if (e->type() == QEvent::Timer) {
        QTimerEvent *te = (QTimerEvent *) e;

        if (waiting_for_data) // should never happen
            return false;

        if (te->timerId() == timer_id) {
            killTimer(timer_id);
            timer_id = 0;

            timer_event_clear = true;
            if (selection_watcher) // clear selection
                selectionData()->clear();
            if (clipboard_watcher) // clear clipboard
                clipboardData()->clear();
            timer_event_clear = false;

            return true;
        } else if (te->timerId() == pending_timer_id) {
            // I hate klipper
            killTimer(pending_timer_id);
            pending_timer_id = 0;

            if (pending_clipboard_changed) {
                pending_clipboard_changed = false;
                clipboardData()->clear();
                emitChanged(QClipboard::Clipboard);
            }
            if (pending_selection_changed) {
                pending_selection_changed = false;
                selectionData()->clear();
                emitChanged(QClipboard::Selection);
            }

            return true;
        } else if (te->timerId() == incr_timer_id) {
            killTimer(incr_timer_id);
            incr_timer_id = 0;

            qt_xclb_incr_timeout();

            return true;
        } else {
            return QObject::event(e);
        }
    } else if (e->type() != QEvent::Clipboard) {
        return QObject::event(e);
    }

    XEvent *xevent = (XEvent *)(((QClipboardEvent *)e)->data());
    Display *dpy = X11->display;

    if (!xevent) {
        // That means application exits and we need to give clipboard
        // content to the clipboard manager.
        // First we check if there is a clipboard manager.
        if (XGetSelectionOwner(X11->display, ATOM(CLIPBOARD_MANAGER)) == XNone
            || !owner)
            return true;

        Window ownerId = owner->internalWinId();
        Q_ASSERT(ownerId);
        // we delete the property so the manager saves all TARGETS.
        XDeleteProperty(X11->display, ownerId, ATOM(_QT_SELECTION));
        XConvertSelection(X11->display, ATOM(CLIPBOARD_MANAGER), ATOM(SAVE_TARGETS),
                          ATOM(_QT_SELECTION), ownerId, X11->time);
        XSync(dpy, false);

        XEvent event;
        // waiting until the clipboard manager fetches the content.
        if (!X11->clipboardWaitForEvent(ownerId, SelectionNotify, &event, 10000)) {
            qWarning("QClipboard: Unable to receive an event from the "
                     "clipboard manager in a reasonable time");
        }

        return true;
    }

    switch (xevent->type) {

    case SelectionClear:
        // new selection owner
        if (xevent->xselectionclear.selection == XA_PRIMARY) {
            QClipboardData *d = selectionData();

            // ignore the event if it was generated before we gained selection ownership
            if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp)
                break;

            DEBUG("QClipboard: new selection owner 0x%lx at time %lx (ours %lx)",
                  XGetSelectionOwner(dpy, XA_PRIMARY),
                  xevent->xselectionclear.time, d->timestamp);

            if (! waiting_for_data) {
                d->clear();
                emitChanged(QClipboard::Selection);
            } else {
                pending_selection_changed = true;
                if (! pending_timer_id)
                    pending_timer_id = QApplication::clipboard()->startTimer(0);
            }
        } else if (xevent->xselectionclear.selection == ATOM(CLIPBOARD)) {
            QClipboardData *d = clipboardData();

            // ignore the event if it was generated before we gained selection ownership
            if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp)
                break;

            DEBUG("QClipboard: new clipboard owner 0x%lx at time %lx (%lx)",
                  XGetSelectionOwner(dpy, ATOM(CLIPBOARD)),
                  xevent->xselectionclear.time, d->timestamp);

            if (! waiting_for_data) {
                d->clear();
                emitChanged(QClipboard::Clipboard);
            } else {
                pending_clipboard_changed = true;
                if (! pending_timer_id)
                    pending_timer_id = QApplication::clipboard()->startTimer(0);
            }
        } else {
            qWarning("QClipboard: Unknown SelectionClear event received");
            return false;
        }
        break;

    case SelectionNotify:
        /*
          Something has delivered data to us, but this was not caught
          by QClipboardWatcher::getDataInFormat()

          Just skip the event to prevent Bad Things (tm) from
          happening later on...
        */
        break;

    case SelectionRequest:
        {
            // someone wants our data
            XSelectionRequestEvent *req = &xevent->xselectionrequest;

            if (requestor && req->requestor == requestor->internalWinId())
                break;

            XEvent event;
            event.xselection.type      = SelectionNotify;
            event.xselection.display   = req->display;
            event.xselection.requestor = req->requestor;
            event.xselection.selection = req->selection;
            event.xselection.target    = req->target;
            event.xselection.property  = XNone;
            event.xselection.time      = req->time;

            DEBUG("QClipboard: SelectionRequest from %lx\n"
                  "    selection 0x%lx (%s) target 0x%lx (%s)",
                  req->requestor,
                  req->selection,
                  X11->xdndAtomToString(req->selection).data(),
                  req->target,
                  X11->xdndAtomToString(req->target).data());

            QClipboardData *d;
            if (req->selection == XA_PRIMARY) {
                d = selectionData();
            } else if (req->selection == ATOM(CLIPBOARD)) {
                d = clipboardData();
            } else {
                qWarning("QClipboard: Unknown selection '%lx'", req->selection);
                XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
                break;
            }

            if (! d->source()) {
                qWarning("QClipboard: Cannot transfer data, no data available");
                XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
                break;
            }

            DEBUG("QClipboard: SelectionRequest at time %lx (ours %lx)",
                  req->time, d->timestamp);

            if (d->timestamp == CurrentTime // we don't own the selection anymore
                || (req->time != CurrentTime && req->time < d->timestamp)) {
                DEBUG("QClipboard: SelectionRequest too old");
                XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
                break;
            }

            Atom xa_targets = ATOM(TARGETS);
            Atom xa_multiple = ATOM(MULTIPLE);
            Atom xa_timestamp = ATOM(TIMESTAMP);

            struct AtomPair { Atom target; Atom property; } *multi = 0;
            Atom multi_type = XNone;
            int multi_format = 0;
            int nmulti = 0;
            int imulti = -1;
            bool multi_writeback = false;

            if (req->target == xa_multiple) {
                QByteArray multi_data;
                if (req->property == XNone
                    || !X11->clipboardReadProperty(req->requestor, req->property, false, &multi_data,
                                                   0, &multi_type, &multi_format)
                    || multi_format != 32) {
                    // MULTIPLE property not formatted correctly
                    XSendEvent(dpy, req->requestor, False, NoEventMask, &event);
                    break;
                }
                nmulti = multi_data.size()/sizeof(*multi);
                multi = new AtomPair[nmulti];
                memcpy(multi,multi_data.data(),multi_data.size());
                imulti = 0;
            }

            for (; imulti < nmulti; ++imulti) {
                Atom target;
                Atom property;

                if (multi) {
                    target = multi[imulti].target;
                    property = multi[imulti].property;
                } else {
                    target = req->target;
                    property = req->property;
                    if (property == XNone) // obsolete client
                        property = target;
                }

                Atom ret = XNone;
                if (target == XNone || property == XNone) {
                    ;
                } else if (target == xa_timestamp) {
                    if (d->timestamp != CurrentTime) {
                        XChangeProperty(dpy, req->requestor, property, XA_INTEGER, 32,
                                        PropModeReplace, (uchar *) &d->timestamp, 1);
                        ret = property;
                    } else {
                        qWarning("QClipboard: Invalid data timestamp");
                    }
                } else if (target == xa_targets) {
                    ret = send_targets_selection(d, req->requestor, property);
                } else {
                    ret = send_selection(d, target, req->requestor, property);
                }

                if (nmulti > 0) {
                    if (ret == XNone) {
                        multi[imulti].property = XNone;
                        multi_writeback = true;
                    }
                } else {
                    event.xselection.property = ret;
                    break;
                }
            }

            if (nmulti > 0) {
                if (multi_writeback) {
                    // according to ICCCM 2.6.2 says to put None back
                    // into the original property on the requestor window
                    XChangeProperty(dpy, req->requestor, req->property, multi_type, 32,
                                    PropModeReplace, (uchar *) multi, nmulti * 2);
                }

                delete [] multi;
                event.xselection.property = req->property;
            }

            // send selection notify to requestor
            XSendEvent(dpy, req->requestor, False, NoEventMask, &event);

            DEBUG("QClipboard: SelectionNotify to 0x%lx\n"
                  "    property 0x%lx (%s)",
                  req->requestor, event.xselection.property,
                  X11->xdndAtomToString(event.xselection.property).data());
        }
        break;
    }

    return true;
}