Drag and drop optimization

Lubos Lunak kde-optimize@mail.kde.org
Wed, 5 Feb 2003 15:56:37 +0100


--Boundary-00=_lYSQ+xqtdbvxJpF
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Wednesday 05 of February 2003 15:11, Wilco Greven wrote:
> On Wednesday 05 February 2003 13:27, Lubos Lunak wrote:
> > On Tuesday 04 of February 2003 22:36, Wilco Greven wrote:
> > > On Tuesday 04 February 2003 13:08, Lubos Lunak wrote:
> >
> > [snip]
> >
> > > I tried out your patch. At first it didn't seem to be any better than
> > > the old situation. I could be that the first part (the hole patch),
> > > doesn't work as expected. Maybe Enter/Leave events are to blame in this
> > > case.
> >
> >  I actually left some of the debug comments in the patch. The 'AVOIDING'
> > message lists number of avoided calls to QDragManager::move(). The 'TAR:'
> > message lists results of finding the window under the cursor, and with
> > the hole in the pixmap, the third number should never be the same as one
> > of the first two (and it's not here). Can you check that?
>
> The first is sometimes the same as the third:
>
> TAR: 0x4600001 0x4600001 0x46003e3
> TAR: 0x46003e3 0x0 0x46003e3
> AVOIDING 310
> AVOIDING 311
> AVOIDING 312
> TAR: 0x4600001 0x4600001 0x46003e3
> AVOIDING 313
> TAR: 0x46003e3 0x0 0x46003e3
> AVOIDING 314
> AVOIDING 315
> TAR: 0x4600001 0x4600001 0x46003e3
>
> Can XMoveResizeWindow somehow not have an immediate effect in certain
> cases?

 Please try the attached patches.

-- 
Lubos Lunak
KDE developer
---------------------------------------------------------------------
SuSE CR, s.r.o.  e-mail: l.lunak@suse.cz , l.lunak@kde.org
Drahobejlova 27  tel: +420 2 9654 2373
190 00 Praha 9   fax: +420 2 9654 2374
Czech Republic   http://www.suse.cz/

--Boundary-00=_lYSQ+xqtdbvxJpF
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="qdnd_x11.cpp.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="qdnd_x11.cpp.patch"

--- qdnd_x11.cpp.sav	2003-01-02 12:22:59.000000000 +0100
+++ qdnd_x11.cpp	2003-02-05 15:54:29.000000000 +0100
@@ -54,8 +54,8 @@
 
 // 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
 
@@ -245,23 +245,40 @@ static const char* const default_pm[] = 
 "X X X X X X X"
 };
 
+#include <qbitmap.h>
+#include <qpainter.h>
+
 class QShapedPixmapWidget : public QWidget {
     QPixmap pixmap;
 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)
     {
-	pixmap = pm;
-	if ( pixmap.mask() ) {
-	    setMask( *pixmap.mask() );
-	} else {
-	    clearMask();
+	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());
+	QBitmap mask = pixmap.mask() ? *pixmap.mask() : QBitmap( pm.width(), pm.height());
+	if( hotspot_in ) {
+	    if( !pixmap.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 );
+	pixmap = pm;
 	resize(pm.width(),pm.height());
     }
 
@@ -269,6 +286,9 @@ public:
     {
 	bitBlt(this,0,0,&pixmap);
     }
+    int oldpmser;
+    int oldbmser;
+    QPoint oldhot;
 };
 
 QShapedPixmapWidget * qt_xdnd_deco = 0;
@@ -865,6 +885,38 @@ void QDragManager::timerEvent( QTimerEve
 	move( QCursor::pos() );
 }
 
+static bool was_move = false;
+static bool found = false;
+static
+Bool predicate( Display*, XEvent* ev, XPointer )
+{
+    if( found )
+	return False;
+    if( ev->type == MotionNotify )
+    {
+	was_move = true;
+	found = true;
+    }
+    if( ev->type == ButtonPress || ev->type == ButtonRelease
+	|| ev->type == XKeyPress || ev->type == XKeyRelease
+	|| ev->type == ClientMessage )
+    {
+	was_move = false;
+	found = true;
+    }
+    return False;
+}
+
+static
+bool another_movement()
+{
+    was_move = false;
+    found = false;
+    XEvent dummy;
+    XCheckIfEvent( qt_xdisplay(), &dummy, predicate, NULL );
+    return was_move;
+}
+
 bool QDragManager::eventFilter( QObject * o, QEvent * e)
 {
     if ( beingCancelled ) {
@@ -887,8 +939,14 @@ bool QDragManager::eventFilter( QObject 
 
     if ( e->type() == QEvent::MouseMove ) {
 	QMouseEvent* me = (QMouseEvent *)e;
-	updateMode(me->stateAfter());
-	move( me->globalPos() );
+	if( !another_movement()) {
+	    updateMode(me->stateAfter());
+	    move( me->globalPos() );
+	}
+	else {
+	    static int i = 0;
+	    qDebug( "AVOIDING %d", ++i );
+	}
 	return TRUE;
     } else if ( e->type() == QEvent::MouseButtonRelease ) {
 	qApp->removeEventFilter( this );
@@ -1112,7 +1170,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() ) {
@@ -1136,6 +1194,7 @@ void QDragManager::move( const QPoint & 
 	Window targetW = qt_x11_findClientWindow( target, qt_wm_state, TRUE );
 	if (targetW)
 	    target = targetW;
+	qDebug( "TAR: 0x%lx 0x%lx 0x%lx", target, targetW, qt_xdnd_deco->winId());
 	if ( qt_xdnd_deco && (!target || target == qt_xdnd_deco->winId()) ) {
 	    target = findRealWindow(globalPos,rootwin,6);
 	}
@@ -1685,7 +1744,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;
@@ -1700,8 +1759,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->setPixmap(pm, pm_hot);
+	qt_xdnd_deco->move(cursorPos-pm_hot);
 	qt_xdnd_deco->repaint(FALSE);
 	    //if ( willDrop ) {
 	    qt_xdnd_deco->show();
@@ -1711,4 +1770,9 @@ void QDragManager::updatePixmap()
     }
 }
 
+void QDragManager::updatePixmap()
+{
+    updatePixmap( QCursor::pos());
+}
+
 #endif // QT_NO_DRAGANDDROP

--Boundary-00=_lYSQ+xqtdbvxJpF
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="qdragobject.h.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="qdragobject.h.patch"

--- qdragobject.h.sav	2002-11-01 19:25:07.000000000 +0100
+++ 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;

--Boundary-00=_lYSQ+xqtdbvxJpF--