stable/x11-libs/qt/files/0001-dnd_optimization.patch

188 lines
5.5 KiB
Diff
Raw Normal View History

2010-07-07 08:23:58 +02:00
qt-bugs@ issue : 16115
applied: no
author: Lubos Lunak <l.lunak@kde.org>
See http://lists.kde.org/?t=104388858900001&r=1&w=2
--- src/kernel/qdnd_x11.cpp.sav 2003-02-05 16:09:45.000000000 +0100
+++ 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 ) {
qApp->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
--- src/kernel/qdragobject.h.sav 2002-11-01 19:25:07.000000000 +0100
+++ 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;