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