void QClipboard::setMimeData(QMimeData *src, Mode mode) { if (mode != Clipboard) { delete src; return; } QClipboardData *d = clipboardData(); if (!(d->iData && d->iData->mimeData() == src)) { d->releaseIData(); d->iData = new QOleDataObject(src); } if (OleSetClipboard(d->iData) != S_OK) { d->releaseIData(); qErrnoWarning("QClipboard::setMimeData: Failed to set data on clipboard"); return; } #if defined(Q_OS_WINCE) // As WinCE does not support notifications we send the signal here // We will get no event when the clipboard changes outside... emit dataChanged(); emit changed(Clipboard); #endif }
void QClipboard::clear(Mode mode) { if (mode != Clipboard) return; QClipboardData *d = clipboardData(); d->releaseIData(); if (OleSetClipboard(0) != S_OK) { qErrnoWarning("QClipboard::clear: Failed to clear data on clipboard"); return; } }
bool QClipboard::event(QEvent *e) { if (e->type() != QEvent::Clipboard) return QObject::event(e); QClipboardData *d = clipboardData(); MSG *m = (MSG *)((QClipboardEvent*)e)->data(); if (!m) { // this is sent to render all formats at app shut down if (ownsClipboard()) { OleFlushClipboard(); d->releaseIData(); } return true; } bool propagate = false; if (m->message == WM_CHANGECBCHAIN) { if ((HWND)m->wParam == d->nextClipboardViewer) d->nextClipboardViewer = (HWND)m->lParam; else propagate = true; } else if (m->message == WM_DRAWCLIPBOARD) { emitChanged(QClipboard::Clipboard); if (!ownsClipboard() && d->iData) // clean up the clipboard object if we no longer own the clipboard d->releaseIData(); propagate = true; } if (propagate && d->nextClipboardViewer) { if (ptrIsHungAppWindow == 0) { QSystemLibrary library(QLatin1String("User32")); ptrIsHungAppWindow = (PtrIsHungAppWindow)library.resolve("IsHungAppWindow"); } if (ptrIsHungAppWindow && ptrIsHungAppWindow(d->nextClipboardViewer)) { qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO); } else if (isProcessBeingDebugged(d->nextClipboardViewer)) { // Also refuse if the process is being debugged, specifically, if it is // displaying a runtime assert, which is not caught by isHungAppWindow(). qWarning("%s: Cowardly refusing to send clipboard message to application under debugger...", Q_FUNC_INFO); } else { SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); } } return true; }
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(); }
void QClipboard::setMimeData(QMimeData *src, Mode mode) { if (mode != Clipboard) return; QClipboardData *d = clipboardData(); if (!(d->iData && d->iData->mimeData() == src)) { d->releaseIData(); d->iData = new QOleDataObject(src); } if (OleSetClipboard(d->iData) != S_OK) { d->releaseIData(); qErrnoWarning("QClipboard::setMimeData: Failed to set data on clipboard"); return; } }
void QClipboard::clear(Mode mode) { if (mode != Clipboard) return; QClipboardData *d = clipboardData(); d->releaseIData(); if (OleSetClipboard(0) != S_OK) { qErrnoWarning("QClipboard::clear: Failed to clear data on clipboard"); return; } #if defined(Q_OS_WINCE) // As WinCE does not support notifications we send the signal here // We will get no event when the clipboard changes outside... emit dataChanged(); emit changed(Clipboard); #endif }
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(); } }
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); }
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; } }
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(); }
bool QClipboard::event(QEvent *e) { if (e->type() != QEvent::Clipboard) return QObject::event(e); QClipboardData *d = clipboardData(); MSG *m = (MSG *)((QClipboardEvent*)e)->data(); if (!m) { // this is sent to render all formats at app shut down if (ownsClipboard()) { OleFlushClipboard(); d->releaseIData(); } return true; } bool propagate = false; if (m->message == WM_CHANGECBCHAIN) { if ((HWND)m->wParam == d->nextClipboardViewer) d->nextClipboardViewer = (HWND)m->lParam; else propagate = true; } else if (m->message == WM_DRAWCLIPBOARD) { emitChanged(QClipboard::Clipboard); if (!ownsClipboard() && d->iData) // clean up the clipboard object if we no longer own the clipboard d->releaseIData(); propagate = true; } if (propagate && d->nextClipboardViewer) { SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); } return true; }
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; }
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; }
void QClipboard::setMimeData(QMimeData* src, Mode mode) { Atom atom, sentinel_atom; QClipboardData *d; switch (mode) { case Selection: atom = XA_PRIMARY; sentinel_atom = ATOM(_QT_SELECTION_SENTINEL); d = selectionData(); break; case Clipboard: atom = ATOM(CLIPBOARD); sentinel_atom = ATOM(_QT_CLIPBOARD_SENTINEL); d = clipboardData(); break; default: qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode); return; } Display *dpy = X11->display; Window newOwner; if (! src) { // no data, clear clipboard contents newOwner = XNone; d->clear(); } else { setupOwner(); newOwner = owner->internalWinId(); d->setSource(src); d->timestamp = X11->time; } Window prevOwner = XGetSelectionOwner(dpy, atom); // use X11->time, since d->timestamp == CurrentTime when clearing XSetSelectionOwner(dpy, atom, newOwner, X11->time); if (mode == Selection) emitChanged(QClipboard::Selection); else emitChanged(QClipboard::Clipboard); if (XGetSelectionOwner(dpy, atom) != newOwner) { qWarning("QClipboard::setData: Cannot set X11 selection owner for %s", X11->xdndAtomToString(atom).data()); d->clear(); return; } // Signal to other Qt processes that the selection has changed Window owners[2]; owners[0] = newOwner; owners[1] = prevOwner; XChangeProperty(dpy, QApplication::desktop()->screen(0)->internalWinId(), sentinel_atom, XA_WINDOW, 32, PropModeReplace, (unsigned char*)&owners, 2); }