summaryrefslogtreecommitdiff
diff options
authorDaniel van Vugt <daniel.van.vugt@canonical.com>2012-07-16 12:01:30 +0800
committerDaniel van Vugt <daniel.van.vugt@canonical.com>2012-07-16 12:01:30 +0800
commitce8f901422f4c734d7f0db2d5231e85b04979522 (patch)
treeaf58082affb194c416558d5b79fa010e58178e8c
parent44a27aeb6ec386e005c17e1a8db4132b3c8a70ff (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.cpp45
-rw-r--r--plugins/unityshell/src/unityshell.h2
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 &region);
+ 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&,