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:
parent
9390b270f8
commit
6c4ef3ef35
1 changed files with 49 additions and 18 deletions
67
effects.cpp
67
effects.cpp
|
@ -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)
|
||||
{
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.override_redirect = True;
|
||||
Window 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));
|
||||
|
||||
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;
|
||||
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());
|
||||
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
|
||||
|
@ -1042,11 +1070,14 @@ void EffectsHandlerImpl::checkInputWindowStacking()
|
|||
{
|
||||
if (input_windows.count() == 0)
|
||||
return;
|
||||
Window* wins = new Window[ input_windows.count()];
|
||||
Window* wins = new Window[input_windows.count()];
|
||||
int pos = 0;
|
||||
foreach (const InputWindowPair & it, input_windows)
|
||||
wins[ pos++ ] = it.second;
|
||||
XRaiseWindow(display(), wins[ 0 ]);
|
||||
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;
|
||||
// Raise electric border windows above the input windows
|
||||
|
|
Loading…
Reference in a new issue