diff options
| author | Daniel van Vugt <daniel.van.vugt@canonical.com> | 2012-07-16 12:01:30 +0800 |
|---|---|---|
| committer | Daniel van Vugt <daniel.van.vugt@canonical.com> | 2012-07-16 12:01:30 +0800 |
| commit | ce8f901422f4c734d7f0db2d5231e85b04979522 (patch) | |
| tree | af58082affb194c416558d5b79fa010e58178e8c | |
| parent | 44a27aeb6ec386e005c17e1a8db4132b3c8a70ff (diff) | |
Don't bind the FBO if it's possible it won't get painted and unbound. That
could lead the the screen freezing while fullscreen windows are open. (LP: #1024911) Fixes LP: #1024911 (bzr r2501.2.1)
| -rw-r--r-- | plugins/unityshell/src/unityshell.cpp | 45 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.h | 2 |
2 files changed, 45 insertions, 2 deletions
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index 34ad8880a..da6886a3b 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -1202,6 +1202,42 @@ void UnityWindow::handleEvent (XEvent *event) } } +bool UnityScreen::shellCouldBeHidden(CompOutput const& output) +{ + std::vector<Window> const& nuxwins(nux::XInputWindow::NativeHandleList()); + + // Loop through windows from front to back + CompWindowList const& wins = screen->windows(); + for ( CompWindowList::const_reverse_iterator r = wins.rbegin() + ; r != wins.rend() + ; r++ + ) + { + CompWindow* w = *r; + + /* + * The shell is hidden if there exists any window that fully covers + * the output and is in front of all Nux windows on that output. + */ + if (w->isMapped() && + !(w->state () & CompWindowStateHiddenMask) && + w->geometry().contains(output)) + { + return true; + } + else + { + for (Window n : nuxwins) + { + if (w->id() == n && output.intersects(w->geometry())) + return false; + } + } + } + + return false; +} + /* called whenever we need to repaint parts of the screen */ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib, const GLMatrix& transform, @@ -1234,8 +1270,13 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib, * once an fbo is bound any further * attempts to bind it will only increment * its bind reference so make sure that - * you always unbind as much as you bind */ - if (doShellRepaint) + * you always unbind as much as you bind + * + * But NOTE: It is only safe to bind the FBO if !shellCouldBeHidden. + * Otherwise it's possible painting won't occur and that would + * confuse the state of the FBO. + */ + if (doShellRepaint && !shellCouldBeHidden(*output)) _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ())); #endif diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index 999af973e..34e29975e 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -113,6 +113,8 @@ public: void damageRegion(const CompRegion ®ion); + bool shellCouldBeHidden(CompOutput const& output); + /* paint on top of all windows if we could not find a window * to paint underneath */ bool glPaintOutput(const GLScreenPaintAttrib&, |
