Пример #1
0
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());
}
Пример #2
0
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;
}
Пример #3
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;
    }
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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 );
}
Пример #10
0
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 );
}
Пример #11
0
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 );
}