re-use input window, prevent destryoing it

we cannot fix Qt DnD crashing on client destruction (eg. also occurs with toolptips)
but we can prevent it to happen with effects by just un/mapping the input window instead
of destroying and re-creating it

BUG: 179077
FIXED-IN: 4.10
REVIEW: 105339
This commit is contained in:
Thomas Lübking 2012-06-24 11:13:33 +02:00
parent 9390b270f8
commit 6c4ef3ef35

View file

@ -962,23 +962,52 @@ QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, const QPoint& p, int
Window EffectsHandlerImpl::createInputWindow(Effect* e, int x, int y, int w, int h, const QCursor& cursor)
{
Window win = 0;
QList<InputWindowPair>::iterator it = input_windows.begin();
while (it != input_windows.end()) {
if (it->first != e) {
++it;
continue;
}
XWindowAttributes attr;
if (!XGetWindowAttributes(display(), it->second, &attr)) {
// this is some random junk that certainly should no be here
kDebug(1212) << "found input window that is NOT on the server, something is VERY broken here";
Q_ASSERT(false); // exit in debug mode - for releases we'll be a bit more graceful
it = input_windows.erase(it);
continue;
}
if (attr.x == x && attr.y == y && attr.width == w && attr.height == h) {
win = it->second; // re-use
break;
} else if (attr.map_state == IsUnmapped) {
// probably old one, likely no longer of interest
XDestroyWindow(display(), it->second);
it = input_windows.erase(it);
continue;
}
++it;
}
if (!win) {
XSetWindowAttributes attrs;
attrs.override_redirect = True;
Window win = XCreateWindow(display(), rootWindow(), x, y, w, h, 0, 0, InputOnly, CopyFromParent,
win = XCreateWindow(display(), rootWindow(), x, y, w, h, 0, 0, InputOnly, CopyFromParent,
CWOverrideRedirect, &attrs);
// TODO keeping on top?
// TODO enter/leave notify?
XSelectInput(display(), win, ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
XDefineCursor(display(), win, cursor.handle());
XMapWindow(display(), win);
input_windows.append(qMakePair(e, win));
}
XMapRaised(display(), win);
// Raise electric border windows above the input windows
// so they can still be triggered.
#ifdef KWIN_BUILD_SCREENEDGES
Workspace::self()->screenEdge()->ensureOnTop();
#endif
if (input_windows.count() > 10) // that sounds like some leak - could still be correct, thoug - so NO ABORT HERE!
kDebug() << "** warning ** there are now " << input_windows.count() <<
"input windows what's a bit much - please have a look and if this counts up, better report a bug";
return win;
}
@ -986,8 +1015,7 @@ void EffectsHandlerImpl::destroyInputWindow(Window w)
{
foreach (const InputWindowPair & pos, input_windows) {
if (pos.second == w) {
input_windows.removeAll(pos);
XDestroyWindow(display(), w);
XUnmapWindow(display(), w);
#ifdef KWIN_BUILD_SCREENEDGES
Workspace::self()->screenEdge()->raisePanelProxies();
#endif
@ -1044,8 +1072,11 @@ void EffectsHandlerImpl::checkInputWindowStacking()
return;
Window* wins = new Window[input_windows.count()];
int pos = 0;
foreach (const InputWindowPair & it, input_windows)
foreach (const InputWindowPair &it, input_windows) {
XWindowAttributes attr;
if (XGetWindowAttributes(display(), it.second, &attr) && attr.map_state != IsUnmapped)
wins[pos++] = it.second;
}
XRaiseWindow(display(), wins[0]);
XRestackWindows(display(), wins, pos);
delete[] wins;