diff options
| author | Brandon Schaefer <brandontschaefer@gmail.com> | 2012-07-11 09:16:23 -0700 |
|---|---|---|
| committer | Brandon Schaefer <brandontschaefer@gmail.com> | 2012-07-11 09:16:23 -0700 |
| commit | 7af468e8d018abfc4f6dfd9900d5585b20d76007 (patch) | |
| tree | a8e4c19db37ca5c5c642d66a2923bede0d11509d /plugins | |
| parent | 71cc5843006d1080313c739f46932d92e4282d8f (diff) | |
| parent | 101c935ffd4b3b55bcbaa36d97664f8630382545 (diff) | |
* Merged trunk, fixed conflicts
(bzr r2463.4.3)
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/unity-mt-grab-handles/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.cpp | 316 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.h | 16 |
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 ®ion) { - 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_; |
