--Boundary-00=_XoHO+ll9kIwDSNL Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hello, The accompanying patch speeds up the part of Qt's dnd code which looks up the window under the cursor (*). The critical part of this code is the function findClientWindow. One call takes about 100 ms. Most of this time of this is spend in XGetWindowAttributes. The replacement avoids uses the NETWM client list stacking looks at the windows starting from the top of the client stack. Here are some testresults comparing the two methods: KCounterProf:findRealWindow took approx 117.79 ms findRealWindow was called 584 times Window returned: 22001b3 KCounterProf:findRealWindowNETWM took approx 3.32 ms Window returned: 22001b3 KCounterProf:findRealWindow took approx 113.16 ms findRealWindow was called 582 times Window returned: 1a00002 KCounterProf:findRealWindowNETWM took approx 2.17 ms Window returned: 1a00002 KCounterProf:findRealWindow took approx 114.25 ms findRealWindow was called 583 times Window returned: 2c02673 KCounterProf:findRealWindowNETWM took approx 2.70 ms Window returned: 2c02673 So far the biggest problem I can see is that the code relies on a NETWM compliant window manager. For the rest it's hard to say because I don't know X11 that well. -- Greetings, Wilco (*) You can't use XTranslateCoordinates for this when the drag icon is under the cursor. The drag icon itself is a Window, so XTranslateCoordinates will return the drag icon. --Boundary-00=_XoHO+ll9kIwDSNL Content-Type: text/x-diff; charset="us-ascii"; name="qdnd_x11.cpp.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="qdnd_x11.cpp.diff" Index: qdnd_x11.cpp =================================================================== RCS file: /home/kde/qt-copy/src/kernel/qdnd_x11.cpp,v retrieving revision 1.54 diff -u -p -b -r1.54 qdnd_x11.cpp --- qdnd_x11.cpp 29 Jan 2003 13:54:56 -0000 1.54 +++ qdnd_x11.cpp 30 Jan 2003 00:29:30 -0000 @@ -245,6 +245,9 @@ static const char* const default_pm[] = "X X X X X X X" }; +// Use NETWM for drag and drop. +Atom qt_net_wm_client_list_stacking; + class QShapedPixmapWidget : public QWidget { public: QShapedPixmapWidget(int screen = -1) : @@ -419,6 +422,9 @@ void qt_xdnd_setup() { qt_x11_intern_atom( "QT_SELECTION", &qt_selection_property ); qt_x11_intern_atom( "INCR", &qt_incr_atom ); + qt_x11_intern_atom("_NET_CLIENT_LIST_STACKING", + &qt_net_wm_client_list_stacking); + qAddPostRoutine( qt_xdnd_cleanup ); } @@ -1096,6 +1102,55 @@ Window findRealWindow( const QPoint & po return 0; } +static Window findRealWindowNETWM( const QPoint& pos, Window root, int) +{ + int x = pos.x(); + int y = pos.y(); + + Window* first; + Window* win; + + Atom type_ret; + int format_ret; + unsigned long nitems_ret; + unsigned long unused; + unsigned char *data_ret = 0; + + if (XGetWindowProperty(QPaintDevice::x11AppDisplay(), root, + qt_net_wm_client_list_stacking, + 0, 1024, False, XA_WINDOW, &type_ret, + &format_ret, &nitems_ret, &unused, &data_ret) + == Success) { + if (type_ret == XA_WINDOW && format_ret == 32) + first = (Window*) data_ret; + + if (data_ret) + XFree(data_ret); + } + else + return 0; + + win = first + nitems_ret - 1; + do { + XWindowAttributes attr; + XGetWindowAttributes(QPaintDevice::x11AppDisplay(), *win, &attr); + + int globalX, globalY; + Window child_ret; + XTranslateCoordinates(QPaintDevice::x11AppDisplay(), *win, root, + attr.x, attr.y, &globalX, &globalY, &child_ret); + + if ( attr.map_state != IsUnmapped + && x >= globalX && x < globalX + attr.width + && y >= globalY && y < globalY + attr.height) + break; + + --win; + } while (win != first); + + return *win; +} + void QDragManager::move( const QPoint & globalPos ) { Q_ASSERT( object != 0 ); // ### remove in Qt 4.0 (object should never be 0 here) @@ -1131,7 +1186,8 @@ void QDragManager::move( const QPoint & if (targetW) target = targetW; if ( qt_xdnd_deco && (!target || target == qt_xdnd_deco->winId()) ) { - target = findRealWindow(globalPos,rootwin,6); + // target = findRealWindowM(globalPos,rootwin,6); + target = findRealWindowNETWM(globalPos,rootwin,6); } } --Boundary-00=_XoHO+ll9kIwDSNL Content-Type: text/x-c++src; charset="us-ascii"; name="findclient.cpp" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="findclient.cpp" // Build using: // g++ -g findclient.cpp -o findclient -I/usr/local/kde/include -L/usr/X11R6/lib -L/usr/local/kde/lib -lX11 -lqt-mt #include #include #include extern "C" { #include #include } #include "kcounterprof.h" static Display* dpy; static Window supportWindow; static Window rootWindow; static Atom wm_state; static Atom net_client_list_stacking; static int count; static Window findRealWindow( int x, int y, Window w, int md ) { count++; if ( md ) { XWindowAttributes attr; XGetWindowAttributes(dpy, w, &attr); if ( attr.map_state != IsUnmapped && x >= attr.x && x < attr.x + attr.width && y >= attr.y && y < attr.y + attr.height) { { Atom type = None; int f; unsigned long n, a; unsigned char *data; XGetWindowProperty( dpy, w, wm_state, 0, 0, False, AnyPropertyType, &type, &f,&n,&a,&data ); if ( data ) XFree(data); if ( type ) return w; } Window r, p; Window* c; uint nc; if ( XQueryTree( dpy, w, &r, &p, &c, &nc ) ) { r=0; for (uint i=nc; !r && i--; ) { r = findRealWindow( x-attr.x, y-attr.y, c[i], md-1 ); } XFree(c); if ( r ) return r; // We didn't find a client window! Just use the // innermost window. } // No children! return w; } } return 0; } static Window findRealWindowNETWM( int x, int y, Window, int) { Window* head; Atom type_ret; int format_ret; unsigned long nitems_ret; unsigned long unused; unsigned char *data_ret = 0; if (XGetWindowProperty(dpy, rootWindow, net_client_list_stacking, 0, 1024, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { if (type_ret == XA_WINDOW && format_ret == 32) head = (Window*) data_ret; if (data_ret) XFree(data_ret); } else return 0; Window* win = head + nitems_ret - 1; do { XWindowAttributes attr; XGetWindowAttributes(dpy, *win, &attr); int root_x, root_y; Window child_ret; XTranslateCoordinates(dpy, *win, rootWindow, attr.x, attr.y, &root_x, &root_y, &child_ret); if (attr.map_state != IsUnmapped && x >= root_x && x < root_x + attr.width && y >= root_y && y < root_y + attr.height) break; --win; } while (win != head); return *win; } void test(int x, int y) { Window result1 = findRealWindow(x, y, rootWindow, 6); Window result2 = findRealWindowNETWM(x, y, rootWindow, 6); if (result1 != result2) { qDebug("Different results for position (%i, %i): ", x, y); qDebug(" findRealWindow: %x", result1); qDebug(" findRealWindowNETWM: %x", result2); } } int main(int argc, char** argv) { QApplication app(argc, argv); supportWindow = (new QWidget())->winId(); srand48(QTime::currentTime().second()+QTime::currentTime().msec()); dpy = QPaintDevice::x11AppDisplay(); wm_state = XInternAtom(dpy, "WM_STATE", False); net_client_list_stacking = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False); count = 0; rootWindow = RootWindow(dpy, DefaultScreen(dpy)); int x, y; const int width = DisplayWidth(dpy, DefaultScreen(dpy)); const int height = DisplayHeight(dpy, DefaultScreen(dpy)); /* for (;;) { x = int(drand48() * width); y = int(drand48() * height); test(x, y); } */ x = int(drand48() * width); y = int(drand48() * height); KCounterProf::begin("findRealWindow"); Window result1 = findRealWindow(x, y, rootWindow, 6); KCounterProf::end("findRealWindow"); qDebug("findRealWindow was called %u times", count); qDebug("Window returned: %x", result1); KCounterProf::begin("findRealWindowNETWM"); Window result2 = findRealWindowNETWM(x, y, rootWindow, 6); KCounterProf::end("findRealWindowNETWM"); qDebug("Window returned: %x", result2); return 0; } --Boundary-00=_XoHO+ll9kIwDSNL-- _______________________________________________ Kde-optimize mailing list Kde-optimize@mail.kde.org http://mail.kde.org/mailman/listinfo/kde-optimize