summaryrefslogtreecommitdiff
path: root/plugins
diff options
authorBrandon Schaefer <brandontschaefer@gmail.com>2012-07-11 09:16:23 -0700
committerBrandon Schaefer <brandontschaefer@gmail.com>2012-07-11 09:16:23 -0700
commit7af468e8d018abfc4f6dfd9900d5585b20d76007 (patch)
treea8e4c19db37ca5c5c642d66a2923bede0d11509d /plugins
parent71cc5843006d1080313c739f46932d92e4282d8f (diff)
parent101c935ffd4b3b55bcbaa36d97664f8630382545 (diff)
* Merged trunk, fixed conflicts
(bzr r2463.4.3)
Diffstat (limited to 'plugins')
-rw-r--r--plugins/unity-mt-grab-handles/CMakeLists.txt2
-rw-r--r--plugins/unityshell/src/unityshell.cpp316
-rw-r--r--plugins/unityshell/src/unityshell.h16
3 files changed, 216 insertions, 118 deletions
diff --git a/plugins/unity-mt-grab-handles/CMakeLists.txt b/plugins/unity-mt-grab-handles/CMakeLists.txt
index 9e5a65f4a..3020cf6a3 100644
--- a/plugins/unity-mt-grab-handles/CMakeLists.txt
+++ b/plugins/unity-mt-grab-handles/CMakeLists.txt
@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
include (CompizPlugin)
-compiz_plugin (unitymtgrabhandles PKGDEPS nux-2.0>=2.0.0 PLUGINDEPS composite opengl CFLAGSADD -std=c++0x)
+compiz_plugin (unitymtgrabhandles PKGDEPS nux-3.0>=3.0.0 PLUGINDEPS composite opengl CFLAGSADD -std=c++0x)
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index aced94a8a..07435d47a 100644
--- a/plugins/unityshell/src/unityshell.cpp
+++ b/plugins/unityshell/src/unityshell.cpp
@@ -100,7 +100,6 @@ const unsigned int SCROLL_DOWN_BUTTON = 6;
const unsigned int SCROLL_UP_BUTTON = 7;
const std::string RELAYOUT_TIMEOUT = "relayout-timeout";
-const std::string REDRAW_IDLE = "redraw-idle";
} // namespace local
} // anon namespace
@@ -118,8 +117,8 @@ UnityScreen::UnityScreen(CompScreen* screen)
, super_keypressed_(false)
, newFocusedWindow(nullptr)
, doShellRepaint(false)
+ , didShellRepaint(false)
, allowWindowPaint(false)
- , damaged(false)
, _key_nav_mode_requested(false)
, _last_output(nullptr)
#ifndef USE_MODERN_COMPIZ_GL
@@ -909,13 +908,14 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo
}
doShellRepaint = false;
- damaged = false;
+ didShellRepaint = true;
}
bool UnityScreen::forcePaintOnTop ()
{
return !allowWindowPaint ||
- ((switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen())
+ ((switcher_controller_->Visible() ||
+ PluginAdapter::Default()->IsExpoActive())
&& !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));
}
@@ -1211,7 +1211,15 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
{
bool ret;
- doShellRepaint = true;
+ /*
+ * Very important!
+ * Don't waste GPU and CPU rendering the shell on every frame if you don't
+ * need to. Doing so on every frame causes Nux to hog the GPU and slow down
+ * ALL rendering. (LP: #988079)
+ */
+ bool force = forcePaintOnTop() || PluginAdapter::Default()->IsExpoActive();
+ doShellRepaint = force || !(region.isEmpty() || wt->GetDrawList().empty());
+
allowWindowPaint = true;
_last_output = output;
paint_panel_ = false;
@@ -1227,13 +1235,21 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
* attempts to bind it will only increment
* its bind reference so make sure that
* you always unbind as much as you bind */
- _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
+ if (doShellRepaint)
+ _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
#endif
+ // CompRegion has no clear() method. So this is the fastest alternative.
+ fullscreenRegion = CompRegion();
+ nuxRegion = CompRegion();
+
/* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
#ifndef USE_MODERN_COMPIZ_GL
+ if (doShellRepaint && !force && fullscreenRegion.contains(*output))
+ doShellRepaint = false;
+
if (doShellRepaint)
paintDisplay(region, transform, mask);
#endif
@@ -1286,16 +1302,26 @@ void UnityScreen::preparePaint(int ms)
for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
wi->HandleAnimations (ms);
- if (damaged)
- {
- damaged = false;
- damageNuxRegions();
- }
+ compizDamageNux(cScreen->currentDamage());
+ didShellRepaint = false;
+ firstWindowAboveShell = NULL;
}
void UnityScreen::donePaint()
{
+ /*
+ * It's only safe to clear the draw list if drawing actually occurred
+ * (i.e. the shell was not obscured behind a fullscreen window).
+ * If you clear the draw list and drawing has not occured then you'd be
+ * left with all your views thinking they're queued for drawing still and
+ * would refuse to redraw when you return from fullscreen.
+ * I think this is a Nux bug. ClearDrawList should ideally also mark all
+ * the queued views as draw_cmd_queued_=false.
+ */
+ if (didShellRepaint)
+ wt->ClearDrawList();
+
std::list <ShowdesktopHandlerWindowInterface *> remove_windows;
for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
@@ -1316,42 +1342,116 @@ void UnityScreen::donePaint()
cScreen->donePaint ();
}
-/* Grab changed nux regions and add damage rects for them */
-void UnityScreen::damageNuxRegions()
+void UnityScreen::compizDamageNux(CompRegion const& damage)
{
- CompRegion nux_damage;
-
- if (damaged)
+ if (!launcher_controller_)
return;
- std::vector<nux::Geometry> dirty = wt->GetDrawList();
- damaged = true;
+ /*
+ * Prioritise user interaction over active blur updates. So the general
+ * slowness of the active blur doesn't affect the UI interaction performance.
+ *
+ * Also, BackgroundEffectHelper::ProcessDamage() is causing a feedback loop
+ * while the dash is open. Calling it results in the NEXT frame (and the
+ * current one?) to get some damage. This GetDrawList().empty() check avoids
+ * that feedback loop and allows us to idle correctly.
+ */
+ if (wt->GetDrawList().empty())
+ {
+ CompRect::vector const& rects(damage.rects());
+ for (CompRect const& r : rects)
+ {
+ nux::Geometry geo(r.x(), r.y(), r.width(), r.height());
+ BackgroundEffectHelper::ProcessDamage(geo);
+ }
+ }
- for (std::vector<nux::Geometry>::iterator it = dirty.begin(), end = dirty.end();
- it != end; ++it)
+ auto launchers = launcher_controller_->launchers();
+ for (auto launcher : launchers)
{
- nux::Geometry const& geo = *it;
- nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
+ if (!launcher->Hidden())
+ {
+ nux::Geometry geo = launcher->GetAbsoluteGeometry();
+ CompRegion launcher_region(geo.x, geo.y, geo.width, geo.height);
+ if (damage.intersects(launcher_region))
+ launcher->QueueDraw();
+ nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
+ if (!tooltip.IsNull())
+ {
+ nux::Geometry tip = tooltip->GetAbsoluteGeometry();
+ CompRegion tip_region(tip.x, tip.y, tip.width, tip.height);
+ if (damage.intersects(tip_region))
+ tooltip->QueueDraw();
+ }
+ }
}
- nux::Geometry geo = wt->GetWindowCompositor().GetTooltipMainWindowGeometry();
- nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
+ std::vector<nux::View*> const& panels(panel_controller_->GetPanelViews());
+ for (nux::View* view : panels)
+ {
+ nux::Geometry geo = view->GetAbsoluteGeometry();
+ CompRegion panel_region(geo.x, geo.y, geo.width, geo.height);
+ if (damage.intersects(panel_region))
+ view->QueueDraw();
+ }
- geo = lastTooltipArea;
- nux_damage += CompRegion(lastTooltipArea.x, lastTooltipArea.y,
- lastTooltipArea.width, lastTooltipArea.height);
+ QuicklistManager* qm = QuicklistManager::Default();
+ if (qm)
+ {
+ QuicklistView* view = qm->Current();
+ if (view)
+ {
+ nux::Geometry geo = view->GetAbsoluteGeometry();
+ CompRegion quicklist_region(geo.x, geo.y, geo.width, geo.height);
+ if (damage.intersects(quicklist_region))
+ view->QueueDraw();
+ }
+ }
+}
+/* Grab changed nux regions and add damage rects for them */
+void UnityScreen::nuxDamageCompiz()
+{
/*
- * Avoid Nux damaging Nux as recommended by smspillaz. Though I don't
- * believe it would be harmful or significantly expensive right now.
+ * WARNING: Nux bug LP: #1014610 (unbounded DrawList growth) will cause
+ * this code to be called far too often in some cases and
+ * Unity will appear to freeze for a while. Please ensure you
+ * have Nux 3.0+ with the fix for LP: #1014610.
*/
+
+ if (!launcher_controller_ || !dash_controller_)
+ return;
+
+ CompRegion nux_damage;
+
+ std::vector<nux::Geometry> const& dirty = wt->GetDrawList();
+ for (auto geo : dirty)
+ nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
+
+ if (launcher_controller_->IsOverlayOpen())
+ {
+ nux::BaseWindow* dash_window = dash_controller_->window();
+ nux::Geometry const& geo = dash_window->GetAbsoluteGeometry();
+ nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
+ }
+
+ auto launchers = launcher_controller_->launchers();
+ for (auto launcher : launchers)
+ {
+ if (!launcher->Hidden())
+ {
+ nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
+ if (!tooltip.IsNull())
+ {
+ nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
+ nux_damage += CompRegion(g.x, g.y, g.width, g.height);
+ }
+ }
+ }
+
cScreen->damageRegionSetEnabled(this, false);
cScreen->damageRegion(nux_damage);
cScreen->damageRegionSetEnabled(this, true);
-
- wt->ClearDrawList();
-
- lastTooltipArea = geo;
}
/* handle X Events */
@@ -1371,9 +1471,11 @@ void UnityScreen::handleEvent(XEvent* event)
#endif
if (_key_nav_mode_requested)
{
+ // Close any overlay that is open.
if (launcher_controller_->IsOverlayOpen())
{
dash_controller_->HideDash();
+ hud_controller_->HideHud();
}
launcher_controller_->KeyNavGrab();
}
@@ -1407,6 +1509,19 @@ void UnityScreen::handleEvent(XEvent* event)
break;
case KeyPress:
{
+ if (super_keypressed_)
+ {
+ /* We need an idle to postpone this action, after the current event
+ * has been processed */
+ sources_.AddIdle([&] {
+ shortcut_controller_->SetEnabled(false);
+ shortcut_controller_->Hide();
+ EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, false);
+
+ return false;
+ });
+ }
+
KeySym key_sym;
char key_string[2];
int result = XLookupString(&(event->xkey), key_string, 2, &key_sym, 0);
@@ -1434,21 +1549,6 @@ void UnityScreen::handleEvent(XEvent* event)
if (super_keypressed_)
{
- if (key_sym != XK_Escape || (key_sym == XK_Escape && !launcher_controller_->KeyNavIsActive()))
- {
- /* We need an idle to postpone this action, after the current event
- * has been processed */
- sources_.Add(std::make_shared<glib::Idle>([&]() {
- if (!launcher_controller_->KeyNavIsActive())
- {
- shortcut_controller_->SetEnabled(false);
- shortcut_controller_->Hide();
- EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, false);
- }
- return false;
- }));
- }
-
skip_other_plugins = launcher_controller_->HandleLauncherKeyEvent(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string);
if (!skip_other_plugins)
skip_other_plugins = dash_controller_->CheckShortcutActivation(key_string);
@@ -1517,13 +1617,7 @@ void UnityScreen::handleEvent(XEvent* event)
void UnityScreen::damageRegion(const CompRegion &region)
{
- const CompRect::vector &rects(region.rects());
- for (const CompRect &r : rects)
- {
- nux::Geometry geo(r.x(), r.y(), r.width(), r.height());
- BackgroundEffectHelper::ProcessDamage(geo);
- }
-
+ compizDamageNux(region);
cScreen->damageRegion(region);
}
@@ -2008,6 +2102,9 @@ bool UnityScreen::ShowHud()
if (launcher_controller_->IsOverlayOpen())
dash_controller_->HideDash();
+ if (QuicklistManager::Default()->Current())
+ QuicklistManager::Default()->Current()->Hide();
+
hud_controller_->ShowHud();
}
@@ -2186,14 +2283,6 @@ bool isNuxWindow (CompWindow* value)
return false;
}
-const CompWindowList& UnityScreen::getWindowPaintList()
-{
- CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList();
- pl.remove_if(isNuxWindow);
-
- return pl;
-}
-
void UnityScreen::RaiseInputWindows()
{
std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
@@ -2218,6 +2307,42 @@ bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,
const CompRegion& region,
unsigned int mask)
{
+ /*
+ * The occlusion pass tests windows from TOP to BOTTOM. That's opposite to
+ * the actual painting loop.
+ *
+ * Detect uScreen->fullscreenRegion here. That represents the region which
+ * fully covers the shell on its output. It does not include regular windows
+ * stacked above the shell like DnD icons or Onboard etc.
+ */
+ if (isNuxWindow(window))
+ {
+ if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+ {
+ uScreen->nuxRegion += window->geometry();
+ uScreen->nuxRegion -= uScreen->fullscreenRegion;
+ }
+ return false; // Ensure nux windows are never painted by compiz
+ }
+ else if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+ {
+ static const unsigned int nonOcclusionBits =
+ PAINT_WINDOW_TRANSLUCENT_MASK |
+ PAINT_WINDOW_TRANSFORMED_MASK |
+ PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
+ if (!(mask & nonOcclusionBits) &&
+ (window->state() & CompWindowStateFullscreenMask))
+ // And I've been advised to test other things, but they don't work:
+ // && (attrib.opacity == OPAQUE)) <-- Doesn't work; Only set in glDraw
+ // && !window->alpha() <-- Doesn't work; Opaque windows often have alpha
+ {
+ uScreen->fullscreenRegion += window->geometry();
+ uScreen->fullscreenRegion -= uScreen->nuxRegion;
+ }
+ if (uScreen->nuxRegion.isEmpty())
+ uScreen->firstWindowAboveShell = window;
+ }
+
GLWindowPaintAttrib wAttrib = attrib;
if (mMinimizeHandler)
@@ -2276,28 +2401,17 @@ bool UnityWindow::glDraw(const GLMatrix& matrix,
}
}
- if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ())
+ if (uScreen->doShellRepaint &&
+ !uScreen->forcePaintOnTop () &&
+ window == uScreen->firstWindowAboveShell &&
+ !uScreen->fullscreenRegion.contains(window->geometry())
+ )
{
- std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
- unsigned int size = xwns.size();
-
- for (CompWindow* w = window; w && uScreen->doShellRepaint; w = w->prev)
- {
- auto id = w->id();
-
- for (unsigned int i = 0; i < size; ++i)
- {
- if (xwns[i] == id)
- {
#ifdef USE_MODERN_COMPIZ_GL
- uScreen->paintDisplay();
+ uScreen->paintDisplay();
#else
- uScreen->paintDisplay(region, matrix, mask);
+ uScreen->paintDisplay(region, matrix, mask);
#endif
- break;
- }
- }
- }
}
if (window->type() == CompWindowTypeDesktopMask)
@@ -2591,25 +2705,7 @@ void UnityScreen::initUnity(nux::NThread* thread, void* InitData)
void UnityScreen::onRedrawRequested()
{
- // disable blur updates so we dont waste perf. This can stall the blur during animations
- // but ensures a smooth animation.
- if (_in_paint)
- {
- if (!sources_.GetSource(local::REDRAW_IDLE))
- {
- auto redraw_idle(std::make_shared<glib::Idle>(glib::Source::Priority::DEFAULT));
- sources_.Add(redraw_idle, local::REDRAW_IDLE);
-
- redraw_idle->Run([&]() {
- onRedrawRequested();
- return false;
- });
- }
- }
- else
- {
- damageNuxRegions();
- }
+ nuxDamageCompiz();
}
/* Handle option changes and plug that into nux windows */
@@ -2768,17 +2864,14 @@ void UnityScreen::ScheduleRelayout(guint timeout)
{
if (!sources_.GetSource(local::RELAYOUT_TIMEOUT))
{
- auto relayout_timeout(std::make_shared<glib::Timeout>(timeout));
- sources_.Add(relayout_timeout, local::RELAYOUT_TIMEOUT);
-
- relayout_timeout->Run([&]() {
+ sources_.AddTimeout(timeout, [&] {
NeedsRelayout();
Relayout();
cScreen->damageScreen();
return false;
- });
+ }, local::RELAYOUT_TIMEOUT);
}
}
@@ -2871,7 +2964,6 @@ void UnityScreen::initLauncher()
optionGetMenusDiscoveryDuration(),
optionGetMenusDiscoveryFadein(),
optionGetMenusDiscoveryFadeout());
- panel_controller_->SetOpacity(optionGetPanelOpacity());
LOG_INFO(logger) << "initLauncher-Panel " << timer.ElapsedSeconds() << "s";
/* Setup Places */
@@ -3153,6 +3245,8 @@ void capture_g_log_calls(const gchar* log_domain,
const gchar* message,
gpointer user_data)
{
+ // If the environment variable is set, we capture the backtrace.
+ static bool glog_backtrace = ::getenv("UNITY_LOG_GLOG_BACKTRACE");
// If nothing else, all log messages from unity should be identified as such
std::string module("unity");
if (log_domain)
@@ -3163,14 +3257,16 @@ void capture_g_log_calls(const gchar* log_domain,
nux::logging::Level level = glog_level_to_nux(log_level);
if (level >= logger.GetEffectiveLogLevel())
{
- nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
- << message;
- if (level >= nux::logging::Error)
+ std::string backtrace;
+ if (glog_backtrace && level >= nux::logging::Warning)
{
- nux::logging::Backtrace();
+ backtrace = "\n" + nux::logging::Backtrace();
}
+ nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
+ << message << backtrace;
}
}
} // anonymous namespace
} // namespace unity
+
diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h
index f53f09e20..999af973e 100644
--- a/plugins/unityshell/src/unityshell.h
+++ b/plugins/unityshell/src/unityshell.h
@@ -133,9 +133,6 @@ public:
CompOutput*,
unsigned int);
- /* Pop our InputOutput windows from the paint list */
- const CompWindowList& getWindowPaintList();
-
/* handle X11 events */
void handleEvent(XEvent*);
@@ -212,7 +209,10 @@ private:
bool initPluginActions();
void initLauncher();
- void damageNuxRegions();
+
+ void compizDamageNux(CompRegion const& region);
+ void nuxDamageCompiz();
+
void onRedrawRequested();
void Relayout();
@@ -260,7 +260,6 @@ private:
bool enable_shortcut_overlay_;
GestureEngine gesture_engine_;
- nux::Geometry lastTooltipArea;
bool needsRelayout;
bool _in_paint;
bool super_keypressed_;
@@ -277,11 +276,14 @@ private:
/* handle paint order */
bool doShellRepaint;
+ bool didShellRepaint;
bool allowWindowPaint;
- bool damaged;
bool _key_nav_mode_requested;
CompOutput* _last_output;
- CompWindowList _withRemovedNuxWindows;
+
+ CompRegion nuxRegion;
+ CompRegion fullscreenRegion;
+ CompWindow* firstWindowAboveShell;
nux::Property<nux::Geometry> primary_monitor_;