Drag and drop optimization (update)
Wilco Greven
kde-optimize@mail.kde.org
Thu, 30 Jan 2003 12:05:35 +0100
--Boundary-00=_/bQO+2N2ptAig+e
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Here's an updated patch + testprogram. It uses XGetGeometry instead of
XGetWindowAttributes now. And the clumsy do..while has been replaced by a for
loop.
--Boundary-00=_/bQO+2N2ptAig+e
Content-Type: text/x-diff;
charset="iso-8859-1";
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 10:59:36 -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 rootWindow, int )
+{
+ Display* const dpy = QPaintDevice::x11AppDisplay();
+
+ Window* head;
+
+ Atom type_ret;
+ int format_ret;
+ unsigned long nitems_ret;
+ unsigned long unused;
+ unsigned char *data_ret = 0;
+
+ if (XGetWindowProperty(dpy, rootWindow, 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)
+ head = (Window*) data_ret;
+
+ if (data_ret)
+ XFree(data_ret);
+ }
+ else
+ return 0;
+
+ Window* win;
+ for (win = head + nitems_ret - 1; win != head; --win) {
+ Window root_win;
+ int win_x, win_y;
+ unsigned int win_width, win_height;
+ unsigned int border_width_ret;
+ unsigned int depth_ret;
+ XGetGeometry(dpy, *win, &root_win, &win_x, &win_y,
+ &win_width, &win_height, &border_width_ret,
+ &depth_ret);
+
+ int win_glob_x, win_glob_y;
+ Window child;
+ XTranslateCoordinates(dpy, *win, root_win, win_x, win_y,
+ &win_glob_x, &win_glob_y, &child);
+
+ if (pos.x() >= win_glob_x && pos.x() < win_glob_x + win_width
+ && pos.y() >= win_glob_y && pos.y() < win_glob_y + win_height)
+ break;
+ }
+
+ 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=_/bQO+2N2ptAig+e
Content-Type: text/x-c++src;
charset="iso-8859-1";
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 <qapplication.h>
#include <qdatetime.h>
#include <qwidget.h>
extern "C" {
#include <X11/Xatom.h>
#include <X11/Xlib.h>
}
#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;
for (win = head + nitems_ret - 1; win != head; --win) {
Window root_win;
int win_x, win_y;
unsigned int win_width, win_height;
unsigned int border_width_ret;
unsigned int depth_ret;
XGetGeometry(dpy, *win, &root_win, &win_x, &win_y,
&win_width, &win_height, &border_width_ret,
&depth_ret);
int win_glob_x, win_glob_y;
Window child_ret;
XTranslateCoordinates(dpy, *win, root_win, win_x, win_y,
&win_glob_x, &win_glob_y, &child_ret);
if (x >= win_glob_x && x < win_glob_x + win_width
&& y >= win_glob_y && y < win_glob_y + win_height)
break;
}
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=_/bQO+2N2ptAig+e--