From 8129451ab379fd87f8f40892e444da82bbad0340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Wed, 30 Jan 2013 21:50:09 +0100 Subject: [PATCH] re-settle slideBack effect to stackingOrderChanged BUG: 294490 FIXED-IN: 4.11 --- effects/slideback/slideback.cpp | 120 ++++++++++++-------------------- effects/slideback/slideback.h | 12 ++-- 2 files changed, 49 insertions(+), 83 deletions(-) diff --git a/effects/slideback/slideback.cpp b/effects/slideback/slideback.cpp index 529dd37bab..e527d7080b 100644 --- a/effects/slideback/slideback.cpp +++ b/effects/slideback/slideback.cpp @@ -30,14 +30,14 @@ KWIN_EFFECT(slideback, SlideBackEffect) SlideBackEffect::SlideBackEffect() { - updateStackingOrder(); - disabled = false; - unminimizedWindow = NULL; - connect(effects, SIGNAL(windowAdded(KWin::EffectWindow*)), this, SLOT(slotWindowAdded(KWin::EffectWindow*))); - connect(effects, SIGNAL(windowActivated(KWin::EffectWindow*)), this, SLOT(slotWindowActivated(KWin::EffectWindow*))); - connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*))); - connect(effects, SIGNAL(windowUnminimized(KWin::EffectWindow*)), this, SLOT(slotWindowUnminimized(KWin::EffectWindow*))); - connect(effects, SIGNAL(tabBoxClosed()), this, SLOT(slotTabBoxClosed())); + m_tabboxActive = 0; + m_justMapped = m_upmostWindow = NULL; + connect(effects, SIGNAL(windowAdded(KWin::EffectWindow*)), SLOT(slotWindowAdded(KWin::EffectWindow*))); + connect(effects, SIGNAL(stackingOrderChanged()), SLOT(slotStackingOrderChanged())); + connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), SLOT(slotWindowDeleted(KWin::EffectWindow*))); + connect(effects, SIGNAL(windowUnminimized(KWin::EffectWindow*)), SLOT(slotWindowUnminimized(KWin::EffectWindow*))); + connect(effects, SIGNAL(tabBoxAdded(int)), SLOT(slotTabBoxAdded())); + connect(effects, SIGNAL(tabBoxClosed()), SLOT(slotTabBoxClosed())); } static inline bool windowsShareDesktop(EffectWindow *w1, EffectWindow *w2) @@ -45,29 +45,37 @@ static inline bool windowsShareDesktop(EffectWindow *w1, EffectWindow *w2) return w1->isOnAllDesktops() || w2->isOnAllDesktops() || w1->desktop() == w2->desktop(); } -void SlideBackEffect::slotWindowActivated(EffectWindow* w) + +void SlideBackEffect::slotStackingOrderChanged() { - if (w == NULL || w->keepAbove()) { // plasma popups, yakuake etc... + if (effects->activeFullScreenEffect() || m_tabboxActive) { + oldStackingOrder = effects->stackingOrder(); + usableOldStackingOrder = usableWindows(oldStackingOrder); return; } - if (disabled || effects->activeFullScreenEffect()) { // TabBox or PresentWindows/Cube in progress - updateStackingOrder(); - disabled = false; + EffectWindowList newStackingOrder = effects->stackingOrder(), + usableNewStackingOrder = usableWindows(newStackingOrder); + if (usableNewStackingOrder == usableOldStackingOrder || usableNewStackingOrder.isEmpty()) { + oldStackingOrder = newStackingOrder; + usableOldStackingOrder = usableNewStackingOrder; return; } - if (!isWindowUsable(w) || !stackingOrderChanged() || !isWindowOnTop(w)) { // Focus changed but stacking still the same - updateStackingOrder(); - return; - } + m_upmostWindow = usableNewStackingOrder.last(); - if (unminimizedWindow == w) { // A window was activated by being unminimized. Don't trigger SlideBack. - unminimizedWindow = NULL; - updateStackingOrder(); - return; - } + if (m_upmostWindow == m_justMapped ) // a window was added, got on top, stacking changed. Nothing impressive + m_justMapped = 0; + else if (m_upmostWindow != usableOldStackingOrder.last()) + windowRaised(m_upmostWindow); + + oldStackingOrder = newStackingOrder; + usableOldStackingOrder = usableNewStackingOrder; +} + +void SlideBackEffect::windowRaised(EffectWindow *w) +{ // Determine all windows on top of the activated one bool currentFound = false; foreach (EffectWindow * tmp, oldStackingOrder) { @@ -112,7 +120,6 @@ void SlideBackEffect::slotWindowActivated(EffectWindow* w) effects->setElevatedWindow(tmp, false); } } - updateStackingOrder(); } QRect SlideBackEffect::getSlideDestination(const QRect &windowUnderGeometry, const QRect &windowOverGeometry) @@ -141,12 +148,6 @@ QRect SlideBackEffect::getSlideDestination(const QRect &windowUnderGeometry, con return slideRect; } -void SlideBackEffect::updateStackingOrder() -{ - usableOldStackingOrder = usableWindows(effects->stackingOrder()); - oldStackingOrder = effects->stackingOrder(); -} - void SlideBackEffect::prePaintScreen(ScreenPrePaintData &data, int time) { if (motionManager.managingWindows()) { @@ -175,21 +176,6 @@ void SlideBackEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, void SlideBackEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) { - if (stackingOrderChanged() && (w == newTopWindow()) && !disabled) { - /* This can happen because of two reasons: - - a window has received the focus earlier without being raised and is raised now. -> call windowActivated() now - - paintWindow() is called with a new stackingOrder before activateWindow(). Bug? -> don't draw the overlapping content;*/ - foreach (EffectWindow * tmp, oldStackingOrder) { - if (oldStackingOrder.lastIndexOf(tmp) > oldStackingOrder.lastIndexOf(w) && isWindowUsable(tmp) && windowsShareDesktop(tmp, w)) { - kDebug(1212) << "screw detected. region:" << region << "clipping:" << tmp->geometry() ; - clippedRegions << region.subtracted(tmp->geometry()); - PaintClipper::push(clippedRegions.last()); -// region = region.subtracted( tmp->geometry() ); - } - } - // Finally call windowActivated in case a already active window is raised. - slotWindowActivated(w); - } if (motionManager.isManaging(w)) { motionManager.apply(w, data); } @@ -207,7 +193,7 @@ void SlideBackEffect::postPaintWindow(EffectWindow* w) if (motionManager.isManaging(w)) { if (destinationList.contains(w)) { if (!motionManager.isWindowMoving(w)) { // has window reched its destination? - // If we are still intersecting with the activeWindow it is moving. slide to somewhere else + // If we are still intersecting with the upmostWindow it is moving. slide to somewhere else // restore the stacking order of all windows not intersecting any more except panels if (coveringWindows.contains(w)) { EffectWindowList tmpList; @@ -216,9 +202,9 @@ void SlideBackEffect::postPaintWindow(EffectWindow* w) if (motionManager.isManaging(tmp)) { elevatedGeometry = motionManager.transformedGeometry(tmp).toAlignedRect(); } - if (effects->activeWindow() && !tmp->isDock() && !tmp->keepAbove() && effects->activeWindow()->geometry().intersects(elevatedGeometry)) { + if (m_upmostWindow && !tmp->isDock() && !tmp->keepAbove() && m_upmostWindow->geometry().intersects(elevatedGeometry)) { QRect newDestination; - newDestination = getSlideDestination(getModalGroupGeometry(effects->activeWindow()), elevatedGeometry); + newDestination = getSlideDestination(getModalGroupGeometry(m_upmostWindow), elevatedGeometry); if (!motionManager.isManaging(tmp)) { motionManager.manage(tmp); } @@ -256,7 +242,7 @@ void SlideBackEffect::postPaintWindow(EffectWindow* w) if (coveringWindows.contains(w)) { // It could happen that there is no aciveWindow() here if the user clicks the close-button on an inactive window. // Just skip... the window will be removed in windowDeleted() later - if (effects->activeWindow() && !intersects(effects->activeWindow(), motionManager.transformedGeometry(w).toAlignedRect())) { + if (m_upmostWindow && !intersects(m_upmostWindow, motionManager.transformedGeometry(w).toAlignedRect())) { coveringWindows.removeAll(w); if (coveringWindows.isEmpty()) { // Restore correct stacking order @@ -273,6 +259,10 @@ void SlideBackEffect::postPaintWindow(EffectWindow* w) void SlideBackEffect::slotWindowDeleted(EffectWindow* w) { + if (w == m_upmostWindow) + m_upmostWindow = 0; + if (w == m_justMapped) + m_justMapped = 0; usableOldStackingOrder.removeAll(w); oldStackingOrder.removeAll(w); coveringWindows.removeAll(w); @@ -284,34 +274,23 @@ void SlideBackEffect::slotWindowDeleted(EffectWindow* w) void SlideBackEffect::slotWindowAdded(EffectWindow *w) { - Q_UNUSED(w); - updateStackingOrder(); + m_justMapped = w; } void SlideBackEffect::slotWindowUnminimized(EffectWindow* w) { // SlideBack should not be triggered on an unminimized window. For this we need to store the last unminimized window. - // If a window is unminimized but not on top we need to clear the memory because the windowUnminimized() is not - // followed by a windowActivated(). - if (isWindowOnTop(w)) { - unminimizedWindow = w; - } else { - unminimizedWindow = NULL; - } + m_justMapped = w; } -void SlideBackEffect::slotTabBoxClosed() +void SlideBackEffect::slotTabBoxAdded() { - disabled = true; + ++m_tabboxActive; } -bool SlideBackEffect::isWindowOnTop(EffectWindow* w) +void SlideBackEffect::slotTabBoxClosed() { - EffectWindowList openWindows = usableWindows(effects->stackingOrder()); - if (!openWindows.isEmpty() && (openWindows.last() == w)) { - return true; - } - return false; + m_tabboxActive = qMax(m_tabboxActive-1, 0); } bool SlideBackEffect::isWindowUsable(EffectWindow* w) @@ -337,17 +316,6 @@ EffectWindowList SlideBackEffect::usableWindows(const EffectWindowList & allWind return retList; } -bool SlideBackEffect::stackingOrderChanged() -{ - return !(usableOldStackingOrder == usableWindows(effects->stackingOrder())); -} - -EffectWindow* SlideBackEffect::newTopWindow() -{ - EffectWindowList stacking = usableWindows(effects->stackingOrder()); - return stacking.isEmpty() ? NULL : stacking.last(); -} - QRect SlideBackEffect::getModalGroupGeometry(EffectWindow *w) { QRect modalGroupGeometry = w->geometry(); diff --git a/effects/slideback/slideback.h b/effects/slideback/slideback.h index eec82fc1c4..2bed4a0798 100644 --- a/effects/slideback/slideback.h +++ b/effects/slideback/slideback.h @@ -44,9 +44,10 @@ public: public Q_SLOTS: void slotWindowAdded(KWin::EffectWindow *w); - void slotWindowActivated(KWin::EffectWindow *w); void slotWindowDeleted(KWin::EffectWindow *w); void slotWindowUnminimized(KWin::EffectWindow *w); + void slotStackingOrderChanged(); + void slotTabBoxAdded(); void slotTabBoxClosed(); private: @@ -56,20 +57,17 @@ private: EffectWindowList oldStackingOrder; EffectWindowList coveringWindows; EffectWindowList elevatedList; - EffectWindow* unminimizedWindow; + EffectWindow *m_justMapped, *m_upmostWindow; QHash destinationList; - bool disabled; + int m_tabboxActive; QList clippedRegions; QRect getSlideDestination(const QRect &windowUnderGeometry, const QRect &windowOverGeometry); - void updateStackingOrder(); - bool isWindowOnTop(EffectWindow *w); bool isWindowUsable(EffectWindow *w); - bool stackingOrderChanged(); bool intersects(EffectWindow *windowUnder, const QRect &windowOverGeometry); EffectWindowList usableWindows(const EffectWindowList &allWindows); - EffectWindow *newTopWindow(); QRect getModalGroupGeometry(EffectWindow *w); + void windowRaised(EffectWindow *w); };