qt-bugs@ issue : 16115 applied: no author: Lubos Lunak See http://lists.kde.org/?t=104388858900001&r=1&w=2 --- work/qt-x11-free-3.3.8/src/kernel/qdnd_x11.cpp.sav 2003-02-05 16:09:45.000000000 +0100 +++ work/qt-x11-free-3.3.8/src/kernel/qdnd_x11.cpp 2003-02-07 16:14:49.000000000 +0100 @@ -49,13 +49,15 @@ #include "qdragobject.h" #include "qobjectlist.h" #include "qcursor.h" +#include "qbitmap.h" +#include "qpainter.h" #include "qt_x11_p.h" // conflict resolution -// unused, may be used again later: const int XKeyPress = KeyPress; -// unused, may be used again later: const int XKeyRelease = KeyRelease; +const int XKeyPress = KeyPress; +const int XKeyRelease = KeyRelease; #undef KeyPress #undef KeyRelease @@ -249,20 +251,47 @@ class QShapedPixmapWidget : public QWidg public: QShapedPixmapWidget(int screen = -1) : QWidget(QApplication::desktop()->screen( screen ), - 0, WStyle_Customize | WStyle_Tool | WStyle_NoBorder | WX11BypassWM ) + 0, WStyle_Customize | WStyle_Tool | WStyle_NoBorder | WX11BypassWM ), oldpmser( 0 ), oldbmser( 0 ) { } - void setPixmap(QPixmap pm) + void setPixmap(QPixmap pm, QPoint hot) { - if ( pm.mask() ) { + int bmser = pm.mask() ? pm.mask()->serialNumber() : 0; + if( oldpmser == pm.serialNumber() && oldbmser == bmser + && oldhot == hot ) + return; + oldpmser = pm.serialNumber(); + oldbmser = bmser; + oldhot = hot; + bool hotspot_in = !(hot.x() < 0 || hot.y() < 0 || hot.x() >= pm.width() || hot.y() >= pm.height()); +// if the pixmap has hotspot in its area, make a "hole" in it at that position +// this will allow XTranslateCoordinates() to find directly the window below the cursor instead +// of finding this pixmap, and therefore there won't be needed any (slow) search for the window +// using findRealWindow() + if( hotspot_in ) { + QBitmap mask = pm.mask() ? *pm.mask() : QBitmap( pm.width(), pm.height()); + if( !pm.mask()) + mask.fill( Qt::color1 ); + QPainter p( &mask ); + p.setPen( Qt::color0 ); + p.drawPoint( hot.x(), hot.y()); + p.end(); + pm.setMask( mask ); + setMask( mask ); + } else if ( pm.mask() ) { setMask( *pm.mask() ); } else { clearMask(); } resize(pm.width(),pm.height()); setErasePixmap(pm); + erase(); } +private: + int oldpmser; + int oldbmser; + QPoint oldhot; }; QShapedPixmapWidget * qt_xdnd_deco = 0; @@ -859,6 +888,45 @@ void QDragManager::timerEvent( QTimerEve move( QCursor::pos() ); } +static bool qt_xdnd_was_move = false; +static bool qt_xdnd_found = false; +// check whole incoming X queue for move events +// checking whole queue is done by always returning False in the predicate +// if there's another move event in the queue, and there's not a mouse button +// or keyboard or ClientMessage event before it, the current move event +// may be safely discarded +// this helps avoiding being overloaded by being flooded from many events +// from the XServer +static +Bool qt_xdnd_predicate( Display*, XEvent* ev, XPointer ) +{ + if( qt_xdnd_found ) + return False; + if( ev->type == MotionNotify ) + { + qt_xdnd_was_move = true; + qt_xdnd_found = true; + } + if( ev->type == ButtonPress || ev->type == ButtonRelease + || ev->type == XKeyPress || ev->type == XKeyRelease + || ev->type == ClientMessage ) + { + qt_xdnd_was_move = false; + qt_xdnd_found = true; + } + return False; +} + +static +bool qt_xdnd_another_movement() +{ + qt_xdnd_was_move = false; + qt_xdnd_found = false; + XEvent dummy; + XCheckIfEvent( qt_xdisplay(), &dummy, qt_xdnd_predicate, NULL ); + return qt_xdnd_was_move; +} + bool QDragManager::eventFilter( QObject * o, QEvent * e) { if ( beingCancelled ) { @@ -881,8 +949,10 @@ bool QDragManager::eventFilter( QObject if ( e->type() == QEvent::MouseMove ) { QMouseEvent* me = (QMouseEvent *)e; - updateMode(me->stateAfter()); - move( me->globalPos() ); + if( !qt_xdnd_another_movement()) { + updateMode(me->stateAfter()); + move( me->globalPos() ); + } return TRUE; } else if ( e->type() == QEvent::MouseButtonRelease ) { tqApp->removeEventFilter( this ); @@ -1106,7 +1176,7 @@ void QDragManager::move( const QPoint & delete qt_xdnd_deco; qt_xdnd_deco = new QShapedPixmapWidget( screen ); } - updatePixmap(); + updatePixmap( globalPos ); if ( qt_xdnd_source_sameanswer.contains( globalPos ) && qt_xdnd_source_sameanswer.isValid() ) { @@ -1679,7 +1749,7 @@ bool QDragManager::drag( QDragObject * o // qt_xdnd_source_object persists until we get an xdnd_finish message } -void QDragManager::updatePixmap() +void QDragManager::updatePixmap( const QPoint& cursorPos ) { if ( qt_xdnd_deco ) { QPixmap pm; @@ -1694,9 +1764,8 @@ void QDragManager::updatePixmap() 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); + qt_xdnd_deco->setPixmap(pm, pm_hot); + qt_xdnd_deco->move(cursorPos-pm_hot); //if ( willDrop ) { qt_xdnd_deco->show(); //} else { @@ -1705,4 +1774,9 @@ void QDragManager::updatePixmap() } } +void QDragManager::updatePixmap() +{ + updatePixmap( QCursor::pos()); +} + #endif // QT_NO_DRAGANDDROP --- work/qt-x11-free-3.3.8/src/kernel/qdragobject.h.sav 2002-11-01 19:25:07.000000000 +0100 +++ work/qt-x11-free-3.3.8/src/kernel/qdragobject.h 2001-01-01 01:01:00.000000000 +0100 @@ -245,6 +245,7 @@ private: void move( const QPoint & ); void drop(); void updatePixmap(); + void updatePixmap( const QPoint& cursorPos ); private: QDragObject * object;