📄 qdnd_x11.cpp
字号:
} if (data) XFree((uchar*)data); } else { // get the types from the message int i; for(i=2; i < 5; i++) { qt_xdnd_types[j++] = l[i]; } } qt_xdnd_types[j] = 0;}static void handle_xdnd_position(QWidget *w, const XEvent * xe, bool passive){ const unsigned long *l = (const unsigned long *)xe->xclient.data.l; QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff); QWidget * c = find_child(w, p); // changes p to to c-local coordinates if (!passive && checkEmbedded(c, xe)) return; if (!c || !c->acceptDrops() && (c->windowType() == Qt::Desktop)) return; if (l[0] != qt_xdnd_dragsource_xid) { DEBUG("xdnd drag position from unexpected source (%08lx not %08lx)", l[0], qt_xdnd_dragsource_xid); return; } if (l[3] != 0) { // timestamp from the source qt_xdnd_target_current_time = X11->userTime = l[3]; } QDragManager *manager = QDragManager::self(); QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; XClientMessageEvent response; response.type = ClientMessage; response.window = qt_xdnd_dragsource_xid; response.format = 32; response.message_type = ATOM(XdndStatus); response.data.l[0] = w->internalWinId(); response.data.l[1] = 0; // flags response.data.l[2] = 0; // x, y response.data.l[3] = 0; // w, h response.data.l[4] = 0; // action if (!passive) { // otherwise just reject while (c && !c->acceptDrops() && !c->isWindow()) { p = c->mapToParent(p); c = c->parentWidget(); } QWidget *target_widget = c && c->acceptDrops() ? c : 0; QRect answerRect(c->mapToGlobal(p), QSize(1,1)); if (manager->object) { possible_actions = manager->dragPrivate()->possible_actions; } else { possible_actions = Qt::DropActions(xdndaction_to_qtaction(l[4]));// possible_actions |= Qt::CopyAction; } QDragMoveEvent me(p, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); Qt::DropAction accepted_action = Qt::IgnoreAction; if (target_widget != qt_xdnd_current_widget) { if (qt_xdnd_current_widget) { QDragLeaveEvent e; QApplication::sendEvent(qt_xdnd_current_widget, &e); } if (qt_xdnd_current_widget != target_widget) { qt_xdnd_current_widget = target_widget; } if (target_widget) { qt_xdnd_current_position = p; last_target_accepted_action = Qt::IgnoreAction; QDragEnterEvent de(p, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); QApplication::sendEvent(target_widget, &de); if (de.isAccepted() && de.dropAction() != Qt::IgnoreAction) last_target_accepted_action = de.dropAction(); } } DEBUG() << "qt_handle_xdnd_position action=" << X11->xdndAtomToString(l[4]); if (!target_widget) { answerRect = QRect(p, QSize(1, 1)); } else { qt_xdnd_current_widget = c; qt_xdnd_current_position = p; if (last_target_accepted_action != Qt::IgnoreAction) { me.setDropAction(last_target_accepted_action); me.accept(); } QApplication::sendEvent(c, &me); if (me.isAccepted()) { response.data.l[1] = 1; // yes accepted_action = me.dropAction(); last_target_accepted_action = accepted_action; } else { response.data.l[0] = 0; last_target_accepted_action = Qt::IgnoreAction; } answerRect = me.answerRect().intersected(c->rect()); } answerRect = QRect(c->mapToGlobal(answerRect.topLeft()), answerRect.size()); if (answerRect.left() < 0) answerRect.setLeft(0); if (answerRect.right() > 4096) answerRect.setRight(4096); if (answerRect.top() < 0) answerRect.setTop(0); if (answerRect.bottom() > 4096) answerRect.setBottom(4096); if (answerRect.width() < 0) answerRect.setWidth(0); if (answerRect.height() < 0) answerRect.setHeight(0); response.data.l[2] = (answerRect.x() << 16) + answerRect.y(); response.data.l[3] = (answerRect.width() << 16) + answerRect.height(); response.data.l[4] = qtaction_to_xdndaction(accepted_action); } // reset qt_xdnd_target_current_time = CurrentTime; QWidget * source = QWidget::find(qt_xdnd_dragsource_xid); if (source && (source->windowType() == Qt::Desktop) && !source->acceptDrops()) source = 0; DEBUG() << "sending XdndStatus"; if (source) handle_xdnd_status(source, (const XEvent *)&response, passive); else XSendEvent(X11->display, qt_xdnd_dragsource_xid, False, NoEventMask, (XEvent*)&response);}static Bool xdnd_position_scanner(Display *, XEvent *event, XPointer){ if (event->type != ClientMessage) return false; XClientMessageEvent *ev = &event->xclient; if (ev->message_type == ATOM(XdndPosition)) return true; return false;}void QX11Data::xdndHandlePosition(QWidget * w, const XEvent * xe, bool passive){ DEBUG("xdndHandlePosition"); while (XCheckIfEvent(X11->display, (XEvent *)xe, xdnd_position_scanner, 0)) ; handle_xdnd_position(w, xe, passive);}static void handle_xdnd_status(QWidget *, const XEvent * xe, bool){ const unsigned long *l = (const unsigned long *)xe->xclient.data.l; // ignore late status messages if (l[0] && l[0] != qt_xdnd_current_proxy_target) return; Qt::DropAction newAction = (l[1] & 0x1) ? xdndaction_to_qtaction(l[4]) : Qt::IgnoreAction; if ((int)(l[1] & 2) == 0) { QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff); QSize s((l[3] & 0xffff0000) >> 16, l[3] & 0x0000ffff); qt_xdnd_source_sameanswer = QRect(p, s); } else { qt_xdnd_source_sameanswer = QRect(); } QDragManager *manager = QDragManager::self(); manager->willDrop = (l[1] & 0x1); if (global_accepted_action != newAction) manager->emitActionChanged(newAction); global_accepted_action = newAction; manager->updateCursor(); waiting_for_status = false;}static Bool xdnd_status_scanner(Display *, XEvent *event, XPointer){ if (event->type != ClientMessage) return false; XClientMessageEvent *ev = &event->xclient; if (ev->message_type == ATOM(XdndStatus)) return true; return false;}void QX11Data::xdndHandleStatus(QWidget * w, const XEvent * xe, bool passive){ DEBUG("xdndHandleStatus"); while (XCheckIfEvent(X11->display, (XEvent *)xe, xdnd_status_scanner, 0)) ; handle_xdnd_status(w, xe, passive); DEBUG("xdndHandleStatus end");}void QX11Data::xdndHandleLeave(QWidget *w, const XEvent * xe, bool /*passive*/){ DEBUG("xdnd leave"); if (!qt_xdnd_current_widget || w->window() != qt_xdnd_current_widget->window()) { return; // sanity } if (checkEmbedded(current_embedding_widget, xe)) { current_embedding_widget = 0; qt_xdnd_current_widget = 0; return; } const unsigned long *l = (const unsigned long *)xe->xclient.data.l; QDragLeaveEvent e; QApplication::sendEvent(qt_xdnd_current_widget, &e); if (l[0] != qt_xdnd_dragsource_xid) { // This often happens - leave other-process window quickly DEBUG("xdnd drag leave from unexpected source (%08lx not %08lx", l[0], qt_xdnd_dragsource_xid); qt_xdnd_current_widget = 0; return; } qt_xdnd_dragsource_xid = 0; qt_xdnd_types[0] = 0; qt_xdnd_current_widget = 0;}void qt_xdnd_send_leave(){ if (!qt_xdnd_current_target) return; XClientMessageEvent leave; leave.type = ClientMessage; leave.window = qt_xdnd_current_target; leave.format = 32; leave.message_type = ATOM(XdndLeave); leave.data.l[0] = qt_xdnd_dragsource_xid; leave.data.l[1] = 0; // flags leave.data.l[2] = 0; // x, y leave.data.l[3] = 0; // w, h leave.data.l[4] = 0; // just null QWidget * w = QWidget::find(qt_xdnd_current_proxy_target); if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops()) w = 0; if (w) X11->xdndHandleLeave(w, (const XEvent *)&leave, false); else XSendEvent(X11->display, qt_xdnd_current_proxy_target, False, NoEventMask, (XEvent*)&leave); // reset the drag manager state QDragManager *manager = QDragManager::self(); manager->willDrop = false; if (global_accepted_action != Qt::IgnoreAction) manager->emitActionChanged(Qt::IgnoreAction); global_accepted_action = Qt::IgnoreAction; manager->updateCursor(); qt_xdnd_current_target = 0; qt_xdnd_current_proxy_target = 0; qt_xdnd_source_current_time = 0; waiting_for_status = false;}void QX11Data::xdndHandleDrop(QWidget *, const XEvent * xe, bool passive){ DEBUG("xdndHandleDrop"); if (!qt_xdnd_current_widget) { qt_xdnd_dragsource_xid = 0; return; // sanity } if (!passive && checkEmbedded(qt_xdnd_current_widget, xe)){ current_embedding_widget = 0; qt_xdnd_dragsource_xid = 0; qt_xdnd_current_widget = 0; return; } const unsigned long *l = (const unsigned long *)xe->xclient.data.l; QDragManager *manager = QDragManager::self(); DEBUG("xdnd drop"); if (l[0] != qt_xdnd_dragsource_xid) { DEBUG("xdnd drop from unexpected source (%08lx not %08lx", l[0], qt_xdnd_dragsource_xid); return; } if (l[2] != 0) { // update the "user time" from the timestamp in the event. qt_xdnd_target_current_time = X11->userTime = l[2]; } if (!passive) { // this could be a same-application drop, just proxied due to // some XEMBEDding, so try to find the real QMimeData used // based on the timestamp for this drop. QMimeData *dropData = 0; int at = findXdndDropTransactionByTime(qt_xdnd_target_current_time); if (at != -1) dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data; // if we can't find it, then use the data in the drag manager if (!dropData) dropData = (manager->object) ? manager->dragPrivate()->data : manager->dropData; QDropEvent de(qt_xdnd_current_position, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); QApplication::sendEvent(qt_xdnd_current_widget, &de); if (!de.isAccepted()) { // Ignore a failed drag global_accepted_action = Qt::IgnoreAction; } else { global_accepted_action = de.dropAction(); } XClientMessageEvent finished; finished.type = ClientMessage; finished.window = qt_xdnd_dragsource_xid; finished.format = 32; finished.message_type = ATOM(XdndFinished); DNDDEBUG << "xdndHandleDrop" << "qt_xdnd_current_widget" << qt_xdnd_current_widget << (qt_xdnd_current_widget ? qt_xdnd_current_widget->internalWinId() : 0) << "t_xdnd_current_widget->window()" << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window() : 0) << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window()->internalWinId() : 0); finished.data.l[0] = qt_xdnd_current_widget?qt_xdnd_current_widget->window()->internalWinId():0; finished.data.l[1] = de.isAccepted() ? 1 : 0; // flags finished.data.l[2] = qtaction_to_xdndaction(global_accepted_action); XSendEvent(X11->display, qt_xdnd_dragsource_xid, False, NoEventMask, (XEvent*)&finished); } else { QDragLeaveEvent e; QApplication::sendEvent(qt_xdnd_current_widget, &e); } qt_xdnd_dragsource_xid = 0; qt_xdnd_current_widget = 0; waiting_for_status = false; // reset qt_xdnd_target_current_time = CurrentTime;}void QX11Data::xdndHandleFinished(QWidget *, const XEvent * xe, bool passive){ DEBUG("xdndHandleFinished"); const unsigned long *l = (const unsigned long *)xe->xclient.data.l; DNDDEBUG << "xdndHandleFinished, l[0]" << l[0] << "qt_xdnd_current_target" << qt_xdnd_current_target << "qt_xdnd_current_proxy_targe" << qt_xdnd_current_proxy_target; if (l[0]) { int at = findXdndDropTransactionByWindow(l[0]); if (at != -1) { restartXdndDropExpiryTimer(); QXdndDropTransaction t = X11->dndDropTransactions.takeAt(at); QDragManager *manager = QDragManager::self(); Window target = qt_xdnd_current_target; Window proxy_target = qt_xdnd_current_proxy_target; QWidget *embedding_widget = current_embedding_widget; QDrag *currentObject = manager->object; qt_xdnd_current_target = t.target; qt_xdnd_current_proxy_target = t.proxy_target; current_embedding_widget = t.embedding_widget; manager->object = t.object; if (!passive) (void) checkEmbedded(qt_xdnd_current_widget, xe); current_embedding_widget = 0; qt_xdnd_current_target = 0; qt_xdnd_current_proxy_target = 0; if (t.object) t.object->deleteLater(); qt_xdnd_current_target = target; qt_xdnd_current_proxy_target = proxy_target;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -