Source Code (Use browser search to find items of interest.)

Class Index

qt'QDragManager (./qt-2.1.0/src/kernel/qdragobject.h:176)

class Q_EXPORT QDragManager: public QObject {
    Q_OBJECT

private:
    QDragManager();
    ~QDragManager();
    // only friend classes can use QDragManager.
    friend class QDragObject;
    friend class QDragMoveEvent;
    friend class QDropEvent;

    bool eventFilter( QObject *, QEvent * );
    void timerEvent( QTimerEvent* );

    bool drag( QDragObject *, QDragObject::DragMode );

    void cancel( bool deleteSource = TRUE );
    void move( const QPoint & );
    void drop();
    void updatePixmap();

private:
    QDragObject * object;
    void updateMode( ButtonState newstate );
    void updateCursor();

    QWidget * dragSource;
    QWidget * dropWidget;
    bool beingCancelled;
    bool restoreCursor;
    bool willDrop;

    QPixmap *pm_cursor;
    int n_cursor;
};


qt'QDragManager::timerEvent() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:828)

void QDragManager::timerEvent( QTimerEvent* e )
{
    if ( e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull() )
	move( QCursor::pos() );
}


qt'QDragManager::eventFilter() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:834)

bool QDragManager::eventFilter( QObject * o, QEvent * e)
{
    if ( beingCancelled ) {
	if ( e->type() == QEvent::KeyRelease &&
	     ((QKeyEvent*)e)->key() == Key_Escape ) {
	    qApp->removeEventFilter( this );
	    object = 0;
	    dragSource = 0;
	    beingCancelled = FALSE;
	    qApp->exit_loop();
	    return TRUE; // block the key release
	}
	return FALSE;
    }

    ASSERT( object != 0 );

    if ( !o->isWidgetType() )
	return FALSE;

    QWidget* w = (QWidget*)o;

    if ( e->type() == QEvent::MouseMove ) {
	QMouseEvent* me = (QMouseEvent *)e;
	updateMode(me->stateAfter());
	move( w->mapToGlobal( me->pos() ) );
	return TRUE;
    } else if ( e->type() == QEvent::MouseButtonRelease ) {
	qApp->removeEventFilter( this );
	if ( willDrop )
	    drop();
	else
	    cancel();
	object = 0;
	dragSource = 0;
	beingCancelled = FALSE;
	qApp->exit_loop();
	return TRUE;
    } else if ( e->type() == QEvent::DragResponse ) {
	if ( ((QDragResponseEvent *)e)->dragAccepted() ) {
	    if ( !willDrop ) {
		willDrop = TRUE;
	    }
	} else {
	    if ( willDrop ) {
		willDrop = FALSE;
	    }
	}
	updateCursor();
	return TRUE;
    }

    if ( e->type() == QEvent::KeyPress
      || e->type() == QEvent::KeyRelease )
    {
	QKeyEvent *ke = ((QKeyEvent*)e);
	if ( ke->key() == Key_Escape && e->type() == QEvent::KeyPress ) {
	    cancel();
	    qApp->removeEventFilter( this );
	    object = 0;
	    dragSource = 0;
	    beingCancelled = FALSE;
	    qApp->exit_loop();
	} else {
	    updateMode(ke->stateAfter());
	    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::Accel:
      case QEvent::AccelAvailable:
	return TRUE;
      default:
	return FALSE;
    }
}



qt'QDragManager::updateMode() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:926)

void QDragManager::updateMode( ButtonState newstate )
{
    if ( newstate == oldstate )
	return;
    const int both = ShiftButton|ControlButton;
    if ( (newstate & both) == both ) {
	global_requested_action = QDropEvent::Link;
    } else {
	bool local = qt_xdnd_source_object != 0;
	if ( drag_mode == QDragObject::DragMove )
	    global_requested_action = QDropEvent::Move;
	else if ( drag_mode == QDragObject::DragCopy )
	    global_requested_action = QDropEvent::Copy;
	else {
	    if ( drag_mode == QDragObject::DragDefault && local )
		global_requested_action = QDropEvent::Move;
	    else
		global_requested_action = QDropEvent::Copy;
	    if ( newstate & ShiftButton )
		global_requested_action = QDropEvent::Move;
	    else if ( newstate & ControlButton )
		global_requested_action = QDropEvent::Copy;
	}
    }
    oldstate = newstate;
}



qt'QDragManager::updateCursor() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:954)

void QDragManager::updateCursor()
{
    if ( !noDropCursor ) {
	noDropCursor = new QCursor( ForbiddenCursor );
	if ( !pm_cursor[0].isNull() )
	    moveCursor = new QCursor(pm_cursor[0], 0,0);
	if ( !pm_cursor[1].isNull() )
	    copyCursor = new QCursor(pm_cursor[1], 0,0);
	if ( !pm_cursor[2].isNull() )
	    linkCursor = new QCursor(pm_cursor[2], 0,0);
    }

    QCursor *c;
    if ( willDrop ) {
	if ( global_accepted_action == QDropEvent::Copy ) {
	    if ( global_requested_action == QDropEvent::Move )
		c = moveCursor; // (source can delete)
	    else
		c = copyCursor;
	} else if ( global_accepted_action == QDropEvent::Link ) {
	    c = linkCursor;
	} else {
	    c = moveCursor;
	}
	if ( qt_xdnd_deco )
	    qt_xdnd_deco->show();
    } else {
	c = noDropCursor;
	if ( qt_xdnd_deco )
	    qt_xdnd_deco->hide();
    }
    if ( c )
	qApp->setOverrideCursor( *c, TRUE );
}



qt'QDragManager::cancel() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:990)

void QDragManager::cancel( bool deleteSource )
{
    if ( object ) {
	beingCancelled = TRUE;
	object = 0;
    }

    if ( qt_xdnd_current_target ) {
	qt_xdnd_send_leave();
    }

    if ( restoreCursor ) {
	QApplication::restoreOverrideCursor();
	restoreCursor = FALSE;
    }

    if ( deleteSource )
	delete qt_xdnd_source_object;
    qt_xdnd_source_object = 0;
    delete qt_xdnd_deco;
    qt_xdnd_deco = 0;
}

static

qt'QDragManager::move() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:1063)

void QDragManager::move( const QPoint & globalPos )
{
    updatePixmap();

    if ( qt_xdnd_source_sameanswer.contains( globalPos ) &&
	 qt_xdnd_source_sameanswer.isValid() ) {
	return;
    }

    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 ) {
	//me
	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);
 	}
    }

    int emask = NoEventMask;
    QWidget* w;
    if ( target ) {
	w = QWidget::find( (WId)target );
	if ( w && w->isDesktop() && !w->acceptDrops() ) {
	    emask = EnterWindowMask;
	    w = 0;
	}
    } else {
	w = 0;
	target = qt_xrootwin();
    }

    WId proxy_target = target;
    int target_version = 1;

    {
	Atom   type = None;
	int f;
	unsigned long n, a;
	WId *proxy_id;
	qt_ignore_badwindow();
	XGetWindowProperty( qt_xdisplay(), target, qt_xdnd_proxy, 0,
	    1, False, XA_WINDOW, &type, &f,&n,&a,(uchar**)&proxy_id );
	if ( qt_badwindow() ) {
	    proxy_target = target = 0;
	} else if ( type == XA_WINDOW && proxy_id ) {
	    proxy_target = *proxy_id;
	    XFree(proxy_id);
	    proxy_id = 0;
	    qt_ignore_badwindow();
	    XGetWindowProperty( qt_xdisplay(), proxy_target, qt_xdnd_proxy, 0,
		1, False, XA_WINDOW, &type, &f,&n,&a,(uchar**)&proxy_id );
	    if ( qt_badwindow() || !type || !proxy_id || *proxy_id != proxy_target ) {
		// Bogus
		proxy_target = 0;
		target = 0;
	    }
	    if ( proxy_id )
		XFree(proxy_id);
	}
	if ( proxy_target ) {
	    int *tv;
	    qt_ignore_badwindow();
	    XGetWindowProperty( qt_xdisplay(), proxy_target, qt_xdnd_aware, 0,
		1, False, AnyPropertyType, &type, &f,&n,&a,(uchar**)&tv );
	    target_version = QMIN(qt_xdnd_version,tv ? *tv : 1);
	    if ( tv ) XFree(tv);
	    if ( !qt_badwindow() && type )
		emask = EnterWindowMask;
	    else
		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 ) {
	    QArray<Atom> type;
	    int flags = target_version << 24;
	    const char* fmt;
	    int nfmt=0;
	    for (nfmt=0; (fmt=object->format(nfmt)); nfmt++) {
		type.resize(nfmt+1);
		type[nfmt] = *qt_xdnd_str_to_atom( fmt );
	    }
	    if ( nfmt >= 3 ) {
		XChangeProperty( qt_xdisplay(),
		    object->source()->winId(), qt_xdnd_type_list,
		    XA_ATOM, 32, PropModeReplace,
		    (unsigned char *)type.data(),
		    type.size() );
		flags |= 0x0001;
	    }
	    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] = flags;
	    enter.data.l[2] = type.size()>0 ? type[0] : 0;
	    enter.data.l[3] = type.size()>1 ? type[1] : 0;
	    enter.data.l[4] = type.size()>2 ? type[2] : 0;
	    // 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, FALSE );
	    } else if ( target ) {
		XSendEvent( qt_xdisplay(), proxy_target, FALSE, emask,
			    (XEvent*)&enter );
	    }
	}
    }

    if ( target ) {
	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_time;
	move.data.l[4] = qtaction_to_xdndaction( global_requested_action );

	if ( w )
	    qt_handle_xdnd_position( w, (const XEvent *)&move, FALSE );
	else
	    XSendEvent( qt_xdisplay(), proxy_target, FALSE, emask,
			(XEvent*)&move );
    } else {
	if ( willDrop ) {
	    willDrop = FALSE;
	    updateCursor();
	}
    }
}



qt'QDragManager::drop() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:1219)

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_time;
    drop.data.l[4] = 0;

    QWidget * w = QWidget::find( qt_xdnd_current_proxy_target );

    int emask = NoEventMask;
    if ( w && w->isDesktop() && !w->acceptDrops() ) {
	emask = EnterWindowMask;
	w = 0;
    }

    if ( w )
	qt_handle_xdnd_drop( w, (const XEvent *)&drop, FALSE );
    else
	XSendEvent( qt_xdisplay(), qt_xdnd_current_proxy_target, FALSE, emask,
		    (XEvent*)&drop );

    if ( restoreCursor ) {
	QApplication::restoreOverrideCursor();
	restoreCursor = FALSE;
    }
}




qt'QDragManager::drag() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:1531)

bool QDragManager::drag( QDragObject * o, QDragObject::DragMode mode )
{
    if ( object == o )
	return FALSE;

    if ( object ) {
	cancel();
	qApp->removeEventFilter( this );
	beingCancelled = FALSE;
    }

    qt_xdnd_source_object = o;
    qt_xdnd_deco = new QShapedPixmapWidget();

    willDrop = FALSE;

    object = o;
    updatePixmap();

    dragSource = (QWidget *)(object->parent());

    qApp->installEventFilter( this );
    qt_xdnd_source_current_time = qt_x_time;
    XSetSelectionOwner( qt_xdisplay(), qt_xdnd_selection,
			dragSource->topLevelWidget()->winId(),
			qt_xdnd_source_current_time );
    oldstate = ButtonState(-1); // #### Should use state that caused the drag
    drag_mode = mode;
    global_accepted_action = QDropEvent::Copy; // #####
    updateMode(ButtonState(0));
    qt_xdnd_source_sameanswer = QRect();
    move(QCursor::pos());
    heartbeat = startTimer(200);

    qApp->setOverrideCursor( arrowCursor );
    restoreCursor = TRUE;
    updateCursor();

    qApp->enter_loop(); // Do the DND.

    qApp->restoreOverrideCursor();

    delete qt_xdnd_deco;
    qt_xdnd_deco = 0;
    killTimer(heartbeat);
    heartbeat = 0;

    return global_accepted_action == QDropEvent::Copy
	    && global_requested_action == QDropEvent::Move; // source del?

    // qt_xdnd_source_object persists for a while...
}


qt'QDragManager::updatePixmap() (./qt-2.1.0/src/kernel/qdnd_x11.cpp:1584)

void QDragManager::updatePixmap()
{
    if ( qt_xdnd_deco ) {
	QPixmap pm;
	QPoint pm_hot(default_pm_hotx,default_pm_hoty);
	if ( object ) {
	    pm = object->pixmap();
	    if ( !pm.isNull() )
		pm_hot = object->pixmapHotSpot();
	}
	if ( pm.isNull() ) {
	    if ( !defaultPm )
		defaultPm = new QPixmap(default_pm);
	    pm = *defaultPm;
	}
	qt_xdnd_deco->setPixmap(pm);
	qt_xdnd_deco->move(QCursor::pos()-pm_hot);
	//qt_xdnd_deco->repaint(FALSE);
	if ( willDrop ) {
	    qt_xdnd_deco->show();
	} else {
	    qt_xdnd_deco->hide();
	}
    }
}

qt'QDragManager::QDragManager() (./qt-2.1.0/src/kernel/qdragobject.cpp:237)

QDragManager::QDragManager()
    : QObject( qApp, "global drag manager" )
{
    n_cursor = 3;
    pm_cursor = new QPixmap[n_cursor];
    pm_cursor[0] = QPixmap((const char **)move_xpm);
    pm_cursor[1] = QPixmap((const char **)copy_xpm);
    pm_cursor[2] = QPixmap((const char **)link_xpm);
    object = 0;
    dragSource = 0;
    dropWidget = 0;
    if ( !manager )
	manager = this;
    beingCancelled = FALSE;
    restoreCursor = FALSE;
    willDrop = FALSE;
}



qt'QDragManager::~QDragManager() (./qt-2.1.0/src/kernel/qdragobject.cpp:256)

QDragManager::~QDragManager()
{
    if ( restoreCursor )
	QApplication::restoreOverrideCursor();
    manager = 0;
    delete [] pm_cursor;
}




/*!  Constructs a drag object which is a child of \a dragSource and
  named \a name.

  Note that the drag object will be deleted when \a dragSource is.
*/