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

📄 qclipboard_x11.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            usleep_tv.tv_sec = 0;            usleep_tv.tv_usec = 50000;            select(0, 0, 0, 0, &usleep_tv);        } while (started.msecsTo(now) < timeout);    }    return false;}static inline int maxSelectionIncr(Display *dpy){ return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; }bool QX11Data::clipboardReadProperty(Window win, Atom property, bool deleteProperty,                                     QByteArray *buffer, int *size, Atom *type, int *format, bool nullterm){    int           maxsize = maxSelectionIncr(display);    ulong  bytes_left; // bytes_after    ulong  length;     // nitems    uchar *data;    Atom   dummy_type;    int    dummy_format;    int    r;    if (!type)                                // allow null args        type = &dummy_type;    if (!format)        format = &dummy_format;    // Don't read anything, just get the size of the property data    r = XGetWindowProperty(display, win, property, 0, 0, False,                            AnyPropertyType, type, format,                            &length, &bytes_left, &data);    if (r != Success || (type && *type == XNone)) {        buffer->resize(0);        return false;    }    XFree((char*)data);    int  offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left;    VDEBUG("QClipboard: read_property(): initial property length: %d", proplen);    switch (*format) {    case 8:    default:        format_inc = sizeof(char) / 1;        break;    case 16:        format_inc = sizeof(short) / 2;        proplen *= sizeof(short) / 2;        break;    case 32:        format_inc = sizeof(long) / 4;        proplen *= sizeof(long) / 4;        break;    }    int newSize = proplen + (nullterm ? 1 : 0);    buffer->resize(newSize);    bool ok = (buffer->size() == newSize);    VDEBUG("QClipboard: read_property(): buffer resized to %d", buffer->size());    if (ok) {        // could allocate buffer        while (bytes_left) {            // more to read...            r = XGetWindowProperty(display, win, property, offset, maxsize/4,                                   False, AnyPropertyType, type, format,                                   &length, &bytes_left, &data);            if (r != Success || (type && *type == XNone))                break;            offset += length / (32 / *format);            length *= format_inc * (*format) / 8;            // Here we check if we get a buffer overflow and tries to            // recover -- this shouldn't normally happen, but it doesn't            // hurt to be defensive            if ((int)(buffer_offset + length) > buffer->size()) {                length = buffer->size() - buffer_offset;                // escape loop                bytes_left = 0;            }            memcpy(buffer->data() + buffer_offset, data, length);            buffer_offset += length;            XFree((char*)data);        }        if (*format == 8 && *type == ATOM(COMPOUND_TEXT)) {            // convert COMPOUND_TEXT to a multibyte string            XTextProperty textprop;            textprop.encoding = *type;            textprop.format = *format;            textprop.nitems = length;            textprop.value = (unsigned char *) buffer->data();            char **list_ret = 0;            int count;            if (XmbTextPropertyToTextList(display, &textprop, &list_ret,                         &count) == Success && count && list_ret) {                offset = strlen(list_ret[0]);                buffer->resize(offset + (nullterm ? 1 : 0));                memcpy(buffer->data(), list_ret[0], offset);            }            if (list_ret) XFreeStringList(list_ret);        }        // zero-terminate (for text)        if (nullterm)            buffer->data()[buffer_offset] = '\0';    }    // correct size, not 0-term.    if (size)        *size = buffer_offset;    VDEBUG("QClipboard: read_property(): buffer size %d, buffer offset %d, offset %d",           buffer->size(), buffer_offset, offset);    if (deleteProperty)        XDeleteProperty(display, win, property);    XFlush(display);    return ok;}QByteArray QX11Data::clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm){    XEvent event;    QByteArray buf;    QByteArray tmp_buf;    bool alloc_error = false;    int  length;    int  offset = 0;    if (nbytes > 0) {        // Reserve buffer + zero-terminator (for text data)        // We want to complete the INCR transfer even if we cannot        // allocate more memory        buf.resize(nbytes+1);        alloc_error = buf.size() != nbytes+1;    }    for (;;) {        XFlush(display);        if (!clipboardWaitForEvent(win,PropertyNotify,&event,clipboard_timeout))            break;        if (event.xproperty.atom != property ||             event.xproperty.state != PropertyNewValue)            continue;        if (X11->clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0, false)) {            if (length == 0) {                // no more data, we're done                if (nullterm) {                    buf.resize(offset+1);                    buf[offset] = '\0';                } else {                    buf.resize(offset);                }                return buf;            } else if (!alloc_error) {                if (offset+length > (int)buf.size()) {                    buf.resize(offset+length+65535);                    if (buf.size() != offset+length+65535) {                        alloc_error = true;                        length = buf.size() - offset;                    }                }                memcpy(buf.data()+offset, tmp_buf.constData(), length);                tmp_buf.resize(0);                offset += length;            }        } else {            break;        }    }    // timed out ... create a new requestor window, otherwise the requestor    // could consider next request to be still part of this timed out request    delete requestor;    requestor = new QWidget(0);    requestor->setObjectName(QLatin1String("internal clipboard requestor"));    return QByteArray();}static Atom send_targets_selection(QClipboardData *d, Window window, Atom property){    QVector<Atom> types;    QStringList formats = QInternalMimeData::formatsHelper(d->source());    for (int i = 0; i < formats.size(); ++i) {        QList<Atom> atoms = X11->xdndMimeAtomsForFormat(formats.at(i));        for (int j = 0; j < atoms.size(); ++j) {            if (!types.contains(atoms.at(j)))                types.append(atoms.at(j));        }    }    types.append(ATOM(TARGETS));    types.append(ATOM(MULTIPLE));    types.append(ATOM(TIMESTAMP));    XChangeProperty(X11->display, window, property, XA_ATOM, 32,                    PropModeReplace, (uchar *) types.data(), types.size());    return property;}static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom property){    Atom atomFormat = target;    int dataFormat = 0;    QByteArray data;    if (X11->xdndMimeDataForAtom(target, d->source(), &data, &atomFormat, &dataFormat)) {        VDEBUG("QClipboard: send_selection():\n"          "    property type %lx\n"          "    property name '%s'\n"          "    format %d\n"          "    %d bytes\n",          target, X11->xdndMimeAtomToString(atomFormat).toLatin1().data(), dataFormat, 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, atomFormat, dataFormat, 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?        int dataSize = data.size() / (dataFormat / 8);        // use a single request to transfer data        XChangeProperty(X11->display, window, property, atomFormat,                        dataFormat, PropModeReplace, (uchar *) data.data(),                        dataSize);    }    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();                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)        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;

⌨️ 快捷键说明

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