⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qclipboard_x11.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    Pixmap handle = pm.handle();    XChangeProperty(X11->display, window, property,                    target, 32, PropModeReplace, (uchar *) &handle, 1);    d->addTransferredPixmap(pm);    return property;}static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom property,                           int format, QByteArray data){    if (format == 0) format = 8;    if (data.isEmpty()) {        QByteArray fmt = X11->xdndAtomToString(target);        DEBUG("QClipboard: send_selection(): converting to type '%s'", fmt.data());	if (fmt.isEmpty() || !QInternalMimeData::hasFormatHelper(fmt, d->source())) // Not a MIME type we have	    return XNone;         else	    data = QInternalMimeData::renderDataHelper(fmt, d->source());    }    DEBUG("QClipboard: send_selection():\n"          "    property type %lx\n"          "    property name '%s'\n"          "    format %d\n"          "    %d bytes",          target, X11->xdndAtomToString(target).data(), format, data.size());    // don't allow INCR transfers when using MULTIPLE or to    // Motif clients (since Motif doesn't support INCR)    static Atom motif_clip_temporary = ATOM(CLIP_TEMPORARY);    bool allow_incr = property != motif_clip_temporary;    // X_ChangeProperty protocol request is 24 bytes    const int increment = (XMaxRequestSize(X11->display) * 4) - 24;    if (data.size() > increment && allow_incr) {        long bytes = data.size();        XChangeProperty(X11->display, window, property,                        ATOM(INCR), 32, PropModeReplace, (uchar *) &bytes, 1);        (void)new QClipboardINCRTransaction(window, property, target, format, data, increment);        return ATOM(INCR);    }    // make sure we can perform the XChangeProperty in a single request    if (data.size() > increment)        return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend?    // use a single request to transfer data    XChangeProperty(X11->display, window, property, target,                    format, PropModeReplace, (uchar *) data.data(),                    data.size() / sizeof_format(format));    return property;}/*! \internal    Internal cleanup for Windows.*/void QClipboard::ownerDestroyed(){ }/*! \internal    Internal optimization for Windows.*/void QClipboard::connectNotify(const char *){ }/*! \reimp */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();                emit dataChanged();            }            if (pending_selection_changed) {                pending_selection_changed = false;                selectionData()->clear();                emit selectionChanged();            }            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)        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();                emit selectionChanged();            } 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();                emit dataChanged();            } 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->winId())                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, 0)                    || 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_timestamp, 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 if (target == XA_STRING                           || target == ATOM(TEXT)                           || target == ATOM(COMPOUND_TEXT)                           || target == ATOM(UTF8_STRING)) {                    ret = send_string_selection(d, target, req->requestor, property);                } else if (target == XA_PIXMAP                           || target == XA_BITMAP) {                    ret = send_pixmap_selection(d, target, 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;}QClipboardWatcher::QClipboardWatcher(QClipboard::Mode mode)    : QInternalMimeData(){    switch (mode) {    case QClipboard::Selection:        atom = XA_PRIMARY;        break;    case QClipboard::Clipboard:        atom = ATOM(CLIPBOARD);        break;    default:        qWarning("QClipboardWatcher: internal error, unknown clipboard mode");        break;    }    setupOwner();}QClipboardWatcher::~QClipboardWatcher(){    if(selection_watcher == this)        selection_watcher = 0;    if(clipboard_watcher == this)        clipboard_watcher = 0;}bool QClipboardWatcher::empty() const{    Display *dpy = X11->display;    Window win = XGetSelectionOwner(dpy, atom);    if(win == requestor->winId()) {        qWarning("QClipboardWatcher::empty: internal error, app owns the selection");        return true;    }    return win == XNone;}QStringList QClipboardWatcher::formats_sys() const

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -