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 ); }