void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event) { Q_ASSERT(event->type() ==QEvent::DragMove || !m_dragTarget); // Find a target widget under mouse that accepts drops (QTBUG-22987). QWidget *widget = m_widget->childAt(event->pos()); if (!widget) widget = m_widget; for ( ; widget && !widget->isWindow() && !widget->acceptDrops(); widget = widget->parentWidget()) ; if (widget && !widget->acceptDrops()) widget = 0; // Target widget unchanged: DragMove if (widget && widget == m_dragTarget.data()) { Q_ASSERT(event->type() == QEvent::DragMove); const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos())); QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers()); translated.setDropAction(event->dropAction()); if (event->isAccepted()) { // Handling 'DragEnter' should suffice for the application. translated.accept(); translated.setDropAction(event->dropAction()); } QGuiApplication::sendSpontaneousEvent(widget, &translated); if (translated.isAccepted()) { event->accept(); } else { event->ignore(); } event->setDropAction(translated.dropAction()); return; } // Target widget changed: Send DragLeave to previous, DragEnter to new if there is any if (m_dragTarget.data()) { QDragLeaveEvent le; QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &le); m_dragTarget = 0; } if (!widget) { event->ignore(); return; } m_dragTarget = widget; const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos())); QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers()); QGuiApplication::sendSpontaneousEvent(widget, &translated); if (translated.isAccepted()) { event->accept(); } else { event->ignore(); } event->setDropAction(translated.dropAction()); }
static 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 = qt_xdnd_leave; 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_target ); int emask = NoEventMask; if ( w && w->isDesktop() && !w->acceptDrops() ) { emask = EnterWindowMask; w = 0; } if ( w ) qt_handle_xdnd_leave( w, (const XEvent *)&leave ); else XSendEvent( qt_xdisplay(), qt_xdnd_current_target, FALSE, emask, (XEvent*)&leave ); qt_xdnd_current_target = 0; }
void QDragManager::drop() { if ( !qt_xdnd_current_target ) return; delete qt_xdnd_deco; qt_xdnd_deco = 0; XClientMessageEvent drop; drop.type = ClientMessage; drop.window = qt_xdnd_current_target; drop.format = 32; drop.message_type = qt_xdnd_drop; drop.data.l[0] = object->source()->winId(); drop.data.l[1] = 1 << 24; // flags drop.data.l[2] = 0; // ### drop.data.l[3] = qt_x_clipboardtime; drop.data.l[4] = 0; QWidget * w = QWidget::find( qt_xdnd_current_target ); int emask = NoEventMask; if ( w && w->isDesktop() && !w->acceptDrops() ) { emask = EnterWindowMask; w = 0; } if ( w ) qt_handle_xdnd_drop( w, (const XEvent *)&drop ); else XSendEvent( qt_xdisplay(), qt_xdnd_current_target, FALSE, emask, (XEvent*)&drop ); qt_xdnd_current_target = 0; if ( restoreCursor ) { QApplication::restoreOverrideCursor(); restoreCursor = FALSE; } }
bool QDragManager::eventFilter(QObject *o, QEvent *e) { if (beingCancelled) { if (e->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) { qApp->removeEventFilter(this); Q_ASSERT(object == 0); beingCancelled = false; #ifndef QT_NO_LOCALEVENTLOOP eventLoop->exit(); #else asyncDragFinished(); #endif return true; // block the key release } return false; } if (!o->isWidgetType()) return false; switch(e->type()) { case QEvent::ShortcutOverride: // prevent accelerators from firing while dragging e->accept(); return true; case QEvent::KeyPress: case QEvent::KeyRelease: { QKeyEvent *ke = ((QKeyEvent*)e); if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { cancel(); qApp->removeEventFilter(this); beingCancelled = false; #ifndef QT_NO_LOCALEVENTLOOP eventLoop->exit(); #else asyncDragFinished(); #endif } else { updateCursor(); } return true; // Eat all key events } case QEvent::MouseButtonPress: case QEvent::MouseMove: { if (!object) { //#### this should not happen qWarning("QDragManager::eventFilter: No object"); return true; } QDragManager *manager = QDragManager::self(); QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; if (manager->object) possible_actions = manager->dragPrivate()->possible_actions; else possible_actions = Qt::IgnoreAction; QMouseEvent *me = (QMouseEvent *)e; if (me->buttons()) { Qt::DropAction prevAction = global_accepted_action; QWidget *cw = QApplication::widgetAt(me->globalPos()); // Fix for when we move mouse on to the deco widget if (qt_qws_dnd_deco && cw == qt_qws_dnd_deco) cw = object->target(); while (cw && !cw->acceptDrops() && !cw->isWindow()) cw = cw->parentWidget(); if (object->target() != cw) { if (object->target()) { QDragLeaveEvent dle; QApplication::sendEvent(object->target(), &dle); willDrop = false; global_accepted_action = Qt::IgnoreAction; updateCursor(); restoreCursor = true; object->d_func()->target = 0; } if (cw && cw->acceptDrops()) { object->d_func()->target = cw; QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, me->buttons(), me->modifiers()); QApplication::sendEvent(object->target(), &dee); willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction; updateCursor(); restoreCursor = true; } } else if (cw) { QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, me->buttons(), me->modifiers()); if (global_accepted_action != Qt::IgnoreAction) { dme.setDropAction(global_accepted_action); dme.accept(); } QApplication::sendEvent(cw, &dme); willDrop = dme.isAccepted(); global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction; updatePixmap(); updateCursor(); } if (global_accepted_action != prevAction) emitActionChanged(global_accepted_action); } return true; // Eat all mouse events } case QEvent::MouseButtonRelease: { qApp->removeEventFilter(this); if (restoreCursor) { willDrop = false; #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); #endif restoreCursor = false; } if (object && object->target()) { QMouseEvent *me = (QMouseEvent *)e; QDragManager *manager = QDragManager::self(); QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData, me->buttons(), me->modifiers()); QApplication::sendEvent(object->target(), &de); if (de.isAccepted()) global_accepted_action = de.dropAction(); else global_accepted_action = Qt::IgnoreAction; if (object) object->deleteLater(); drag_object = object = 0; } #ifndef QT_NO_LOCALEVENTLOOP eventLoop->exit(); #else asyncDragFinished(); #endif return true; // Eat all mouse events } default: break; } return false; }
bool QDragManager::eventFilter( QObject *o, QEvent *e ) { if ( !o->isWidgetType() ) return FALSE; switch( e->type() ) { case QEvent::KeyPress: case QEvent::KeyRelease: { QKeyEvent *ke = ((QKeyEvent*)e); if ( ke->key() == Key_Escape && e->type() == QEvent::KeyPress ) { cancel(); qApp->removeEventFilter( this ); dragSource = 0; } else { updateMode(ke->stateAfter()); updateCursor(); } return TRUE; // Eat all key events } case QEvent::MouseButtonPress: case QEvent::MouseMove: { QMouseEvent *me = (QMouseEvent *)e; if ( me->state() & ( QMouseEvent::LeftButton | QMouseEvent::MidButton | QMouseEvent::RightButton ) ) { QWidget *cw = QApplication::widgetAt( me->globalPos(), TRUE ); // Fix for when we move mouse on to the deco widget if ( qt_qws_dnd_deco && cw == qt_qws_dnd_deco ) cw = dropWidget; if ( dropWidget != cw ) { if ( dropWidget ) { QDragLeaveEvent dle; QApplication::sendEvent( dropWidget, &dle ); willDrop = FALSE; updateCursor(); restoreCursor = TRUE; dropWidget = NULL; } if ( cw && cw->acceptDrops() ) { dropWidget = cw; QDragEnterEvent dee( me->pos() ); QApplication::sendEvent( dropWidget, &dee ); willDrop = dee.isAccepted(); updateCursor(); restoreCursor = TRUE; } } else if ( cw ) { QDragMoveEvent dme( me->pos() ); QApplication::sendEvent( cw, &dme ); updatePixmap(); } } return TRUE; // Eat all mouse events } case QEvent::MouseButtonRelease: { qApp->removeEventFilter( this ); if ( qt_qws_dnd_deco ) delete qt_qws_dnd_deco; qt_qws_dnd_deco = 0; if ( restoreCursor ) { willDrop = FALSE; myRestoreOverrideCursor(); restoreCursor = FALSE; } if ( dropWidget ) { QMouseEvent *me = (QMouseEvent *)e; QDropEvent de( me->pos() ); QApplication::sendEvent( dropWidget, &de ); dropWidget = NULL; } return TRUE; // Eat all mouse events } default: break; } return FALSE; }
void QX11Data::motifdndHandle(QWidget *widget, const XEvent * xe, bool /* passive */) { XEvent event = *xe; XClientMessageEvent cm ; DndData dnd_data ; char receiver ; if (!(DndParseClientMessage ((XClientMessageEvent*)&event, &dnd_data, &receiver))) { return; } switch (dnd_data.reason) { case DND_DRAG_MOTION: { QPoint p = widget->mapFromGlobal(QPoint(dnd_data.x, dnd_data.y)); QWidget *c = widget->childAt(p); if (!c || !c->acceptDrops()) { // not over a drop site if (dropWidget) { QDragLeaveEvent dragLeaveEvent; QApplication::sendEvent(dropWidget, &dragLeaveEvent); dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; dnd_data.reason = DND_DROP_SITE_LEAVE; dnd_data.time = X11->time; DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ; } else { dnd_data.reason = DND_DRAG_MOTION; dnd_data.status = DND_NO_DROP_SITE; dnd_data.time = X11->time; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ; } } else { Q_ASSERT(c != 0); p = c->mapFrom(widget, p); if (dropWidget != c) { if (dropWidget) { QDragLeaveEvent le; QApplication::sendEvent(dropWidget, &le); } dropWidget = c; lastAcceptedAction = Qt::IgnoreAction; const Qt::DropActions possibleActions = DndOperationsToQtDropActions(dnd_data.operations); QDragEnterEvent de(p, possibleActions, QDragManager::self()->dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); QApplication::sendEvent(dropWidget, &de); dnd_data.reason = DND_DROP_SITE_ENTER; dnd_data.time = X11->time; if (de.isAccepted()) { lastAcceptedAction = de.dropAction(); dnd_data.status = DND_VALID_DROP_SITE; dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction); } else { dnd_data.status = DND_INVALID_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; } DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); } else { const Qt::DropActions possibleActions = DndOperationsToQtDropActions(dnd_data.operations); QDragMoveEvent me(p, possibleActions, QDragManager::self()->dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); if (lastAcceptedAction != Qt::IgnoreAction) { me.setDropAction(lastAcceptedAction); me.accept(); } QApplication::sendEvent(dropWidget, &me); dnd_data.reason = DND_DRAG_MOTION; dnd_data.time = X11->time; if (me.isAccepted()) { lastAcceptedAction = me.dropAction(); dnd_data.status = DND_VALID_DROP_SITE; dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction); } else { dnd_data.status = DND_INVALID_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; } DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); } } break; } case DND_TOP_LEVEL_ENTER: { /* get the size of our drop site for later use */ motifdnd_active = true; sourceWindow = dnd_data.src_window; /* no answer needed, just read source property */ DndReadSourceProperty (event.xclient.display, sourceWindow, dnd_data.property, &src_targets, &num_src_targets); break; } case DND_TOP_LEVEL_LEAVE: { XEvent nextEvent; if (XCheckTypedWindowEvent(X11->display, widget->winId(), ClientMessage, &nextEvent)) { // we just want to check, not eat (should use XPeekIfEvent) XPutBackEvent(X11->display, &nextEvent); if (DndParseClientMessage (&nextEvent.xclient, &dnd_data, &receiver) && dnd_data.reason == DND_DROP_START) { // expecting drop next, keeping DnD alive break; } } // not expecting drop, need to send drag leave events and such here if (dropWidget) { QDragLeaveEvent le; QApplication::sendEvent(dropWidget, &le); } sourceWindow = XNone; dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; motifdnd_active = false; break; } case DND_OPERATION_CHANGED: // ### need to echo break; case DND_DROP_START: { Q_ASSERT(motifdnd_active); Q_ASSERT(sourceWindow == dnd_data.src_window); if (!dropWidget || lastAcceptedAction == Qt::IgnoreAction) { // echo DROP_START dnd_data.reason = DND_DROP_START; dnd_data.status = DND_NO_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); // we have to convert selection in order to indicate failure to the initiator XConvertSelection (X11->display, dnd_data.property, ATOM(XmTRANSFER_FAILURE), dnd_data.property, dnd_data.src_window, dnd_data.time); if (dropWidget) { QDragLeaveEvent e; QApplication::sendEvent(dropWidget, &e); } motifdnd_active = false; sourceWindow = XNone; dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; return; } // store selection and its time Dnd_selection = dnd_data.property; Dnd_selection_time = dnd_data.time; QPoint p(dnd_data.x, dnd_data.y); QDropEvent de(dropWidget->mapFromGlobal(p), Qt::CopyAction, QDragManager::self()->dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); if (lastAcceptedAction != Qt::IgnoreAction) { de.setDropAction(lastAcceptedAction); de.accept(); } QApplication::sendEvent(dropWidget, &de); // reset Dnd_selection = XNone; Dnd_selection_time = 0; // echo DROP_START depending on the result of the dropEvent if (de.isAccepted()) { dnd_data.reason = DND_DROP_START; dnd_data.status = DND_VALID_DROP_SITE; dnd_data.operation = QtDropActionToDndOperation(de.dropAction()); } else { dnd_data.reason = DND_DROP_START; dnd_data.status = DND_NO_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; } DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); sourceWindow = XNone; dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; motifdnd_active = false; break; } default: break; } // end of switch (dnd_data.reason) }
bool QDragManager::eventFilter(QObject *o, QEvent *e) { if (beingCancelled) { return false; } if (!o->isWidgetType()) return false; switch(e->type()) { case QEvent::MouseButtonPress: { } case QEvent::MouseMove: { if (!object) { //#### this should not happen qWarning("QDragManager::eventFilter: No object"); return true; } QDragManager *manager = QDragManager::self(); QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; if (manager->object) possible_actions = manager->dragPrivate()->possible_actions; else possible_actions = Qt::IgnoreAction; QMouseEvent *me = (QMouseEvent *)e; if (me->buttons()) { Qt::DropAction prevAction = global_accepted_action; QWidget *cw = QApplication::widgetAt(me->globalPos()); // map the Coords relative to the window. if (!cw) return true; while (cw && !cw->acceptDrops() && !cw->isWindow()) cw = cw->parentWidget(); bool oldWillDrop = willDrop; if (object->target() != cw) { if (object->target()) { QDragLeaveEvent dle; QApplication::sendEvent(object->target(), &dle); willDrop = false; global_accepted_action = Qt::IgnoreAction; if (oldWillDrop != willDrop) updateCursor(); object->d_func()->target = 0; } if (cw && cw->acceptDrops()) { object->d_func()->target = cw; QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, me->buttons(), me->modifiers()); QApplication::sendEvent(object->target(), &dee); willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction; if (oldWillDrop != willDrop) updateCursor(); } } else if (cw) { QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, me->buttons(), me->modifiers()); if (global_accepted_action != Qt::IgnoreAction) { dme.setDropAction(global_accepted_action); dme.accept(); } QApplication::sendEvent(cw, &dme); willDrop = dme.isAccepted(); global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction; if (oldWillDrop != willDrop) { updatePixmap(); updateCursor(); } } if (global_accepted_action != prevAction) emitActionChanged(global_accepted_action); } return true; // Eat all mouse events } case QEvent::MouseButtonRelease: { qApp->removeEventFilter(this); #ifndef QT_NO_CURSOR if (restoreCursor) { QApplication::restoreOverrideCursor(); willDrop = false; restoreCursor = false; } #endif if (object && object->target()) { QMouseEvent *me = (QMouseEvent *)e; QDragManager *manager = QDragManager::self(); QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData, me->buttons(), me->modifiers()); QApplication::sendEvent(object->target(), &de); if (de.isAccepted()) global_accepted_action = de.dropAction(); else global_accepted_action = Qt::IgnoreAction; if (object) object->deleteLater(); drag_object = object = 0; } eventLoop->exit(); return true; // Eat all mouse events } default: break; } return false; }
static QByteArray qt_xdnd_obtain_data( const char * format ) { QByteArray result; QWidget* w; if ( qt_xdnd_dragsource_xid && qt_xdnd_source_object && (w=QWidget::find( qt_xdnd_dragsource_xid )) && (!w->isDesktop() || w->acceptDrops()) ) { QDragObject * o = qt_xdnd_source_object; if ( o->provides( format ) ) result = o->encodedData(format); return result; } Atom * a = qt_xdnd_str_to_atom( format ); if ( !a || !*a ) return result; if ( !qt_xdnd_target_data ) qt_xdnd_target_data = new QIntDict<QByteArray>( 17 ); if ( qt_xdnd_target_data->find( (int)*a ) ) { result = *(qt_xdnd_target_data->find( (int)*a )); } else { if ( XGetSelectionOwner( qt_xdisplay(), qt_xdnd_selection ) == None ) return result; // should never happen? QWidget* tw = qt_xdnd_current_widget; if ( !tw || qt_xdnd_current_widget->isDesktop() ) { tw = new QWidget; } XConvertSelection( qt_xdisplay(), qt_xdnd_selection, *a, qt_xdnd_selection, tw->winId(), CurrentTime ); XFlush( qt_xdisplay() ); XEvent xevent; bool got=qt_xclb_wait_for_event( qt_xdisplay(), tw->winId(), SelectionNotify, &xevent, 5000); if ( got ) { Atom type; if ( qt_xclb_read_property( qt_xdisplay(), tw->winId(), qt_xdnd_selection, TRUE, &result, 0, &type, 0, FALSE ) ) { if ( type == qt_incr_atom ) { int nbytes = result.size() >= 4 ? *((int*)result.data()) : 0; result = qt_xclb_read_incremental_property( qt_xdisplay(), tw->winId(), qt_xdnd_selection, nbytes, FALSE ); } else if ( type != *a ) { // (includes None) debug( "Qt clipboard: unknown atom %ld", type); } if ( type != None ) qt_xdnd_target_data->insert( (int)((long)a), new QByteArray(result) ); } } if ( !qt_xdnd_current_widget || qt_xdnd_current_widget->isDesktop() ) { delete tw; } } return result; }
void QDragManager::move( const QPoint & globalPos ) { if ( qt_xdnd_source_sameanswer.contains( globalPos ) && qt_xdnd_source_sameanswer.isValid() && !qt_xdnd_source_sameanswer.isEmpty() ) { // ### probably unnecessary return; } if ( qt_xdnd_deco ) { qt_xdnd_deco->move(globalPos-qt_xdnd_source_object->pixmapHotSpot()); qt_xdnd_deco->raise(); } Window target = 0; int lx = 0, ly = 0; if ( !XTranslateCoordinates( qt_xdisplay(), qt_xrootwin(), qt_xrootwin(), globalPos.x(), globalPos.y(), &lx, &ly, &target) ) { // somehow got to a different screen? ignore for now return; } if ( target == qt_xrootwin() ) { // Ok. } else if ( target ) { target = qt_x11_findClientWindow( target, qt_wm_state, TRUE ); if ( qt_xdnd_deco && !target || target == qt_xdnd_deco->winId() ) { target = findRealWindow(globalPos,qt_xrootwin(),6); } } if ( target == 0 ) target = qt_xrootwin(); QWidget * w = QWidget::find( (WId)target ); int emask = NoEventMask; if ( w && w->isDesktop() && !w->acceptDrops() ) { emask = EnterWindowMask; w = 0; } if ( target != qt_xdnd_current_target ) { if ( qt_xdnd_current_target ) qt_xdnd_send_leave(); Atom * type[3]={0,0,0}; const char* fmt; int nfmt=0; for (nfmt=0; nfmt<3 && (fmt=object->format(nfmt)); nfmt++) type[nfmt] = qt_xdnd_str_to_atom( fmt ); XClientMessageEvent enter; enter.type = ClientMessage; enter.window = target; enter.format = 32; enter.message_type = qt_xdnd_enter; enter.data.l[0] = object->source()->winId(); enter.data.l[1] = 1 << 24; // flags enter.data.l[2] = type[0] ? *type[0] : 0; // ### enter.data.l[3] = type[1] ? *type[1] : 0; enter.data.l[4] = type[2] ? *type[2] : 0; qt_xdnd_current_target = target; // provisionally set the rectangle to 5x5 pixels... qt_xdnd_source_sameanswer = QRect( globalPos.x() - 2, globalPos.y() -2 , 5, 5 ); if ( w ) { qt_handle_xdnd_enter( w, (const XEvent *)&enter ); } else { XSendEvent( qt_xdisplay(), target, FALSE, emask, (XEvent*)&enter ); } } XClientMessageEvent move; move.type = ClientMessage; move.window = target; move.format = 32; move.message_type = qt_xdnd_position; move.window = target; move.data.l[0] = object->source()->winId(); move.data.l[1] = 0; // flags move.data.l[2] = (globalPos.x() << 16) + globalPos.y(); move.data.l[3] = qt_x_clipboardtime; move.data.l[4] = qt_xdnd_action_copy; if ( w ) qt_handle_xdnd_position( w, (const XEvent *)&move ); else XSendEvent( qt_xdisplay(), target, FALSE, emask, (XEvent*)&move ); }
void qt_handle_xdnd_position( QWidget *w, const XEvent * xe ) { 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 ); if ( !c || !c->acceptDrops() && c->isDesktop() ) 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; } XClientMessageEvent response; response.type = ClientMessage; response.window = qt_xdnd_dragsource_xid; response.format = 32; response.message_type = qt_xdnd_status; response.data.l[0] = w->winId(); 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; // just null QRect answerRect( c->mapToGlobal( p ), QSize( 1,1 ) ); QDragMoveEvent me( p ); if ( qt_xdnd_current_widget != c ) { qt_xdnd_target_answerwas = FALSE; if ( qt_xdnd_current_widget ) { QDragLeaveEvent e; QApplication::sendEvent( qt_xdnd_current_widget, &e ); } if ( c->acceptDrops() ) { QDragEnterEvent de( p ); QApplication::sendEvent( c, &de ); if ( de.isAccepted() ) me.accept( de.answerRect() ); else me.ignore( de.answerRect() ); } } else { if ( qt_xdnd_target_answerwas ) me.accept(); } if ( !c->acceptDrops() ) { qt_xdnd_current_widget = 0; answerRect = QRect( p, QSize( 1, 1 ) ); } else if ( l[4] != qt_xdnd_action_copy ) { response.data.l[0] = 0; answerRect = QRect( p, QSize( 1, 1 ) ); } else { qt_xdnd_current_widget = c; qt_xdnd_current_position = p; qt_xdnd_target_current_time = l[3]; // will be 0 for xdnd1 QApplication::sendEvent( c, &me ); qt_xdnd_target_answerwas = me.isAccepted(); if ( me.isAccepted() ) response.data.l[1] = 1; // yess!!!! else response.data.l[0] = 0; answerRect = me.answerRect().intersect( c->rect() ); } answerRect = QRect( c->mapToGlobal( answerRect.topLeft() ), answerRect.size() ); if ( answerRect.width() < 0 ) answerRect.setWidth( 0 ); if ( answerRect.height() < 0 ) answerRect.setHeight( 0 ); 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 ); response.data.l[2] = (answerRect.x() << 16) + answerRect.y(); response.data.l[3] = (answerRect.width() << 16) + answerRect.height(); response.data.l[4] = qt_xdnd_action_copy; QWidget * source = QWidget::find( qt_xdnd_dragsource_xid ); int emask = NoEventMask; if ( source && source->isDesktop() && !source->acceptDrops() ) { emask = EnterWindowMask; source = 0; } if ( source ) qt_handle_xdnd_status( source, (const XEvent *)&response ); else XSendEvent( qt_xdisplay(), qt_xdnd_dragsource_xid, FALSE, emask, (XEvent*)&response ); }
void qt_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->isDesktop() ) { return; } if ( l[0] != qt_xdnd_dragsource_xid ) { //qDebug( "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 = qt_x_user_time = l[3]; } XClientMessageEvent response; response.type = ClientMessage; response.window = qt_xdnd_dragsource_xid; response.format = 32; response.message_type = qt_xdnd_status; response.data.l[0] = w->winId(); 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->isTopLevel() ) { p = c->mapToParent( p ); c = c->parentWidget(); } QRect answerRect( c->mapToGlobal( p ), QSize( 1,1 ) ); QDragMoveEvent me( p ); QDropEvent::Action accepted_action = xdndaction_to_qtaction(l[4]); me.setAction(accepted_action); if ( c != qt_xdnd_current_widget ) { qt_xdnd_target_answerwas = FALSE; if ( qt_xdnd_current_widget ) { QDragLeaveEvent e; QApplication::sendEvent( qt_xdnd_current_widget, &e ); } if ( c->acceptDrops() ) { qt_xdnd_current_widget = c; qt_xdnd_current_position = p; QDragEnterEvent de( p ); de.setAction(accepted_action); QApplication::sendEvent( c, &de ); if ( de.isAccepted() ) { me.accept( de.answerRect() ); if ( !de.isActionAccepted() ) // only as a copy (move if we del) accepted_action = QDropEvent::Copy; else me.acceptAction(TRUE); } else { me.ignore( de.answerRect() ); } } } else { if ( qt_xdnd_target_answerwas ) { me.accept(); me.acceptAction(global_requested_action == global_accepted_action); } } if ( !c->acceptDrops() ) { qt_xdnd_current_widget = 0; answerRect = QRect( p, QSize( 1, 1 ) ); } else if ( xdndaction_to_qtaction(l[4]) < QDropEvent::Private ) { qt_xdnd_current_widget = c; qt_xdnd_current_position = p; QApplication::sendEvent( c, &me ); qt_xdnd_target_answerwas = me.isAccepted(); if ( me.isAccepted() ) { response.data.l[1] = 1; // yes if ( !me.isActionAccepted() ) // only as a copy (move if we del) accepted_action = QDropEvent::Copy; } else { response.data.l[0] = 0; } answerRect = me.answerRect().intersect( c->rect() ); } else { response.data.l[0] = 0; answerRect = QRect( p, QSize( 1, 1 ) ); } 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); global_accepted_action = accepted_action; } // reset qt_xdnd_target_current_time = CurrentTime; QWidget * source = QWidget::find( qt_xdnd_dragsource_xid ); if ( source && source->isDesktop() && !source->acceptDrops() ) source = 0; if ( source ) qt_handle_xdnd_status( source, (const XEvent *)&response, passive ); else XSendEvent( QPaintDevice::x11AppDisplay(), qt_xdnd_dragsource_xid, False, NoEventMask, (XEvent*)&response ); }