📄 qdnd_x11.cpp
字号:
current_embedding_widget = embedding_widget; manager->object = currentObject; } } waiting_for_status = false;}void QDragManager::timerEvent(QTimerEvent* e){ if (e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull()) { move(QCursor::pos()); } else if (e->timerId() == transaction_expiry_timer) { for (int i = 0; i < X11->dndDropTransactions.count(); ++i) { const QXdndDropTransaction &t = X11->dndDropTransactions.at(i); if (t.targetWidget) { // dnd within the same process, don't delete these continue; } t.object->deleteLater(); X11->dndDropTransactions.removeAt(i--); } killTimer(transaction_expiry_timer); transaction_expiry_timer = -1; }}bool QDragManager::eventFilter(QObject * o, QEvent * e){ if (beingCancelled) { if (e->type() == QEvent::KeyRelease && ((QKeyEvent*)e)->key() == Qt::Key_Escape) { qApp->removeEventFilter(this); Q_ASSERT(object == 0); beingCancelled = false; eventLoop->exit(); return true; // block the key release } return false; } Q_ASSERT(object != 0); if (!o->isWidgetType()) return false; if (e->type() == QEvent::MouseMove) { QMouseEvent* me = (QMouseEvent *)e; move(me->globalPos()); return true; } else if (e->type() == QEvent::MouseButtonRelease) { DEBUG("pre drop"); qApp->removeEventFilter(this); if (willDrop) drop(); else cancel(); DEBUG("drop, resetting object"); beingCancelled = false; eventLoop->exit(); return true; } if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { QKeyEvent *ke = ((QKeyEvent*)e); if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { cancel(); qApp->removeEventFilter(this); beingCancelled = false; eventLoop->exit(); } else { qt_xdnd_source_sameanswer = QRect(); // force move move(QCursor::pos()); } return true; // Eat all key events } // ### We bind modality to widgets, so we have to do this // ### "manually". // DnD is modal - eat all other interactive events switch (e->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::Wheel: case QEvent::ShortcutOverride:#ifdef QT3_SUPPORT case QEvent::Accel: case QEvent::AccelAvailable:#endif return true; default: return false; }}void QDragManager::updateCursor(){ if (!noDropCursor) { noDropCursor = new QCursor(Qt::ForbiddenCursor); moveCursor = new QCursor(dragCursor(Qt::MoveAction), 0,0); copyCursor = new QCursor(dragCursor(Qt::CopyAction), 0,0); linkCursor = new QCursor(dragCursor(Qt::LinkAction), 0,0); } QCursor *c; if (willDrop) { if (global_accepted_action == Qt::CopyAction) { c = copyCursor; } else if (global_accepted_action == Qt::LinkAction) { c = linkCursor; } else { c = moveCursor; } if (xdnd_data.deco) { xdnd_data.deco->show(); xdnd_data.deco->raise(); } } else { c = noDropCursor; //if (qt_xdnd_deco) // qt_xdnd_deco->hide(); }#ifndef QT_NO_CURSOR if (c) qApp->changeOverrideCursor(*c);#endif}void QDragManager::cancel(bool deleteSource){ DEBUG("QDragManager::cancel"); Q_ASSERT(heartbeat != -1); killTimer(heartbeat); heartbeat = -1; beingCancelled = true; qt_xdnd_dragging = false; if (qt_xdnd_current_target) qt_xdnd_send_leave();#ifndef QT_NO_CURSOR if (restoreCursor) { QApplication::restoreOverrideCursor(); restoreCursor = false; }#endif if (deleteSource && object) object->deleteLater(); object = 0; delete xdnd_data.deco; xdnd_data.deco = 0; global_accepted_action = Qt::IgnoreAction;}staticWindow findRealWindow(const QPoint & pos, Window w, int md){ if (xdnd_data.deco && w == xdnd_data.deco->internalWinId()) return 0; if (md) { X11->ignoreBadwindow(); XWindowAttributes attr; XGetWindowAttributes(X11->display, w, &attr); if (X11->badwindow()) return 0; if (attr.map_state == IsViewable && QRect(attr.x,attr.y,attr.width,attr.height).contains(pos)) { { Atom type = XNone; int f; unsigned long n, a; unsigned char *data; XGetWindowProperty(X11->display, w, ATOM(XdndAware), 0, 0, False, AnyPropertyType, &type, &f,&n,&a,&data); if (data) XFree(data); if (type) return w; } Window r, p; Window* c; uint nc; if (XQueryTree(X11->display, w, &r, &p, &c, &nc)) { r=0; for (uint i=nc; !r && i--;) { r = findRealWindow(pos-QPoint(attr.x,attr.y), c[i], md-1); } XFree(c); if (r) return r; // We didn't find a client window! Just use the // innermost window. } // No children! return w; } } return 0;}void QDragManager::move(const QPoint & globalPos){ DEBUG() << "QDragManager::move enter"; if (!object) { // perhaps the target crashed? return; } int screen = QCursor::x11Screen(); if ((qt_xdnd_current_screen == -1 && screen != X11->defaultScreen) || (screen != qt_xdnd_current_screen)) { // recreate the pixmap on the new screen... delete xdnd_data.deco; xdnd_data.deco = new QShapedPixmapWidget(screen); if (!QWidget::mouseGrabber()) { updatePixmap(); xdnd_data.deco->grabMouse(); } } xdnd_data.deco->move(QCursor::pos() - xdnd_data.deco->pm_hot); if (qt_xdnd_source_sameanswer.contains(globalPos) && qt_xdnd_source_sameanswer.isValid()) return; qt_xdnd_current_screen = screen; Window rootwin = QX11Info::appRootWindow(qt_xdnd_current_screen); Window target = 0; int lx = 0, ly = 0; if (!XTranslateCoordinates(X11->display, rootwin, rootwin, globalPos.x(), globalPos.y(), &lx, &ly, &target)) // some weird error... return; if (target == rootwin) { // Ok. } else if (target) { //me Window src = rootwin; while (target != 0) { DNDDEBUG << "checking target for XdndAware" << QWidget::find(target) << target; int lx2, ly2; Window t; // translate coordinates if (!XTranslateCoordinates(X11->display, src, target, lx, ly, &lx2, &ly2, &t)) { target = 0; break; } lx = lx2; ly = ly2; src = target; // check if it has XdndAware Atom type = 0; int f; unsigned long n, a; unsigned char *data = 0; XGetWindowProperty(X11->display, target, ATOM(XdndAware), 0, 0, False, AnyPropertyType, &type, &f,&n,&a,&data); if (data) XFree(data); if (type) { DNDDEBUG << "Found XdndAware on " << QWidget::find(target) << target; break; } // find child at the coordinates if (!XTranslateCoordinates(X11->display, src, src, lx, ly, &lx2, &ly2, &target)) { target = 0; break; } } if (xdnd_data.deco && (!target || target == xdnd_data.deco->internalWinId())) { DNDDEBUG << "need to find real window"; target = findRealWindow(globalPos, rootwin, 6); DNDDEBUG << "real window found" << QWidget::find(target) << target; } } QWidget* w; if (target) { w = QWidget::find((WId)target); if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops()) w = 0; } else { w = 0; target = rootwin; } DNDDEBUG << "and the final target is " << QWidget::find(target) << target; DNDDEBUG << "the widget w is" << w; WId proxy_target = xdndProxy(target); if (!proxy_target) proxy_target = target; int target_version = 1; if (proxy_target) { Atom type = XNone; int r, f; unsigned long n, a; unsigned char *retval; X11->ignoreBadwindow(); r = XGetWindowProperty(X11->display, proxy_target, ATOM(XdndAware), 0, 1, False, AnyPropertyType, &type, &f,&n,&a,&retval); int *tv = (int *)retval; if (r != Success || X11->badwindow()) { target = 0; } else { target_version = qMin(xdnd_version,tv ? *tv : 1); if (tv) XFree(tv);// if (!(!X11->badwindow() && type))// target = 0; } } if (target != qt_xdnd_current_target) { if (qt_xdnd_current_target) qt_xdnd_send_leave(); qt_xdnd_current_target = target; qt_xdnd_current_proxy_target = proxy_target; if (target) { QVector<Atom> types; int flags = target_version << 24; QStringList fmts = QInternalMimeData::formatsHelper(dragPrivate()->data); for (int i = 0; i < fmts.size(); ++i) { QList<Atom> atoms = X11->xdndMimeAtomsForFormat(fmts.at(i)); for (int j = 0; j < atoms.size(); ++j) { if (!types.contains(atoms.at(j))) types.append(atoms.at(j)); } } if (types.size() > 3) { XChangeProperty(X11->display, dragPrivate()->source->internalWinId(), ATOM(XdndTypelist), XA_ATOM, 32, PropModeReplace, (unsigned char *)types.data(), types.size()); flags |= 0x0001; } XClientMessageEvent enter; enter.type = ClientMessage; enter.window = target; enter.format = 32; enter.message_type = ATOM(XdndEnter); enter.data.l[0] = dragPrivate()->source->internalWinId(); enter.data.l[1] = flags; enter.data.l[2] = types.size()>0 ? types.at(0) : 0; enter.data.l[3] = types.size()>1 ? types.at(1) : 0; enter.data.l[4] = types.size()>2 ? types.at(2) : 0; // provisionally set the rectangle to 5x5 pixels... qt_xdnd_source_sameanswer = QRect(globalPos.x() - 2, globalPos.y() -2 , 5, 5); DEBUG("sending Xdnd enter"); if (w) X11->xdndHandleEnter(w, (const XEvent *)&enter, false); else if (target) XSendEvent(X11->display, proxy_target, False, NoEventMask, (XEvent*)&enter); waiting_for_status = false; } } if (waiting_for_status) return; if (target) { waiting_for_status = true; XClientMessageEvent move; move.type = ClientMessage; move.window = target; move.format = 32; move.message_type = ATOM(XdndPosition); move.window = target; move.data.l[0] = dragPrivate()->source->internalWinId(); move.data.l[1] = 0; // flags move.data.l[2] = (globalPos.x() << 16) + globalPos.y(); move.data.l[3] = X11->time; move.data.l[4] = qtaction_to_xdndaction(defaultAction(dragPrivate()->possible_actions, QApplication::keyboardModifiers())); DEBUG("sending Xdnd position"); qt_xdnd_source_current_time = X11->time; if (w) handle_xdnd_position(w, (const XEvent *)&move, false); else XSendEvent(X11->display, proxy_target, False, NoEventMask, (XEvent*)&move); } else { if (willDrop) { willDrop = false; updateCursor();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -