SHARE
TWEET

Unity-5.18.0 unityshell.cpp

Duckcarer Mar 20th, 2013 44 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
  2. /* Compiz unity plugin
  3.  * unity.cpp
  4.  *
  5.  * Copyright (c) 2010-11 Canonical Ltd.
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License
  9.  * as published by the Free Software Foundation; either version 3
  10.  * of the License, or (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * Your own copyright notice would go above. You are free to choose whatever
  18.  * licence you want, just take note that some compiz code is GPL and you will
  19.  * not be able to re-use it if you want to use a different licence.
  20.  */
  21.  
  22. #include <NuxCore/Logger.h>
  23. #include <Nux/Nux.h>
  24. #include <Nux/HLayout.h>
  25. #include <Nux/BaseWindow.h>
  26. #include <Nux/WindowCompositor.h>
  27.  
  28. #include "IconRenderer.h"
  29. #include "Launcher.h"
  30. #include "LauncherIcon.h"
  31. #include "LauncherController.h"
  32. #include "GeisAdapter.h"
  33. #include "DevicesSettings.h"
  34. #include "PluginAdapter.h"
  35. #include "QuicklistManager.h"
  36. #include "StartupNotifyService.h"
  37. #include "Timer.h"
  38. #include "KeyboardUtil.h"
  39. #include "unityshell.h"
  40. #include "BackgroundEffectHelper.h"
  41.  
  42. #include <dbus/dbus.h>
  43. #include <dbus/dbus-glib.h>
  44. #include <glib/gi18n-lib.h>
  45. #include <gtk/gtk.h>
  46. #include <gdk/gdk.h>
  47. #include <gdk/gdkx.h>
  48. #include <libnotify/notify.h>
  49.  
  50. #include <sstream>
  51. #include <memory>
  52.  
  53. #include <core/atoms.h>
  54.  
  55. #include "unitya11y.h"
  56.  
  57. #include "UBusMessages.h"
  58. #include "UScreen.h"
  59.  
  60. #include "config.h"
  61.  
  62. /* FIXME: once we get a better method to add the toplevel windows to
  63.    the accessible root object, this include would not be required */
  64. #include "unity-util-accessible.h"
  65.  
  66. /* Set up vtable symbols */
  67. COMPIZ_PLUGIN_20090315(unityshell, unity::UnityPluginVTable);
  68.  
  69. namespace unity
  70. {
  71. using namespace launcher;
  72. using launcher::AbstractLauncherIcon;
  73. using launcher::Launcher;
  74. using ui::KeyboardUtil;
  75. using ui::LayoutWindow;
  76. using ui::LayoutWindowList;
  77. using util::Timer;
  78.  
  79. namespace
  80. {
  81.  
  82. nux::logging::Logger logger("unity.shell");
  83.  
  84. UnityScreen* uScreen = 0;
  85.  
  86. void reset_glib_logging();
  87. void configure_logging();
  88. void capture_g_log_calls(const gchar* log_domain,
  89.                          GLogLevelFlags log_level,
  90.                          const gchar* message,
  91.                          gpointer user_data);
  92. gboolean is_extension_supported(const gchar* extensions, const gchar* extension);
  93. gfloat get_opengl_version_f32(const gchar* version_string);
  94.  
  95. namespace local
  96. {
  97. // Tap duration in milliseconds.
  98. const int ALT_TAP_DURATION = 250;
  99. const unsigned int SCROLL_DOWN_BUTTON = 6;
  100. const unsigned int SCROLL_UP_BUTTON = 7;
  101. } // namespace local
  102. } // anon namespace
  103.  
  104. UnityScreen::UnityScreen(CompScreen* screen)
  105.   : BaseSwitchScreen (screen)
  106.   , PluginClassHandler <UnityScreen, CompScreen> (screen)
  107.   , screen(screen)
  108.   , cScreen(CompositeScreen::get(screen))
  109.   , gScreen(GLScreen::get(screen))
  110.   , debugger_(this)
  111.   , enable_shortcut_overlay_(true)
  112.   , needsRelayout(false)
  113.   , _in_paint(false)
  114.   , relayoutSourceId(0)
  115.   , _redraw_handle(0)
  116.   , newFocusedWindow(nullptr)
  117.   , doShellRepaint(false)
  118.   , didShellRepaint(false)
  119.   , allowWindowPaint(false)
  120.   , _key_nav_mode_requested(false)
  121.   , _last_output(nullptr)
  122. #ifndef USE_GLES
  123.   , _active_fbo (0)
  124. #endif
  125.   , grab_index_ (0)
  126.   , painting_tray_ (false)
  127.   , last_scroll_event_(0)
  128.   , hud_keypress_time_(0)
  129.   , panel_texture_has_changed_(true)
  130.   , paint_panel_(false)
  131.   , scale_just_activated_(false)
  132. {
  133.   Timer timer;
  134.   gfloat version;
  135.   gchar* extensions;
  136.   bool  failed = false;
  137.   configure_logging();
  138.   LOG_DEBUG(logger) << __PRETTY_FUNCTION__;
  139.   int (*old_handler)(Display*, XErrorEvent*);
  140.   old_handler = XSetErrorHandler(NULL);
  141.  
  142. #ifndef USE_GLES
  143.   /* Ensure OpenGL version is 1.4+. */
  144.   version = get_opengl_version_f32((const gchar*) glGetString(GL_VERSION));
  145.   if (version < 1.4f)
  146.   {
  147.     compLogMessage("unityshell", CompLogLevelError,
  148.                    "OpenGL 1.4+ not supported\n");
  149.     setFailed ();
  150.     failed = true;
  151.   }
  152.  
  153.   /* Ensure OpenGL extensions required by the Unity plugin are available. */
  154.   extensions = (gchar*) glGetString(GL_EXTENSIONS);
  155.   if (!is_extension_supported(extensions, "GL_ARB_vertex_program"))
  156.   {
  157.     compLogMessage("unityshell", CompLogLevelError,
  158.                    "GL_ARB_vertex_program not supported\n");
  159.     setFailed ();
  160.     failed = true;
  161.   }
  162.   if (!is_extension_supported(extensions, "GL_ARB_fragment_program"))
  163.   {
  164.     compLogMessage("unityshell", CompLogLevelError,
  165.                    "GL_ARB_fragment_program not supported\n");
  166.     setFailed ();
  167.     failed = true;
  168.   }
  169.   if (!is_extension_supported(extensions, "GL_ARB_vertex_buffer_object"))
  170.   {
  171.     compLogMessage("unityshell", CompLogLevelError,
  172.                    "GL_ARB_vertex_buffer_object not supported\n");
  173.     setFailed ();
  174.     failed = true;
  175.   }
  176.   if (!is_extension_supported(extensions, "GL_ARB_framebuffer_object"))
  177.   {
  178.     if (!is_extension_supported(extensions, "GL_EXT_framebuffer_object"))
  179.     {
  180.       compLogMessage("unityshell", CompLogLevelError,
  181.                      "GL_ARB_framebuffer_object or GL_EXT_framebuffer_object "
  182.                      "not supported\n");
  183.       setFailed();
  184.       failed = true;
  185.     }
  186.   }
  187.   if (!is_extension_supported(extensions, "GL_ARB_texture_non_power_of_two"))
  188.   {
  189.     if (!is_extension_supported(extensions, "GL_ARB_texture_rectangle"))
  190.     {
  191.       compLogMessage("unityshell", CompLogLevelError,
  192.                      "GL_ARB_texture_non_power_of_two or "
  193.                      "GL_ARB_texture_rectangle not supported\n");
  194.       setFailed ();
  195.       failed = true;
  196.     }
  197.   }
  198. #endif
  199.  
  200.   if (!failed)
  201.   {
  202.      notify_init("unityshell");
  203.  
  204.      dbus_g_thread_init();
  205.  
  206.      unity_a11y_preset_environment();
  207.  
  208.      XSetErrorHandler(old_handler);
  209.  
  210.      /* Wrap compiz interfaces */
  211.      ScreenInterface::setHandler(screen);
  212.      CompositeScreenInterface::setHandler(cScreen);
  213.      GLScreenInterface::setHandler(gScreen);
  214.  
  215. #ifdef USE_GLES
  216.      gScreen->glPaintCompositedOutputSetEnabled (this, true);
  217. #endif
  218.  
  219.      PluginAdapter::Initialize(screen);
  220.      WindowManager::SetDefault(PluginAdapter::Default());
  221.      AddChild(PluginAdapter::Default());
  222.  
  223.      StartupNotifyService::Default()->SetSnDisplay(screen->snDisplay(), screen->screenNum());
  224.  
  225.      nux::NuxInitialize(0);
  226. #ifndef USE_GLES
  227.      wt.reset(nux::CreateFromForeignWindow(cScreen->output(),
  228.                                            glXGetCurrentContext(),
  229.                                            &UnityScreen::initUnity,
  230.                                            this));
  231. #else
  232.      wt.reset(nux::CreateFromForeignWindow(cScreen->output(),
  233.                                            eglGetCurrentContext(),
  234.                                            &UnityScreen::initUnity,
  235.                                            this));
  236. #endif
  237.  
  238.      wt->RedrawRequested.connect(sigc::mem_fun(this, &UnityScreen::onRedrawRequested));
  239.  
  240.      unity_a11y_init(wt.get());
  241.  
  242.      /* i18n init */
  243.      bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
  244.      bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
  245.  
  246.      wt->Run(NULL);
  247.      uScreen = this;
  248.      _in_paint = false;
  249.  
  250. #ifndef USE_GLES
  251.     void *dlhand = dlopen ("libunityshell.so", RTLD_LAZY);
  252.  
  253.     if (dlhand)
  254.     {
  255.       dlerror ();
  256.       glXGetProcAddressP = (ScreenEffectFramebufferObject::GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
  257.       if (dlerror () != NULL)
  258.         glXGetProcAddressP = NULL;
  259.     }
  260.  
  261.      if (GL::fbo)
  262.      {
  263.        nux::Geometry geometry (0, 0, screen->width (), screen->height ());
  264.        uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
  265.        uScreen->_fbo->onScreenSizeChanged (geometry);
  266.      }
  267. #endif
  268.  
  269.      optionSetShowHudInitiate(boost::bind(&UnityScreen::ShowHudInitiate, this, _1, _2, _3));
  270.      optionSetShowHudTerminate(boost::bind(&UnityScreen::ShowHudTerminate, this, _1, _2, _3));
  271.      optionSetBackgroundColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  272.      optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  273.      optionSetBacklightModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  274.      optionSetRevealTriggerNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  275.      optionSetLaunchAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  276.      optionSetUrgentAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  277.      optionSetPanelOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  278.      optionSetPanelOpacityMaximizedToggleNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  279.      optionSetMenusFadeinNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  280.      optionSetMenusFadeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  281.      optionSetMenusDiscoveryDurationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  282.      optionSetMenusDiscoveryFadeinNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  283.      optionSetMenusDiscoveryFadeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  284.      optionSetLauncherOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  285.      optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  286.      optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  287.      optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  288.      optionSetDevicesOptionNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  289.      optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  290.      optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  291.      optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
  292.      optionSetShowLauncherTerminate(boost::bind(&UnityScreen::showLauncherKeyTerminate, this, _1, _2, _3));
  293.      optionSetKeyboardFocusInitiate(boost::bind(&UnityScreen::setKeyboardFocusKeyInitiate, this, _1, _2, _3));
  294.      //optionSetKeyboardFocusTerminate (boost::bind (&UnityScreen::setKeyboardFocusKeyTerminate, this, _1, _2, _3));
  295.      optionSetExecuteCommandInitiate(boost::bind(&UnityScreen::executeCommand, this, _1, _2, _3));
  296.      optionSetPanelFirstMenuInitiate(boost::bind(&UnityScreen::showPanelFirstMenuKeyInitiate, this, _1, _2, _3));
  297.      optionSetPanelFirstMenuTerminate(boost::bind(&UnityScreen::showPanelFirstMenuKeyTerminate, this, _1, _2, _3));
  298.      optionSetAutomaximizeValueNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  299.      optionSetAltTabTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  300.      optionSetAltTabBiasViewportNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  301.  
  302.      optionSetAltTabForwardAllInitiate(boost::bind(&UnityScreen::altTabForwardAllInitiate, this, _1, _2, _3));
  303.      optionSetAltTabForwardInitiate(boost::bind(&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
  304.      optionSetAltTabForwardTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
  305.      optionSetAltTabForwardAllTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
  306.      optionSetAltTabPrevAllInitiate(boost::bind(&UnityScreen::altTabPrevAllInitiate, this, _1, _2, _3));
  307.      optionSetAltTabPrevInitiate(boost::bind(&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
  308.  
  309.      optionSetAltTabDetailStartInitiate(boost::bind(&UnityScreen::altTabDetailStartInitiate, this, _1, _2, _3));
  310.      optionSetAltTabDetailStopInitiate(boost::bind(&UnityScreen::altTabDetailStopInitiate, this, _1, _2, _3));
  311.  
  312.      optionSetAltTabNextWindowInitiate(boost::bind(&UnityScreen::altTabNextWindowInitiate, this, _1, _2, _3));
  313.      optionSetAltTabNextWindowTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
  314.  
  315.      optionSetAltTabPrevWindowInitiate(boost::bind(&UnityScreen::altTabPrevWindowInitiate, this, _1, _2, _3));
  316.  
  317.      optionSetAltTabLeftInitiate(boost::bind (&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
  318.      optionSetAltTabRightInitiate([&](CompAction* action, CompAction::State state, CompOption::Vector& options) -> bool
  319.      {
  320.       if (switcher_controller_->Visible())
  321.       {
  322.         switcher_controller_->Next();
  323.         return true;
  324.       }
  325.       return false;
  326.      });
  327.  
  328.      optionSetLauncherSwitcherForwardInitiate(boost::bind(&UnityScreen::launcherSwitcherForwardInitiate, this, _1, _2, _3));
  329.      optionSetLauncherSwitcherPrevInitiate(boost::bind(&UnityScreen::launcherSwitcherPrevInitiate, this, _1, _2, _3));
  330.      optionSetLauncherSwitcherForwardTerminate(boost::bind(&UnityScreen::launcherSwitcherTerminate, this, _1, _2, _3));
  331.  
  332.      optionSetStopVelocityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  333.      optionSetRevealPressureNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  334.      optionSetEdgeResponsivenessNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  335.      optionSetOvercomePressureNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  336.      optionSetDecayRateNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  337.      optionSetShowMinimizedWindowsNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  338.  
  339.      optionSetNumLaunchersNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  340.      optionSetLauncherCaptureMouseNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
  341.  
  342.      ubus_manager_.RegisterInterest(UBUS_LAUNCHER_START_KEY_NAV,
  343.                    sigc::mem_fun(this, &UnityScreen::OnLauncherStartKeyNav));
  344.  
  345.      ubus_manager_.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWTICHER,
  346.                    sigc::mem_fun(this, &UnityScreen::OnLauncherStartKeyNav));
  347.  
  348.      ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_NAV,
  349.                    sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav));
  350.  
  351.      ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_SWTICHER,
  352.                    sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav));
  353.  
  354.      ubus_manager_.RegisterInterest(UBUS_SWITCHER_START,
  355.                    sigc::mem_fun(this, &UnityScreen::OnSwitcherStart));
  356.  
  357.      ubus_manager_.RegisterInterest(UBUS_SWITCHER_END,
  358.                    sigc::mem_fun(this, &UnityScreen::OnSwitcherEnd));
  359.  
  360.      g_idle_add_full (G_PRIORITY_DEFAULT, &UnityScreen::initPluginActions, this, NULL);
  361.      super_keypressed_ = false;
  362.  
  363.      geis_adapter_.Run();
  364.      gesture_engine_.reset(new GestureEngine(screen));
  365.  
  366.      CompString name(PKGDATADIR"/panel-shadow.png");
  367.      CompString pname("unityshell");
  368.      CompSize size(1, 20);
  369.      _shadow_texture = GLTexture::readImageToTexture(name, pname, size);
  370.  
  371.      BackgroundEffectHelper::updates_enabled = true;
  372.  
  373.      ubus_manager_.RegisterInterest(UBUS_OVERLAY_SHOWN, [&](GVariant * data)
  374.      {
  375.        unity::glib::String overlay_identity;
  376.        gboolean can_maximise = FALSE;
  377.        gint32 overlay_monitor = 0;
  378.        g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
  379.                     &overlay_identity, &can_maximise, &overlay_monitor);
  380.  
  381.        dash_monitor_ = overlay_monitor;
  382.  
  383.        RaiseInputWindows();
  384.      });
  385.  
  386.     Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default());;
  387.     XSelectInput(display, GDK_ROOT_WINDOW(), PropertyChangeMask);
  388.     LOG_INFO(logger) << "UnityScreen constructed: " << timer.ElapsedSeconds() << "s";
  389.   }
  390.  
  391.   panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged));
  392. }
  393.  
  394. UnityScreen::~UnityScreen()
  395. {
  396.   notify_uninit();
  397.  
  398.   unity_a11y_finalize();
  399.  
  400.   if (relayoutSourceId != 0)
  401.     g_source_remove(relayoutSourceId);
  402.  
  403.   if (_redraw_handle)
  404.     g_source_remove(_redraw_handle);
  405.  
  406.   ::unity::ui::IconRenderer::DestroyTextures();
  407.   QuicklistManager::Destroy();
  408.  
  409.   reset_glib_logging();
  410. }
  411.  
  412. void UnityScreen::initAltTabNextWindow()
  413. {
  414.   KeyboardUtil key_util(screen->dpy());
  415.   guint above_tab_keycode = key_util.GetKeycodeAboveKeySymbol (XStringToKeysym("Tab"));
  416.   KeySym above_tab_keysym = XkbKeycodeToKeysym (screen->dpy(), above_tab_keycode, 0, 0);
  417.  
  418.   if (above_tab_keysym != NoSymbol)
  419.   {
  420.     {
  421.       std::ostringstream sout;
  422.       sout << "<Alt>" << XKeysymToString(above_tab_keysym);
  423.  
  424.       screen->removeAction(&optionGetAltTabNextWindow());
  425.  
  426.       CompAction action = CompAction();
  427.       action.keyFromString(sout.str());
  428.       action.setState (CompAction::StateInitKey | CompAction::StateAutoGrab);
  429.       mOptions[UnityshellOptions::AltTabNextWindow].value().set (action);
  430.       screen->addAction (&mOptions[UnityshellOptions::AltTabNextWindow].value ().action ());
  431.  
  432.       optionSetAltTabNextWindowInitiate(boost::bind(&UnityScreen::altTabNextWindowInitiate, this, _1, _2, _3));
  433.       optionSetAltTabNextWindowTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
  434.     }
  435.     {
  436.       std::ostringstream sout;
  437.       sout << "<Alt><Shift>" << XKeysymToString(above_tab_keysym);
  438.  
  439.       screen->removeAction(&optionGetAltTabPrevWindow());
  440.  
  441.       CompAction action = CompAction();
  442.       action.keyFromString(sout.str());
  443.       action.setState (CompAction::StateInitKey | CompAction::StateAutoGrab);
  444.       mOptions[UnityshellOptions::AltTabPrevWindow].value().set (action);
  445.       screen->addAction (&mOptions[UnityshellOptions::AltTabPrevWindow].value ().action ());
  446.  
  447.       optionSetAltTabPrevWindowInitiate(boost::bind(&UnityScreen::altTabPrevWindowInitiate, this, _1, _2, _3));
  448.     }
  449.   }
  450.   else
  451.   {
  452.     printf ("Could not find key above tab!\n");
  453.   }
  454.  
  455. }
  456.  
  457. void UnityScreen::EnsureSuperKeybindings()
  458. {
  459.   for (auto action : _shortcut_actions)
  460.     screen->removeAction(action.get());
  461.  
  462.   _shortcut_actions.clear ();
  463.  
  464.   for (auto shortcut : launcher_controller_->GetAllShortcuts())
  465.   {
  466.     CreateSuperNewAction(shortcut, impl::ActionModifiers::NONE);
  467.     CreateSuperNewAction(shortcut, impl::ActionModifiers::USE_NUMPAD);
  468.     CreateSuperNewAction(shortcut, impl::ActionModifiers::USE_SHIFT);
  469.   }
  470.  
  471.   for (auto shortcut : dash_controller_->GetAllShortcuts())
  472.     CreateSuperNewAction(shortcut, impl::ActionModifiers::NONE);
  473. }
  474.  
  475. void UnityScreen::CreateSuperNewAction(char shortcut, impl::ActionModifiers flag)
  476. {
  477.     CompActionPtr action(new CompAction());
  478.     const std::string key(optionGetShowLauncher().keyToString());
  479.  
  480.     CompAction::KeyBinding binding;
  481.     binding.fromString(impl::CreateActionString(key, shortcut, flag));
  482.  
  483.     action->setKey(binding);
  484.  
  485.     screen->addAction(action.get());
  486.     _shortcut_actions.push_back(action);
  487. }
  488.  
  489. void UnityScreen::nuxPrologue()
  490. {
  491. #ifndef USE_GLES
  492.   /* Vertex lighting isn't used in Unity, we disable that state as it could have
  493.    * been leaked by another plugin. That should theoretically be switched off
  494.    * right after PushAttrib since ENABLE_BIT is meant to restore the LIGHTING
  495.    * bit, but we do that here in order to workaround a bug (?) in the NVIDIA
  496.    * drivers (lp:703140). */
  497.   glDisable(GL_LIGHTING);
  498.  
  499.   /* reset matrices */
  500.   glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT |
  501.                GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
  502.  
  503.   glMatrixMode(GL_PROJECTION);
  504.   glPushMatrix();
  505.  
  506.   glMatrixMode(GL_MODELVIEW);
  507.   glPushMatrix();
  508.  
  509.   /* This is needed to Fix a crash in glDrawArrays with the NVIDIA driver
  510.    * see bugs #1031554 and #982626.
  511.    * The NVIDIA driver looks to see if the legacy GL_VERTEX_ARRAY,
  512.    * GL_TEXTURE_COORDINATES_ARRAY and other such client states are enabled
  513.    * first before checking if a vertex buffer is bound and will prefer the
  514.    * client buffers over the the vertex buffer object. */
  515.   glDisableClientState(GL_VERTEX_ARRAY);
  516.   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  517. #endif
  518.  
  519.   glGetError();
  520. }
  521.  
  522. void UnityScreen::nuxEpilogue()
  523. {
  524. #ifndef USE_GLES
  525.   (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo);
  526.  
  527.   glMatrixMode(GL_PROJECTION);
  528.   glLoadIdentity();
  529.   glMatrixMode(GL_MODELVIEW);
  530.   glLoadIdentity();
  531.   glDepthRange(0, 1);
  532.   glViewport(-1, -1, 2, 2);
  533.   glRasterPos2f(0, 0);
  534.  
  535.   gScreen->resetRasterPos();
  536.  
  537.   glMatrixMode(GL_PROJECTION);
  538.   glPopMatrix();
  539.   glMatrixMode(GL_MODELVIEW);
  540.   glPopMatrix();
  541.  
  542.   glDrawBuffer(GL_BACK);
  543.   glReadBuffer(GL_BACK);
  544.  
  545.   glPopAttrib();
  546.  
  547.   /* Re-enable the client states that have been disabled in nuxPrologue , for
  548.    * NVIDIA compatibility reasons */
  549.   glEnableClientState(GL_VERTEX_ARRAY);
  550.   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  551. #else
  552.   glDepthRangef(0, 1);
  553.   //glViewport(-1, -1, 2, 2);
  554.   gScreen->resetRasterPos();
  555. #endif
  556.  
  557.   glDisable(GL_SCISSOR_TEST);
  558. }
  559.  
  560. void UnityScreen::setPanelShadowMatrix(const GLMatrix& matrix)
  561. {
  562.   panel_shadow_matrix_ = matrix;
  563. }
  564.  
  565. void UnityScreen::paintPanelShadow(const GLMatrix& matrix)
  566. {
  567. #ifndef USE_GLES
  568.   if (relayoutSourceId > 0)
  569.     return;
  570.  
  571.   if (PluginAdapter::Default()->IsExpoActive())
  572.     return;
  573.  
  574.   CompOutput* output = _last_output;
  575.   float vc[4];
  576.   float h = 20.0f;
  577.   float w = 1.0f;
  578.   float panel_h = panel_style_.panel_height;
  579.  
  580.   float x1 = output->x();
  581.   float y1 = output->y() + panel_h;
  582.   float x2 = x1 + output->width();
  583.   float y2 = y1 + h;
  584.  
  585.   glPushMatrix ();
  586.   glLoadMatrixf (panel_shadow_matrix_.getMatrix ());
  587.  
  588.   vc[0] = x1;
  589.   vc[1] = x2;
  590.   vc[2] = y1;
  591.   vc[3] = y2;
  592.  
  593.   // compiz doesn't use the same method of tracking monitors as our toolkit
  594.   // we need to make sure we properly associate with the right monitor
  595.   int current_monitor = -1;
  596.   auto monitors = UScreen::GetDefault()->GetMonitors();
  597.   int i = 0;
  598.   for (auto monitor : monitors)
  599.   {
  600.     if (monitor.x == output->x() && monitor.y == output->y())
  601.     {
  602.       current_monitor = i;
  603.       break;
  604.     }
  605.     i++;
  606.   }
  607.  
  608.   if (!(launcher_controller_->IsOverlayOpen() && current_monitor == dash_monitor_)
  609.       && panel_controller_->opacity() > 0.0f)
  610.   {
  611.     foreach(GLTexture * tex, _shadow_texture)
  612.     {
  613.       glEnable(GL_BLEND);
  614.       glColor4f(1.0f, 1.0f, 1.0f, panel_controller_->opacity());
  615.       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  616.  
  617.       GL::activeTexture(GL_TEXTURE0_ARB);
  618.       tex->enable(GLTexture::Fast);
  619.  
  620.       glTexParameteri(tex->target(), GL_TEXTURE_WRAP_S, GL_REPEAT);
  621.  
  622.       glBegin(GL_QUADS);
  623.       {
  624.         glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), 0));
  625.         glVertex2f(vc[0], vc[2]);
  626.  
  627.         glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), h));
  628.         glVertex2f(vc[0], vc[3]);
  629.  
  630.         glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), h));
  631.         glVertex2f(vc[1], vc[3]);
  632.  
  633.         glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), 0));
  634.         glVertex2f(vc[1], vc[2]);
  635.       }
  636.       glEnd();
  637.  
  638.       tex->disable();
  639.       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  640.       glDisable(GL_BLEND);
  641.     }
  642.   }
  643.   glPopMatrix();
  644. #else
  645. #warning Panel shadow not properly implemented for GLES2
  646.   return;
  647.  
  648.   if (relayoutSourceId > 0)
  649.     return;
  650.  
  651.   if (PluginAdapter::Default()->IsExpoActive())
  652.     return;
  653.  
  654.   nuxPrologue();
  655.  
  656.   CompOutput* output = _last_output;
  657.   float vc[4];
  658.   float h = 20.0f;
  659.   float w = 1.0f;
  660.   float panel_h = static_cast<float>(panel_style_.panel_height);
  661.  
  662.   float x1 = output->x();
  663.   float y1 = output->y() + panel_h;
  664.   float x2 = x1 + output->width();
  665.   float y2 = y1 + h;
  666.  
  667.   vc[0] = x1;
  668.   vc[1] = x2;
  669.   vc[2] = y1;
  670.   vc[3] = y2;
  671.  
  672.   // compiz doesn't use the same method of tracking monitors as our toolkit
  673.   // we need to make sure we properly associate with the right monitor
  674.   int current_monitor = -1;
  675.   auto monitors = UScreen::GetDefault()->GetMonitors();
  676.   int i = 0;
  677.   for (auto monitor : monitors)
  678.   {
  679.     if (monitor.x == output->x() && monitor.y == output->y())
  680.     {
  681.       current_monitor = i;
  682.       break;
  683.     }
  684.     i++;
  685.   }
  686.  
  687.   if (!(launcher_controller_->IsOverlayOpen() && current_monitor == dash_monitor_)
  688.       && panel_controller_->opacity() > 0.0f)
  689.   {
  690.     foreach(GLTexture * tex, _shadow_texture)
  691.     {
  692.       std::vector<GLfloat>  vertexData;
  693.       std::vector<GLfloat>  textureData;
  694.       std::vector<GLushort> colorData;
  695.       GLVertexBuffer       *streamingBuffer = GLVertexBuffer::streamingBuffer();
  696.       bool                  wasBlend = glIsEnabled(GL_BLEND);
  697.  
  698.       if (!wasBlend)
  699.         glEnable(GL_BLEND);
  700.  
  701.       GL::activeTexture(GL_TEXTURE0);
  702.       tex->enable(GLTexture::Fast);
  703.  
  704.       glTexParameteri(tex->target(), GL_TEXTURE_WRAP_S, GL_REPEAT);
  705.  
  706.       colorData = { 0xFFFF, 0xFFFF, 0xFFFF,
  707.                     (GLushort)(panel_controller_->opacity() * 0xFFFF)
  708.                   };
  709.  
  710.       vertexData = {
  711.         vc[0], vc[2], 0,
  712.         vc[0], vc[3], 0,
  713.         vc[1], vc[2], 0,
  714.         vc[1], vc[3], 0,
  715.       };
  716.  
  717.       textureData = {
  718.         COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), 0),
  719.         COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), h),
  720.         COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), 0),
  721.         COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), h),
  722.       };
  723.  
  724.       streamingBuffer->begin(GL_TRIANGLE_STRIP);
  725.  
  726.       streamingBuffer->addColors(1, &colorData[0]);
  727.       streamingBuffer->addVertices(4, &vertexData[0]);
  728.       streamingBuffer->addTexCoords(0, 4, &textureData[0]);
  729.  
  730.       streamingBuffer->end();
  731.       streamingBuffer->render(matrix);
  732.  
  733.       tex->disable();
  734.       if (!wasBlend)
  735.         glDisable(GL_BLEND);
  736.     }
  737.   }
  738.   nuxEpilogue();
  739. #endif
  740. }
  741.  
  742. void
  743. UnityWindow::updateIconPos (int   &wx,
  744.                             int   &wy,
  745.                             int   x,
  746.                             int   y,
  747.                             float width,
  748.                             float height)
  749. {
  750.   wx = x + (last_bound.width - width) / 2;
  751.   wy = y + (last_bound.height - height) / 2;
  752. }
  753.  
  754. void
  755. UnityScreen::OnPanelStyleChanged()
  756. {
  757.   panel_texture_has_changed_ = true;
  758. }
  759.  
  760. #ifdef USE_GLES
  761. void UnityScreen::paintDisplay()
  762. #else
  763. void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask)
  764. #endif
  765. {
  766.   CompOutput *output = _last_output;
  767.  
  768. #ifndef USE_GLES
  769.   bool was_bound = _fbo->bound ();
  770.  
  771.   if (nux::GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath())
  772.   {
  773.     if (was_bound && launcher_controller_->IsOverlayOpen() && paint_panel_)
  774.     {
  775.       if (panel_texture_has_changed_ || !panel_texture_.IsValid())
  776.       {
  777.         panel_texture_.Release();
  778.  
  779.         nux::NBitmapData* bitmap = panel::Style::Instance().GetBackground(screen->width (), screen->height(), 1.0f);
  780.         nux::BaseTexture* texture2D = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
  781.         if (bitmap && texture2D)
  782.         {
  783.           texture2D->Update(bitmap);
  784.           panel_texture_ = texture2D->GetDeviceTexture();
  785.           texture2D->UnReference();
  786.           delete bitmap;
  787.         }
  788.         panel_texture_has_changed_ = false;
  789.       }
  790.  
  791.       if (panel_texture_.IsValid())
  792.       {
  793.         nux::GetGraphicsDisplay()->GetGraphicsEngine()->ResetModelViewMatrixStack();
  794.         nux::GetGraphicsDisplay()->GetGraphicsEngine()->Push2DTranslationModelViewMatrix(0.0f, 0.0f, 0.0f);
  795.         nux::GetGraphicsDisplay()->GetGraphicsEngine()->ResetProjectionMatrix();
  796.         nux::GetGraphicsDisplay()->GetGraphicsEngine()->SetOrthographicProjectionMatrix(screen->width (), screen->height());
  797.  
  798.         nux::TexCoordXForm texxform;
  799.         int panel_height = panel_style_.panel_height;
  800.         nux::GetGraphicsDisplay()->GetGraphicsEngine()->QRP_GLSL_1Tex(0, 0, screen->width (), panel_height, panel_texture_, texxform, nux::color::White);
  801.       }
  802.     }
  803.   }
  804.  
  805.   _fbo->unbind ();
  806.  
  807.   /* Draw the bit of the relevant framebuffer for each output */
  808.  
  809.   if (was_bound)
  810.   {
  811.     GLMatrix sTransform;
  812.     sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
  813.     glPushMatrix ();
  814.     glLoadMatrixf (sTransform.getMatrix ());
  815.     _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
  816.     glPopMatrix ();
  817.   }
  818.  
  819.   nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture =
  820.       nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),
  821.                                                                        screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
  822. #else
  823.   nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
  824.     nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (),
  825.       output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
  826. #endif
  827.  
  828.   nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
  829.  
  830.   nux::Geometry geo = nux::Geometry (0, 0, screen->width (), screen->height ());
  831.   nux::Geometry oGeo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
  832.   BackgroundEffectHelper::monitor_rect_ = geo;
  833.  
  834. #ifdef USE_GLES
  835.   GLint fboID;
  836.   // Nux renders to the referenceFramebuffer when it's embedded.
  837.   glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fboID);
  838.   wt->GetWindowCompositor().SetReferenceFramebuffer(fboID, geo);
  839. #endif
  840.  
  841.   nuxPrologue();
  842.   _in_paint = true;
  843.   wt->RenderInterfaceFromForeignCmd (&oGeo);
  844.   _in_paint = false;
  845.   nuxEpilogue();
  846.  
  847.   for (Window tray_xid : panel_controller_->GetTrayXids())
  848.   {
  849.     if (tray_xid && !allowWindowPaint)
  850.     {
  851.       CompWindow *tray = screen->findWindow (tray_xid);
  852.  
  853.       if (tray)
  854.       {
  855.         GLMatrix oTransform;
  856.         UnityWindow  *uTrayWindow = UnityWindow::get (tray);
  857. #ifndef USE_GLES
  858.         GLFragment::Attrib attrib (uTrayWindow->gWindow->lastPaintAttrib());
  859. #else
  860.         GLWindowPaintAttrib attrib (uTrayWindow->gWindow->lastPaintAttrib());
  861. #endif
  862.         unsigned int oldGlAddGeometryIndex = uTrayWindow->gWindow->glAddGeometryGetCurrentIndex ();
  863.         unsigned int oldGlDrawIndex = uTrayWindow->gWindow->glDrawGetCurrentIndex ();
  864. #ifndef USE_GLES
  865.         unsigned int oldGlDrawGeometryIndex = uTrayWindow->gWindow->glDrawGeometryGetCurrentIndex ();
  866. #endif
  867.  
  868. #ifndef USE_GLES
  869.         attrib.setOpacity (OPAQUE);
  870.         attrib.setBrightness (BRIGHT);
  871.         attrib.setSaturation (COLOR);
  872. #else
  873.         attrib.opacity = OPAQUE;
  874.         attrib.brightness = BRIGHT;
  875.         attrib.saturation = COLOR;
  876. #endif
  877.  
  878.         oTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
  879.  
  880. #ifndef USE_GLES
  881.         glPushMatrix ();
  882.         glLoadMatrixf (oTransform.getMatrix ());
  883. #endif
  884.  
  885.         painting_tray_ = true;
  886.  
  887.         /* force the use of the core functions */
  888.         uTrayWindow->gWindow->glDrawSetCurrentIndex (MAXSHORT);
  889.         uTrayWindow->gWindow->glAddGeometrySetCurrentIndex ( MAXSHORT);
  890. #ifndef USE_GLES
  891.         uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (MAXSHORT);
  892. #endif
  893.         uTrayWindow->gWindow->glDraw (oTransform, attrib, infiniteRegion,
  894.                PAINT_WINDOW_TRANSFORMED_MASK |
  895.                PAINT_WINDOW_BLEND_MASK |
  896.                PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
  897. #ifndef USE_GLES
  898.         uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (oldGlDrawGeometryIndex);
  899. #endif
  900.         uTrayWindow->gWindow->glAddGeometrySetCurrentIndex (oldGlAddGeometryIndex);
  901.         uTrayWindow->gWindow->glDrawSetCurrentIndex (oldGlDrawIndex);
  902.         painting_tray_ = false;
  903.  
  904. #ifndef USE_GLES
  905.         glPopMatrix ();
  906. #endif
  907.       }
  908.     }
  909.   }
  910.  
  911.  if (switcher_controller_->Visible ())
  912.   {
  913.     LayoutWindowList targets = switcher_controller_->ExternalRenderTargets ();
  914.  
  915.     for (LayoutWindow::Ptr target : targets)
  916.     {
  917.       CompWindow* window = screen->findWindow(target->xid);
  918.       if (window)
  919.       {
  920.         UnityWindow *unity_window = UnityWindow::get (window);
  921.  
  922.         unity_window->paintThumbnail (target->result, target->alpha);
  923.       }
  924.     }
  925.   }
  926.  
  927.   doShellRepaint = false;
  928.   didShellRepaint = true;
  929. }
  930.  
  931. bool UnityScreen::forcePaintOnTop ()
  932. {
  933.     return !allowWindowPaint ||
  934.       ((switcher_controller_->Visible() ||
  935.         PluginAdapter::Default()->IsExpoActive())
  936.        && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));
  937. }
  938.  
  939. void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha)
  940. {
  941.   GLMatrix matrix;
  942.   matrix.toScreenSpace (UnityScreen::get (screen)->_last_output, -DEFAULT_Z_CAMERA);
  943.  
  944.   nux::Geometry geo = bounding;
  945.   last_bound = geo;
  946.  
  947.   GLWindowPaintAttrib attrib = gWindow->lastPaintAttrib ();
  948.   attrib.opacity = (GLushort) (alpha * G_MAXUSHORT);
  949.  
  950.   paintThumb (attrib,
  951.               matrix,
  952.               0,
  953.               geo.x,
  954.               geo.y,
  955.               geo.width,
  956.               geo.height,
  957.               geo.width,
  958.               geo.height);
  959. }
  960.  
  961. void UnityScreen::EnableCancelAction(CancelActionTarget target, bool enabled, int modifiers)
  962. {
  963.   if (enabled)
  964.   {
  965.     /* Create a new keybinding for the Escape key and the current modifiers,
  966.      * compiz will take of the ref-counting of the repeated actions */
  967.     KeyCode escape = XKeysymToKeycode(screen->dpy(), XStringToKeysym("Escape"));
  968.     CompAction::KeyBinding binding(escape, modifiers);
  969.  
  970.     CompActionPtr &escape_action = _escape_actions[target];
  971.     escape_action = CompActionPtr(new CompAction());
  972.     escape_action->setKey(binding);
  973.  
  974.     screen->addAction(escape_action.get());
  975.   }
  976.   else if (!enabled && _escape_actions[target].get())
  977.   {
  978.     screen->removeAction(_escape_actions[target].get());
  979.     _escape_actions.erase(target);
  980.   }
  981. }
  982.  
  983. void UnityScreen::enterShowDesktopMode ()
  984. {
  985.   for (CompWindow *w : screen->windows ())
  986.   {
  987.     UnityWindow *uw = UnityWindow::get (w);
  988.  
  989.     if (ShowdesktopHandler::ShouldHide (static_cast <ShowdesktopHandlerWindowInterface *> (uw)))
  990.     {
  991.       UnityWindow::get (w)->enterShowDesktop ();
  992.       // the animation plugin does strange things here ...
  993.       // if this notification is sent
  994.       // w->windowNotify (CompWindowNotifyEnterShowDesktopMode);
  995.     }
  996.     if (w->type() & CompWindowTypeDesktopMask)
  997.       w->moveInputFocusTo();
  998.   }
  999.  
  1000.   PluginAdapter::Default()->OnShowDesktop();
  1001.  
  1002.   /* Disable the focus handler as we will report that
  1003.    * minimized windows can be focused which will
  1004.    * allow them to enter showdesktop mode. That's
  1005.    * no good */
  1006.   for (CompWindow *w : screen->windows ())
  1007.   {
  1008.     UnityWindow *uw = UnityWindow::get (w);
  1009.     w->focusSetEnabled (uw, false);
  1010.   }
  1011.  
  1012.   screen->enterShowDesktopMode ();
  1013.  
  1014.   for (CompWindow *w : screen->windows ())
  1015.   {
  1016.     UnityWindow *uw = UnityWindow::get (w);
  1017.     w->focusSetEnabled (uw, true);
  1018.   }
  1019. }
  1020.  
  1021. void UnityScreen::leaveShowDesktopMode (CompWindow *w)
  1022. {
  1023.   /* Where a window is inhibiting, only allow the window
  1024.    * that is inhibiting the leave show desktop to actually
  1025.    * fade in again - all other windows should remain faded out */
  1026.   if (!ShowdesktopHandler::InhibitingXid ())
  1027.   {
  1028.     for (CompWindow *cw : screen->windows ())
  1029.     {
  1030.       if (cw->inShowDesktopMode ())
  1031.       {
  1032.         UnityWindow::get (cw)->leaveShowDesktop ();
  1033.         // the animation plugin does strange things here ...
  1034.         // if this notification is sent
  1035.         //cw->windowNotify (CompWindowNotifyLeaveShowDesktopMode);
  1036.       }
  1037.     }
  1038.  
  1039.     PluginAdapter::Default()->OnLeaveDesktop();
  1040.  
  1041.     screen->leaveShowDesktopMode (w);
  1042.   }
  1043.   else
  1044.   {
  1045.     CompWindow *cw = screen->findWindow (ShowdesktopHandler::InhibitingXid ());
  1046.     if (cw)
  1047.     {
  1048.       if (cw->inShowDesktopMode ())
  1049.       {
  1050.         UnityWindow::get (cw)->leaveShowDesktop ();
  1051.       }
  1052.     }
  1053.   }
  1054. }
  1055.  
  1056. void UnityWindow::enterShowDesktop ()
  1057. {
  1058.   if (!mShowdesktopHandler)
  1059.     mShowdesktopHandler = new ShowdesktopHandler (static_cast <ShowdesktopHandlerWindowInterface *> (this),
  1060.                                                   static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (this));
  1061.  
  1062.   window->setShowDesktopMode (true);
  1063.   mShowdesktopHandler->FadeOut ();
  1064. }
  1065.  
  1066. void UnityWindow::leaveShowDesktop ()
  1067. {
  1068.   if (mShowdesktopHandler)
  1069.   {
  1070.     mShowdesktopHandler->FadeIn ();
  1071.     window->setShowDesktopMode (false);
  1072.   }
  1073. }
  1074.  
  1075. void UnityWindow::activate ()
  1076. {
  1077.   ShowdesktopHandler::InhibitLeaveShowdesktopMode (window->id ());
  1078.   window->activate ();
  1079.   ShowdesktopHandler::AllowLeaveShowdesktopMode (window->id ());
  1080. }
  1081.  
  1082. void UnityWindow::DoEnableFocus ()
  1083. {
  1084.   window->focusSetEnabled (this, true);
  1085. }
  1086.  
  1087. void UnityWindow::DoDisableFocus ()
  1088. {
  1089.   window->focusSetEnabled (this, false);
  1090. }
  1091.  
  1092. bool UnityWindow::IsOverrideRedirect ()
  1093. {
  1094.   return window->overrideRedirect ();
  1095. }
  1096.  
  1097. bool UnityWindow::IsManaged ()
  1098. {
  1099.   return window->managed ();
  1100. }
  1101.  
  1102. bool UnityWindow::IsGrabbed ()
  1103. {
  1104.   return window->grabbed ();
  1105. }
  1106.  
  1107. bool UnityWindow::IsDesktopOrDock ()
  1108. {
  1109.   return (window->type () & (CompWindowTypeDesktopMask | CompWindowTypeDockMask));
  1110. }
  1111.  
  1112. bool UnityWindow::IsSkipTaskbarOrPager ()
  1113. {
  1114.   return (window->state () & (CompWindowStateSkipTaskbarMask | CompWindowStateSkipPagerMask));
  1115. }
  1116.  
  1117. bool UnityWindow::IsInShowdesktopMode ()
  1118. {
  1119.   return window->inShowDesktopMode ();
  1120. }
  1121.  
  1122. bool UnityWindow::IsHidden ()
  1123. {
  1124.   return window->state () & CompWindowStateHiddenMask;
  1125. }
  1126.  
  1127. bool UnityWindow::IsShaded ()
  1128. {
  1129.   return window->shaded ();
  1130. }
  1131.  
  1132. bool UnityWindow::IsMinimized ()
  1133. {
  1134.   return window->minimized ();
  1135. }
  1136.  
  1137. void UnityWindow::DoOverrideFrameRegion (CompRegion &region)
  1138. {
  1139.   unsigned int oldUpdateFrameRegionIndex = window->updateFrameRegionGetCurrentIndex ();
  1140.  
  1141.   window->updateFrameRegionSetCurrentIndex (MAXSHORT);
  1142.   window->updateFrameRegion (region);
  1143.   window->updateFrameRegionSetCurrentIndex (oldUpdateFrameRegionIndex);
  1144. }
  1145.  
  1146. void UnityWindow::DoHide ()
  1147. {
  1148.   window->changeState (window->state () | CompWindowStateHiddenMask);
  1149. }
  1150.  
  1151. void UnityWindow::DoNotifyHidden ()
  1152. {
  1153.   window->windowNotify (CompWindowNotifyHide);
  1154. }
  1155.  
  1156. void UnityWindow::DoShow ()
  1157. {
  1158.   window->changeState (window->state () & ~(CompWindowStateHiddenMask));
  1159. }
  1160.  
  1161. void UnityWindow::DoNotifyShown ()
  1162. {
  1163.   window->windowNotify (CompWindowNotifyShow);
  1164. }
  1165.  
  1166. void UnityWindow::DoMoveFocusAway ()
  1167. {
  1168.   window->moveInputFocusToOtherWindow ();
  1169. }
  1170.  
  1171. ShowdesktopHandlerWindowInterface::PostPaintAction UnityWindow::DoHandleAnimations (unsigned int ms)
  1172. {
  1173.   ShowdesktopHandlerWindowInterface::PostPaintAction action = ShowdesktopHandlerWindowInterface::PostPaintAction::Wait;
  1174.  
  1175.   if (mShowdesktopHandler)
  1176.     action = mShowdesktopHandler->Animate (ms);
  1177.  
  1178.   return action;
  1179. }
  1180.  
  1181. void UnityWindow::DoAddDamage ()
  1182. {
  1183.   cWindow->addDamage ();
  1184. }
  1185.  
  1186. void UnityWindow::DoDeleteHandler ()
  1187. {
  1188.   delete mShowdesktopHandler;
  1189.   mShowdesktopHandler = NULL;
  1190.  
  1191.   window->updateFrameRegion ();
  1192. }
  1193.  
  1194. compiz::WindowInputRemoverLock::Ptr
  1195. UnityWindow::GetInputRemover ()
  1196. {
  1197.   if (!input_remover_.expired ())
  1198.     return input_remover_.lock ();
  1199.  
  1200.   compiz::WindowInputRemoverLock::Ptr ret (new compiz::WindowInputRemoverLock (new compiz::WindowInputRemover (screen->dpy (), window->id ())));
  1201.   input_remover_ = ret;
  1202.   return ret;
  1203. }
  1204.  
  1205. unsigned int
  1206. UnityWindow::GetNoCoreInstanceMask ()
  1207. {
  1208.   return PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
  1209. }
  1210.  
  1211. void UnityWindow::handleEvent (XEvent *event)
  1212. {
  1213.   if (screen->XShape () &&
  1214.       event->type == screen->shapeEvent () + ShapeNotify &&
  1215.       !event->xany.send_event)
  1216.   {
  1217.     if (mShowdesktopHandler)
  1218.       mShowdesktopHandler->HandleShapeEvent ();
  1219.   }
  1220. }
  1221.  
  1222. bool UnityScreen::shellCouldBeHidden(CompOutput const& output)
  1223. {
  1224.   std::vector<Window> const& nuxwins(nux::XInputWindow::NativeHandleList());
  1225.  
  1226.   // Loop through windows from front to back
  1227.   CompWindowList const& wins = screen->windows();
  1228.   for ( CompWindowList::const_reverse_iterator r = wins.rbegin()
  1229.       ; r != wins.rend()
  1230.       ; r++
  1231.       )
  1232.   {
  1233.     CompWindow* w = *r;
  1234.  
  1235.     /*
  1236.      * The shell is hidden if there exists any window that fully covers
  1237.      * the output and is in front of all Nux windows on that output.
  1238.      */
  1239.     if (w->isMapped() &&
  1240.         !(w->state () & CompWindowStateHiddenMask) &&
  1241.         w->geometry().contains(output))
  1242.     {
  1243.       return true;
  1244.     }
  1245.     else
  1246.     {
  1247.       for (Window n : nuxwins)
  1248.       {
  1249.         if (w->id() == n && output.intersects(w->geometry()))
  1250.           return false;
  1251.       }
  1252.     }
  1253.   }
  1254.  
  1255.   return false;
  1256. }
  1257.  
  1258. /* called whenever we need to repaint parts of the screen */
  1259. bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
  1260.                                 const GLMatrix& transform,
  1261.                                 const CompRegion& region,
  1262.                                 CompOutput* output,
  1263.                                 unsigned int mask)
  1264. {
  1265.   bool ret;
  1266.  
  1267.   /*
  1268.    * Very important!
  1269.    * Don't waste GPU and CPU rendering the shell on every frame if you don't
  1270.    * need to. Doing so on every frame causes Nux to hog the GPU and slow down
  1271.    * ALL rendering. (LP: #988079)
  1272.    */
  1273.   bool force = forcePaintOnTop();
  1274.   doShellRepaint = force ||
  1275.                    ( !region.isEmpty() &&
  1276.                      ( !wt->GetDrawList().empty() ||
  1277.                        (mask & PAINT_SCREEN_FULL_MASK)
  1278.                      )
  1279.                    );
  1280.  
  1281.   allowWindowPaint = true;
  1282.   _last_output = output;
  1283.   paint_panel_ = false;
  1284.  
  1285. #ifndef USE_GLES
  1286.   /* bind the framebuffer here
  1287.    * - it will be unbound and flushed
  1288.    *   to the backbuffer when some
  1289.    *   plugin requests to draw a
  1290.    *   a transformed screen or when
  1291.    *   we have finished this draw cycle.
  1292.    *   once an fbo is bound any further
  1293.    *   attempts to bind it will only increment
  1294.    *   its bind reference so make sure that
  1295.    *   you always unbind as much as you bind
  1296.    *
  1297.    * But NOTE: It is only safe to bind the FBO if !shellCouldBeHidden.
  1298.    *           Otherwise it's possible painting won't occur and that would
  1299.    *           confuse the state of the FBO.
  1300.    */
  1301.   if (doShellRepaint && !shellCouldBeHidden(*output))
  1302.     _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
  1303. #endif
  1304.  
  1305.   // CompRegion has no clear() method. So this is the fastest alternative.
  1306.   fullscreenRegion = CompRegion();
  1307.   nuxRegion = CompRegion();
  1308.  
  1309.   /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
  1310.   ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
  1311.  
  1312. #ifndef USE_GLES
  1313.   if (doShellRepaint && !force && fullscreenRegion.contains(*output))
  1314.     doShellRepaint = false;
  1315.  
  1316.   if (doShellRepaint)
  1317.     paintDisplay(region, transform, mask);
  1318. #endif
  1319.  
  1320.   return ret;
  1321. }
  1322.  
  1323. #ifdef USE_GLES
  1324. void UnityScreen::glPaintCompositedOutput (const CompRegion &region,
  1325.                                            ::GLFramebufferObject *fbo,
  1326.                                            unsigned int        mask)
  1327. {
  1328.   bool useFbo = false;
  1329.  
  1330.   if (doShellRepaint)
  1331.   {
  1332.     oldFbo = fbo->bind ();
  1333.     useFbo = fbo->checkStatus () && fbo->tex ();
  1334.     if (!useFbo) {
  1335.         printf ("bailing from UnityScreen::glPaintCompositedOutput");
  1336.         ::GLFramebufferObject::rebind (oldFbo);
  1337.         return;
  1338.     }
  1339.     paintDisplay();
  1340.     ::GLFramebufferObject::rebind (oldFbo);
  1341.   }
  1342.  
  1343.   gScreen->glPaintCompositedOutput(region, fbo, mask);
  1344. }
  1345. #endif
  1346.  
  1347. /* called whenever a plugin needs to paint the entire scene
  1348.  * transformed */
  1349.  
  1350. void UnityScreen::glPaintTransformedOutput(const GLScreenPaintAttrib& attrib,
  1351.                                            const GLMatrix& transform,
  1352.                                            const CompRegion& region,
  1353.                                            CompOutput* output,
  1354.                                            unsigned int mask)
  1355. {
  1356.   allowWindowPaint = false;
  1357.   gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask);
  1358.  
  1359. }
  1360.  
  1361. void UnityScreen::preparePaint(int ms)
  1362. {
  1363.   cScreen->preparePaint(ms);
  1364.  
  1365.   for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
  1366.     wi->HandleAnimations (ms);
  1367.  
  1368.   compizDamageNux(cScreen->currentDamage());
  1369.  
  1370.   didShellRepaint = false;
  1371.   firstWindowAboveShell = NULL;
  1372. }
  1373.  
  1374. void UnityScreen::donePaint()
  1375. {
  1376.   /*
  1377.    * It's only safe to clear the draw list if drawing actually occurred
  1378.    * (i.e. the shell was not obscured behind a fullscreen window).
  1379.    * If you clear the draw list and drawing has not occured then you'd be
  1380.    * left with all your views thinking they're queued for drawing still and
  1381.    * would refuse to redraw when you return from fullscreen.
  1382.    * I think this is a Nux bug. ClearDrawList should ideally also mark all
  1383.    * the queued views as draw_cmd_queued_=false.
  1384.    */
  1385.   if (didShellRepaint)
  1386.     wt->ClearDrawList();
  1387.  
  1388.   std::list <ShowdesktopHandlerWindowInterface *> remove_windows;
  1389.  
  1390.   for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
  1391.   {
  1392.     ShowdesktopHandlerWindowInterface::PostPaintAction action = wi->HandleAnimations (0);
  1393.     if (action == ShowdesktopHandlerWindowInterface::PostPaintAction::Remove)
  1394.       remove_windows.push_back(wi);
  1395.     else if (action == ShowdesktopHandlerWindowInterface::PostPaintAction::Damage)
  1396.       wi->AddDamage ();
  1397.   }
  1398.  
  1399.   for (ShowdesktopHandlerWindowInterface *wi : remove_windows)
  1400.   {
  1401.     wi->DeleteHandler ();
  1402.     ShowdesktopHandler::animating_windows.remove (wi);
  1403.   }
  1404.  
  1405.   cScreen->donePaint ();
  1406. }
  1407.  
  1408. void UnityScreen::compizDamageNux(CompRegion const& damage)
  1409. {
  1410.   if (!launcher_controller_)
  1411.     return;
  1412.  
  1413.   /*
  1414.    * Prioritise user interaction over active blur updates. So the general
  1415.    * slowness of the active blur doesn't affect the UI interaction performance.
  1416.    *
  1417.    * Also, BackgroundEffectHelper::ProcessDamage() is causing a feedback loop
  1418.    * while the dash is open. Calling it results in the NEXT frame (and the
  1419.    * current one?) to get some damage. This GetDrawList().empty() check avoids
  1420.    * that feedback loop and allows us to idle correctly.
  1421.    */
  1422.   if (wt->GetDrawList().empty())
  1423.   {
  1424.     CompRect::vector const& rects(damage.rects());
  1425.     for (CompRect const& r : rects)
  1426.     {
  1427.       nux::Geometry geo(r.x(), r.y(), r.width(), r.height());
  1428.       BackgroundEffectHelper::ProcessDamage(geo);
  1429.     }
  1430.   }
  1431.  
  1432.   auto const& launchers = launcher_controller_->launchers();
  1433.   for (auto const& launcher : launchers)
  1434.   {
  1435.     if (!launcher->Hidden())
  1436.     {
  1437.       nux::Geometry const& geo = launcher->GetAbsoluteGeometry();
  1438.       CompRegion launcher_region(geo.x, geo.y, geo.width, geo.height);
  1439.  
  1440.       if (damage.intersects(launcher_region))
  1441.         launcher->QueueDraw();
  1442.  
  1443.       nux::ObjectPtr<nux::View> const& tooltip = launcher->GetActiveTooltip();
  1444.  
  1445.       if (tooltip)
  1446.       {
  1447.         nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
  1448.         CompRegion tip_region(g.x, g.y, g.width, g.height);
  1449.  
  1450.         if (damage.intersects(tip_region))
  1451.           tooltip->QueueDraw();
  1452.       }
  1453.  
  1454.       nux::ObjectPtr<LauncherDragWindow> const& dragged_icon = launcher->GetDraggedIcon();
  1455.  
  1456.       if (dragged_icon)
  1457.       {
  1458.         nux::Geometry const& g = dragged_icon->GetAbsoluteGeometry();
  1459.         CompRegion icon_region(g.x, g.y, g.width, g.height);
  1460.  
  1461.         if (damage.intersects(icon_region))
  1462.           dragged_icon->QueueDraw();
  1463.       }
  1464.     }
  1465.   }
  1466.  
  1467.   std::vector<nux::View*> const& panels(panel_controller_->GetPanelViews());
  1468.   for (nux::View* view : panels)
  1469.   {
  1470.     nux::Geometry const& geo = view->GetAbsoluteGeometry();
  1471.  
  1472.     CompRegion panel_region(geo.x, geo.y, geo.width, geo.height);
  1473.  
  1474.     if (damage.intersects(panel_region))
  1475.       view->QueueDraw();
  1476.   }
  1477.  
  1478.   QuicklistManager* qm = QuicklistManager::Default();
  1479.   if (qm)
  1480.   {
  1481.     QuicklistView* view = qm->Current();
  1482.     if (view)
  1483.     {
  1484.       nux::Geometry const& geo = view->GetAbsoluteGeometry();
  1485.       CompRegion quicklist_region(geo.x, geo.y, geo.width, geo.height);
  1486.  
  1487.       if (damage.intersects(quicklist_region))
  1488.         view->QueueDraw();
  1489.     }
  1490.   }
  1491. }
  1492.  
  1493. /* Grab changed nux regions and add damage rects for them */
  1494. void UnityScreen::nuxDamageCompiz()
  1495. {
  1496.   /*
  1497.    * WARNING: Nux bug LP: #1014610 (unbounded DrawList growth) will cause
  1498.    *          this code to be called far too often in some cases and
  1499.    *          Unity will appear to freeze for a while. Please ensure you
  1500.    *          have Nux 3.0+ with the fix for LP: #1014610.
  1501.    */
  1502.  
  1503.   if (!launcher_controller_ || !dash_controller_)
  1504.     return;
  1505.  
  1506.   CompRegion nux_damage;
  1507.  
  1508.   std::vector<nux::Geometry> const& dirty = wt->GetDrawList();
  1509.  
  1510.   for (auto const& geo : dirty)
  1511.     nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
  1512.  
  1513.   if (launcher_controller_->IsOverlayOpen())
  1514.   {
  1515.     nux::BaseWindow* dash_window = dash_controller_->window();
  1516.     nux::Geometry const& geo = dash_window->GetAbsoluteGeometry();
  1517.     nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
  1518.   }
  1519.  
  1520.   auto const& launchers = launcher_controller_->launchers();
  1521.   for (auto const& launcher : launchers)
  1522.   {
  1523.     if (!launcher->Hidden())
  1524.     {
  1525.       nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
  1526.  
  1527.       if (tooltip)
  1528.       {
  1529.         nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
  1530.         nux_damage += CompRegion(g.x, g.y, g.width, g.height);
  1531.       }
  1532.  
  1533.       nux::ObjectPtr<LauncherDragWindow> const& dragged_icon = launcher->GetDraggedIcon();
  1534.  
  1535.       if (dragged_icon)
  1536.       {
  1537.         nux::Geometry const& g = dragged_icon->GetAbsoluteGeometry();
  1538.         nux_damage += CompRegion(g.x, g.y, g.width, g.height);
  1539.       }
  1540.     }
  1541.   }
  1542.  
  1543.   cScreen->damageRegionSetEnabled(this, false);
  1544.   cScreen->damageRegion(nux_damage);
  1545.   cScreen->damageRegionSetEnabled(this, true);
  1546. }
  1547.  
  1548. /* handle X Events */
  1549. void UnityScreen::handleEvent(XEvent* event)
  1550. {
  1551.   bool skip_other_plugins = false;
  1552.   switch (event->type)
  1553.   {
  1554.     case FocusIn:
  1555.     case FocusOut:
  1556.       if (event->xfocus.mode == NotifyGrab)
  1557.         PluginAdapter::Default()->OnScreenGrabbed();
  1558.       else if (event->xfocus.mode == NotifyUngrab)
  1559.         PluginAdapter::Default()->OnScreenUngrabbed();
  1560. #ifndef USE_GLES
  1561.       cScreen->damageScreen();  // evil hack
  1562. #endif
  1563.       if (_key_nav_mode_requested && !launcher_controller_->IsOverlayOpen())
  1564.         launcher_controller_->KeyNavGrab();
  1565.       _key_nav_mode_requested = false;
  1566.       break;
  1567.     case ButtonPress:
  1568.       if (super_keypressed_)
  1569.       {
  1570.         launcher_controller_->KeyNavTerminate(false);
  1571.         EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, false);
  1572.       }
  1573.       break;
  1574.     case ButtonRelease:
  1575.       if (switcher_controller_ && switcher_controller_->Visible())
  1576.       {
  1577.         XButtonEvent *bev = reinterpret_cast<XButtonEvent*>(event);
  1578.         if (bev->time - last_scroll_event_ > 150)
  1579.         {
  1580.           if (bev->button == Button4 || bev->button == local::SCROLL_UP_BUTTON)
  1581.           {
  1582.             switcher_controller_->Prev();
  1583.             last_scroll_event_ = bev->time;
  1584.           }
  1585.           else if (bev->button == Button5 || bev->button == local::SCROLL_DOWN_BUTTON)
  1586.           {
  1587.             switcher_controller_->Next();
  1588.             last_scroll_event_ = bev->time;
  1589.           }
  1590.         }
  1591.       }
  1592.       break;
  1593.     case KeyPress:
  1594.     {
  1595.       if (super_keypressed_)
  1596.       {
  1597.         /* We need an idle to postpone this action, after the current event
  1598.          * has been processed */
  1599.         g_idle_add([] (gpointer data) -> gboolean {
  1600.           auto self = static_cast<UnityScreen*>(data);
  1601.  
  1602.           self->shortcut_controller_->SetEnabled(false);
  1603.           self->shortcut_controller_->Hide();
  1604.           self->EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, false);
  1605.  
  1606.           return FALSE;
  1607.         }, this);
  1608.       }
  1609.  
  1610.       KeySym key_sym;
  1611.       char key_string[2];
  1612.       int result = XLookupString(&(event->xkey), key_string, 2, &key_sym, 0);
  1613.  
  1614.       if (launcher_controller_->KeyNavIsActive())
  1615.       {
  1616.         if (key_sym == XK_Up)
  1617.         {
  1618.           launcher_controller_->KeyNavPrevious();
  1619.           break;
  1620.         }
  1621.         else if (key_sym == XK_Down)
  1622.         {
  1623.           launcher_controller_->KeyNavNext();
  1624.           break;
  1625.         }
  1626.       }
  1627.  
  1628.       if (result > 0)
  1629.       {
  1630.         // NOTE: does this have the potential to do an invalid write?  Perhaps
  1631.         // we should just say "key_string[1] = 0" because that is the only
  1632.         // thing that could possibly make sense here.
  1633.         key_string[result] = 0;
  1634.  
  1635.         if (super_keypressed_)
  1636.         {
  1637.           skip_other_plugins = launcher_controller_->HandleLauncherKeyEvent(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string);
  1638.           if (!skip_other_plugins)
  1639.             skip_other_plugins = dash_controller_->CheckShortcutActivation(key_string);
  1640.  
  1641.           if (skip_other_plugins && launcher_controller_->KeyNavIsActive())
  1642.           {
  1643.             launcher_controller_->KeyNavTerminate(false);
  1644.             EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, false);
  1645.           }
  1646.         }
  1647.       }
  1648.       break;
  1649.     }
  1650.     case MapRequest:
  1651.       ShowdesktopHandler::InhibitLeaveShowdesktopMode (event->xmaprequest.window);
  1652.       break;
  1653.     case PropertyNotify:
  1654.       if (event->xproperty.window == GDK_ROOT_WINDOW() &&
  1655.           event->xproperty.atom == gdk_x11_get_xatom_by_name("_GNOME_BACKGROUND_REPRESENTATIVE_COLORS"))
  1656.       {
  1657.         _bghash.RefreshColor();
  1658.       }
  1659.       break;
  1660.     default:
  1661.         if (screen->shapeEvent () + ShapeNotify == event->type)
  1662.         {
  1663.           Window xid = event->xany.window;
  1664.           CompWindow *w = screen->findWindow(xid);
  1665.  
  1666.           if (w)
  1667.           {
  1668.             UnityWindow *uw = UnityWindow::get (w);
  1669.  
  1670.             uw->handleEvent(event);
  1671.           }
  1672.         }
  1673.       break;
  1674.   }
  1675.  
  1676.   compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::handleEvent (event);
  1677.  
  1678.   // avoid further propagation (key conflict for instance)
  1679.   if (!skip_other_plugins)
  1680.     screen->handleEvent(event);
  1681.  
  1682.   switch (event->type)
  1683.   {
  1684.     case PropertyNotify:
  1685.       if (event->xproperty.atom == Atoms::mwmHints)
  1686.       {
  1687.         PluginAdapter::Default ()->NotifyNewDecorationState(event->xproperty.window);
  1688.       }
  1689.       break;
  1690.     case MapRequest:
  1691.       ShowdesktopHandler::AllowLeaveShowdesktopMode (event->xmaprequest.window);
  1692.       break;
  1693.   }
  1694.  
  1695.   if (!skip_other_plugins &&
  1696.       screen->otherGrabExist("deco", "move", "switcher", "resize", NULL) &&
  1697.       !switcher_controller_->Visible())
  1698.   {
  1699.     wt->ProcessForeignEvent(event, NULL);
  1700.   }
  1701. }
  1702.  
  1703. void UnityScreen::damageRegion(const CompRegion &region)
  1704. {
  1705.   compizDamageNux(region);
  1706.   cScreen->damageRegion(region);
  1707. }
  1708.  
  1709. void UnityScreen::handleCompizEvent(const char* plugin,
  1710.                                     const char* event,
  1711.                                     CompOption::Vector& option)
  1712. {
  1713.   PluginAdapter::Default()->NotifyCompizEvent(plugin, event, option);
  1714.   compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::handleCompizEvent (plugin, event, option);
  1715.  
  1716.   if (launcher_controller_->IsOverlayOpen() && g_strcmp0(event, "start_viewport_switch") == 0)
  1717.   {
  1718.     ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
  1719.   }
  1720.  
  1721.   if (PluginAdapter::Default()->IsScaleActive() &&
  1722.       g_strcmp0(plugin, "scale") == 0 && super_keypressed_)
  1723.   {
  1724.     scale_just_activated_ = true;
  1725.   }
  1726.  
  1727.   screen->handleCompizEvent(plugin, event, option);
  1728. }
  1729.  
  1730. bool UnityScreen::showLauncherKeyInitiate(CompAction* action,
  1731.                                           CompAction::State state,
  1732.                                           CompOption::Vector& options)
  1733. {
  1734.   // to receive the Terminate event
  1735.   if (state & CompAction::StateInitKey)
  1736.     action->setState(action->state() | CompAction::StateTermKey);
  1737.  
  1738.   super_keypressed_ = true;
  1739.   int when = options[7].value().i();  // XEvent time in millisec
  1740.   launcher_controller_->HandleLauncherKeyPress(when);
  1741.   EnsureSuperKeybindings ();
  1742.  
  1743.   if (!shortcut_controller_->Visible() && shortcut_controller_->IsEnabled())
  1744.   {
  1745.     int launcher_width = optionGetIconSize() + 18;
  1746.     int panel_height = panel_style_.panel_height;
  1747.  
  1748.     if (shortcut_controller_->Show())
  1749.     {
  1750.       shortcut_controller_->SetAdjustment(launcher_width, panel_height);
  1751.       EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, true, action->key().modifiers());
  1752.     }
  1753.   }
  1754.  
  1755.   return true;
  1756. }
  1757.  
  1758. bool UnityScreen::showLauncherKeyTerminate(CompAction* action,
  1759.                                            CompAction::State state,
  1760.                                            CompOption::Vector& options)
  1761. {
  1762.   // Remember StateCancel and StateCommit will be broadcast to all actions
  1763.   // so we need to verify that we are actually being toggled...
  1764.   if (!(state & CompAction::StateTermKey))
  1765.     return false;
  1766.  
  1767.   if (state & CompAction::StateCancel)
  1768.     return false;
  1769.  
  1770.   bool was_tap = state & CompAction::StateTermTapped;
  1771.   LOG_DEBUG(logger) << "Super released: " << (was_tap ? "tapped" : "released");
  1772.   int when = options[7].value().i();  // XEvent time in millisec
  1773.  
  1774.   // hack...if the scale just wasn't activated AND the 'when' time is within time to start the
  1775.   // dash then assume was_tap is also true, since the ScalePlugin doesn't accept that state...
  1776.   if (PluginAdapter::Default()->IsScaleActive() && !scale_just_activated_ && launcher_controller_->AboutToShowDash(true, when))
  1777.   {
  1778.     PluginAdapter::Default()->TerminateScale();
  1779.     was_tap = true;
  1780.   }
  1781.   else if (scale_just_activated_)
  1782.   {
  1783.     scale_just_activated_ = false;
  1784.   }
  1785.  
  1786.   if (hud_controller_->IsVisible() && launcher_controller_->AboutToShowDash(was_tap, when))
  1787.     hud_controller_->HideHud();
  1788.  
  1789.   super_keypressed_ = false;
  1790.   launcher_controller_->KeyNavTerminate(true);
  1791.   launcher_controller_->HandleLauncherKeyRelease(was_tap, when);
  1792.   EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, false);
  1793.  
  1794.   shortcut_controller_->SetEnabled(enable_shortcut_overlay_);
  1795.   shortcut_controller_->Hide();
  1796.   EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, false);
  1797.  
  1798.   action->setState (action->state() & (unsigned)~(CompAction::StateTermKey));
  1799.   return true;
  1800. }
  1801.  
  1802. bool UnityScreen::showPanelFirstMenuKeyInitiate(CompAction* action,
  1803.                                                 CompAction::State state,
  1804.                                                 CompOption::Vector& options)
  1805. {
  1806.   /* In order to avoid too many events when keeping the keybinding pressed,
  1807.    * that would make the unity-panel-service to go crazy (see bug #948522)
  1808.    * we need to filter them, just considering an event every 750 ms */
  1809.   int event_time = options[7].value().i();  // XEvent time in millisec
  1810.  
  1811.   if (event_time - first_menu_keypress_time_ < 750)
  1812.   {
  1813.     first_menu_keypress_time_ = event_time;
  1814.     return false;
  1815.   }
  1816.  
  1817.   first_menu_keypress_time_ = event_time;
  1818.  
  1819.   /* Even if we do nothing on key terminate, we must enable it, not to to hide
  1820.    * the menus entries after that a menu has been shown and hidden via the
  1821.    * keyboard and the Alt key is still pressed */
  1822.   action->setState(action->state() | CompAction::StateTermKey);
  1823.   panel_controller_->FirstMenuShow();
  1824.  
  1825.   return true;
  1826. }
  1827.  
  1828. bool UnityScreen::showPanelFirstMenuKeyTerminate(CompAction* action,
  1829.                                                  CompAction::State state,
  1830.                                                  CompOption::Vector& options)
  1831. {
  1832.   action->setState (action->state() & (unsigned)~(CompAction::StateTermKey));
  1833.   return true;
  1834. }
  1835.  
  1836. void UnityScreen::SendExecuteCommand()
  1837. {
  1838.   if (hud_controller_->IsVisible())
  1839.   {
  1840.     hud_controller_->HideHud();
  1841.   }
  1842.  
  1843.   if (PluginAdapter::Default()->IsScaleActive())
  1844.   {
  1845.     PluginAdapter::Default()->TerminateScale();
  1846.   }
  1847.  
  1848.   ubus_manager_.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
  1849.                             g_variant_new("(sus)", "commands.lens", 0, ""));
  1850. }
  1851.  
  1852. bool UnityScreen::executeCommand(CompAction* action,
  1853.                                  CompAction::State state,
  1854.                                  CompOption::Vector& options)
  1855. {
  1856.   SendExecuteCommand();
  1857.   return true;
  1858. }
  1859.  
  1860. void UnityScreen::startLauncherKeyNav()
  1861. {
  1862.   // get CompWindow* of launcher-window
  1863.   newFocusedWindow = screen->findWindow(launcher_controller_->KeyNavLauncherInputWindowId());
  1864.  
  1865.   // check if currently focused window isn't the launcher-window
  1866.   if (newFocusedWindow != screen->findWindow(screen->activeWindow()))
  1867.     PluginAdapter::Default()->saveInputFocus();
  1868.  
  1869.   // set input-focus on launcher-window and start key-nav mode
  1870.   if (newFocusedWindow)
  1871.   {
  1872.     // Put the launcher BaseWindow at the top of the BaseWindow stack. The
  1873.     // input focus coming from the XinputWindow will be processed by the
  1874.     // launcher BaseWindow only. Then the Launcher BaseWindow will decide
  1875.     // which View will get the input focus.
  1876.     launcher_controller_->PushToFront();
  1877.     newFocusedWindow->moveInputFocusTo();
  1878.   }
  1879. }
  1880.  
  1881. bool UnityScreen::setKeyboardFocusKeyInitiate(CompAction* action,
  1882.                                               CompAction::State state,
  1883.                                               CompOption::Vector& options)
  1884. {
  1885.   _key_nav_mode_requested = true;
  1886.   return true;
  1887. }
  1888.  
  1889. bool UnityScreen::altTabInitiateCommon(CompAction* action, switcher::ShowMode show_mode)
  1890. {
  1891.   if (!grab_index_)
  1892.     grab_index_ = screen->pushGrab (screen->invisibleCursor(), "unity-switcher");
  1893.   if (!grab_index_)
  1894.     return false;
  1895.  
  1896.   screen->addAction(&optionGetAltTabRight());
  1897.   screen->addAction(&optionGetAltTabDetailStart());
  1898.   screen->addAction(&optionGetAltTabDetailStop());
  1899.   screen->addAction(&optionGetAltTabLeft());
  1900.  
  1901.   /* Create a new keybinding for scroll buttons and current modifiers */
  1902.   CompAction scroll_up;
  1903.   CompAction scroll_down;
  1904.   scroll_up.setButton(CompAction::ButtonBinding(local::SCROLL_UP_BUTTON, action->key().modifiers()));
  1905.   scroll_down.setButton(CompAction::ButtonBinding(local::SCROLL_DOWN_BUTTON, action->key().modifiers()));
  1906.   screen->addAction(&scroll_up);
  1907.   screen->addAction(&scroll_down);
  1908.  
  1909.   // maybe check launcher position/hide state?
  1910.  
  1911.   WindowManager *wm = WindowManager::Default();
  1912.   int monitor = wm->GetWindowMonitor(wm->GetActiveWindow());
  1913.   nux::Geometry monitor_geo = UScreen::GetDefault()->GetMonitorGeometry(monitor);
  1914.   monitor_geo.x += 100;
  1915.   monitor_geo.y += 100;
  1916.   monitor_geo.width -= 200;
  1917.   monitor_geo.height -= 200;
  1918.   switcher_controller_->SetWorkspace(monitor_geo, monitor);
  1919.  
  1920.   if (!optionGetAltTabBiasViewport())
  1921.   {
  1922.     if (show_mode == switcher::ShowMode::CURRENT_VIEWPORT)
  1923.       show_mode = switcher::ShowMode::ALL;
  1924.     else
  1925.       show_mode = switcher::ShowMode::CURRENT_VIEWPORT;
  1926.   }
  1927.  
  1928.   RaiseInputWindows();
  1929.  
  1930.   auto results = launcher_controller_->GetAltTabIcons(show_mode == switcher::ShowMode::CURRENT_VIEWPORT);
  1931.  
  1932.   if (!(results.size() == 1 && results[0]->GetIconType() == AbstractLauncherIcon::IconType::TYPE_DESKTOP))
  1933.     switcher_controller_->Show(show_mode, switcher::SortMode::FOCUS_ORDER, false, results);
  1934.  
  1935.   return true;
  1936. }
  1937.  
  1938. bool UnityScreen::altTabTerminateCommon(CompAction* action,
  1939.                                        CompAction::State state,
  1940.                                        CompOption::Vector& options)
  1941. {
  1942.   if (grab_index_)
  1943.   {
  1944.     // remove grab before calling hide so workspace switcher doesn't fail
  1945.     screen->removeGrab(grab_index_, NULL);
  1946.     grab_index_ = 0;
  1947.  
  1948.     screen->removeAction(&optionGetAltTabRight ());
  1949.     screen->removeAction(&optionGetAltTabDetailStart ());
  1950.     screen->removeAction(&optionGetAltTabDetailStop ());
  1951.     screen->removeAction(&optionGetAltTabLeft ());
  1952.  
  1953.     /* Removing the scroll actions */
  1954.     CompAction scroll_up;
  1955.     CompAction scroll_down;
  1956.     scroll_up.setButton(CompAction::ButtonBinding(local::SCROLL_UP_BUTTON, action->key().modifiers()));
  1957.     scroll_down.setButton(CompAction::ButtonBinding(local::SCROLL_DOWN_BUTTON, action->key().modifiers()));
  1958.     screen->removeAction(&scroll_up);
  1959.     screen->removeAction(&scroll_down);
  1960.  
  1961.     bool accept_state = (state & CompAction::StateCancel) == 0;
  1962.     switcher_controller_->Hide(accept_state);
  1963.   }
  1964.  
  1965.   action->setState (action->state() & (unsigned)~(CompAction::StateTermKey));
  1966.   return true;
  1967. }
  1968.  
  1969. bool UnityScreen::altTabForwardInitiate(CompAction* action,
  1970.                                         CompAction::State state,
  1971.                                         CompOption::Vector& options)
  1972. {
  1973.   if (switcher_controller_->Visible())
  1974.     switcher_controller_->Next();
  1975.   else
  1976.     altTabInitiateCommon(action, switcher::ShowMode::CURRENT_VIEWPORT);
  1977.  
  1978.   action->setState(action->state() | CompAction::StateTermKey);
  1979.   return true;
  1980. }
  1981.  
  1982. bool UnityScreen::altTabForwardAllInitiate(CompAction* action,
  1983.                                         CompAction::State state,
  1984.                                         CompOption::Vector& options)
  1985. {
  1986.   if (switcher_controller_->Visible())
  1987.     switcher_controller_->Next();
  1988.   else
  1989.     altTabInitiateCommon(action, switcher::ShowMode::ALL);
  1990.  
  1991.   action->setState(action->state() | CompAction::StateTermKey);
  1992.   return true;
  1993. }
  1994.  
  1995. bool UnityScreen::altTabPrevAllInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  1996. {
  1997.   if (switcher_controller_->Visible())
  1998.   {
  1999.     switcher_controller_->Prev();
  2000.     return true;
  2001.   }
  2002.  
  2003.   return false;
  2004. }
  2005.  
  2006. bool UnityScreen::altTabPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2007. {
  2008.   if (switcher_controller_->Visible())
  2009.   {
  2010.     switcher_controller_->Prev();
  2011.     return true;
  2012.   }
  2013.  
  2014.   return false;
  2015. }
  2016.  
  2017. bool UnityScreen::altTabDetailStartInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2018. {
  2019.   if (switcher_controller_->Visible())
  2020.   {
  2021.     switcher_controller_->SetDetail(true);
  2022.     return true;
  2023.   }
  2024.  
  2025.   return false;
  2026. }
  2027.  
  2028. bool UnityScreen::altTabDetailStopInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2029. {
  2030.   if (switcher_controller_->Visible())
  2031.   {
  2032.     switcher_controller_->SetDetail(false);
  2033.     return true;
  2034.   }
  2035.  
  2036.   return false;
  2037. }
  2038.  
  2039. bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2040. {
  2041.   if (!switcher_controller_->Visible())
  2042.   {
  2043.     altTabInitiateCommon(action, switcher::ShowMode::CURRENT_VIEWPORT);
  2044.     switcher_controller_->Select(1); // always select the current application
  2045.   }
  2046.  
  2047.   switcher_controller_->NextDetail();
  2048.  
  2049.   action->setState(action->state() | CompAction::StateTermKey);
  2050.   return true;
  2051. }
  2052.  
  2053. bool UnityScreen::altTabPrevWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2054. {
  2055.   if (switcher_controller_->Visible())
  2056.   {
  2057.     switcher_controller_->PrevDetail();
  2058.     return true;
  2059.   }
  2060.  
  2061.   return false;
  2062. }
  2063.  
  2064. bool UnityScreen::launcherSwitcherForwardInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2065. {
  2066.   if (!launcher_controller_->KeyNavIsActive())
  2067.   {
  2068.     int modifiers = action->key().modifiers();
  2069.  
  2070.     launcher_controller_->KeyNavActivate();
  2071.  
  2072.     EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, true, modifiers);
  2073.  
  2074.     KeyCode down_key = XKeysymToKeycode(screen->dpy(), XStringToKeysym("Down"));
  2075.     KeyCode up_key = XKeysymToKeycode(screen->dpy(), XStringToKeysym("Up"));
  2076.  
  2077.     CompAction down_action;
  2078.     down_action.setKey(CompAction::KeyBinding(down_key, modifiers));
  2079.     screen->addAction(&down_action);
  2080.  
  2081.     CompAction up_action;
  2082.     up_action.setKey(CompAction::KeyBinding(up_key, modifiers));
  2083.     screen->addAction(&up_action);
  2084.   }
  2085.   else
  2086.   {
  2087.     launcher_controller_->KeyNavNext();
  2088.   }
  2089.  
  2090.   action->setState(action->state() | CompAction::StateTermKey);
  2091.   return true;
  2092. }
  2093. bool UnityScreen::launcherSwitcherPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2094. {
  2095.   launcher_controller_->KeyNavPrevious();
  2096.  
  2097.   return true;
  2098. }
  2099. bool UnityScreen::launcherSwitcherTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
  2100. {
  2101.   bool accept_state = (state & CompAction::StateCancel) == 0;
  2102.   launcher_controller_->KeyNavTerminate(accept_state);
  2103.  
  2104.   EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, false);
  2105.  
  2106.   KeyCode down_key = XKeysymToKeycode(screen->dpy(), XStringToKeysym("Down"));
  2107.   KeyCode up_key = XKeysymToKeycode(screen->dpy(), XStringToKeysym("Up"));
  2108.  
  2109.   CompAction down_action;
  2110.   down_action.setKey(CompAction::KeyBinding(down_key, action->key().modifiers()));
  2111.   screen->removeAction(&down_action);
  2112.  
  2113.   CompAction up_action;
  2114.   up_action.setKey(CompAction::KeyBinding(up_key, action->key().modifiers()));
  2115.   screen->removeAction(&up_action);
  2116.  
  2117.   action->setState (action->state() & (unsigned)~(CompAction::StateTermKey));
  2118.   return true;
  2119. }
  2120.  
  2121. void UnityScreen::OnLauncherStartKeyNav(GVariant* data)
  2122. {
  2123.   startLauncherKeyNav();
  2124. }
  2125.  
  2126. void UnityScreen::OnLauncherEndKeyNav(GVariant* data)
  2127. {
  2128.   RestoreWindow(data);
  2129. }
  2130.  
  2131. void UnityScreen::OnSwitcherStart(GVariant* data)
  2132. {
  2133.   if (switcher_controller_->Visible())
  2134.   {
  2135.     newFocusedWindow = screen->findWindow(switcher_controller_->GetSwitcherInputWindowId());
  2136.  
  2137.     if (switcher_controller_->GetSwitcherInputWindowId() != screen->activeWindow())
  2138.       PluginAdapter::Default()->saveInputFocus();
  2139.  
  2140.     if (newFocusedWindow)
  2141.       newFocusedWindow->moveInputFocusTo();
  2142.   }
  2143. }
  2144.  
  2145. void UnityScreen::OnSwitcherEnd(GVariant* data)
  2146. {
  2147.   RestoreWindow(data);
  2148. }
  2149.  
  2150. void UnityScreen::RestoreWindow(GVariant* data)
  2151. {
  2152.   bool preserve_focus = false;
  2153.  
  2154.   if (data)
  2155.   {
  2156.     preserve_focus = g_variant_get_boolean(data);
  2157.   }
  2158.  
  2159.   // Return input-focus to previously focused window (before key-nav-mode was
  2160.   // entered)
  2161.   if (preserve_focus)
  2162.     PluginAdapter::Default ()->restoreInputFocus ();
  2163. }
  2164.  
  2165. bool UnityScreen::ShowHud()
  2166. {
  2167.   if (switcher_controller_->Visible())
  2168.   {
  2169.     LOG_ERROR(logger) << "this should never happen";
  2170.     return false; // early exit if the switcher is open
  2171.   }
  2172.  
  2173.   if (hud_controller_->IsVisible())
  2174.   {
  2175.     ubus_manager_.SendMessage(UBUS_HUD_CLOSE_REQUEST);
  2176.   }
  2177.   else
  2178.   {
  2179.     // Handles closing KeyNav (Alt+F1) if the hud is about to show
  2180.     if (launcher_controller_->KeyNavIsActive())
  2181.       launcher_controller_->KeyNavTerminate(false);
  2182.  
  2183.     // If an overlay is open, it must be the dash! Close it!
  2184.     if (launcher_controller_->IsOverlayOpen())
  2185.       dash_controller_->HideDash();
  2186.  
  2187.     hud_controller_->ShowHud();
  2188.   }
  2189.  
  2190.   // Consume the event.
  2191.   return true;
  2192. }
  2193.  
  2194. bool UnityScreen::ShowHudInitiate(CompAction* action,
  2195.                                   CompAction::State state,
  2196.                                   CompOption::Vector& options)
  2197. {
  2198.   // Look to see if there is a keycode.  If there is, then this isn't a
  2199.   // modifier only keybinding.
  2200.   int key_code = 0;
  2201.   if (options[6].type() != CompOption::TypeUnset)
  2202.   {
  2203.     key_code = options[6].value().i();
  2204.     LOG_DEBUG(logger) << "HUD initiate key code: " << key_code;
  2205.     // show it now, no timings or terminate needed.
  2206.     return ShowHud();
  2207.   }
  2208.   else
  2209.   {
  2210.     LOG_DEBUG(logger) << "HUD initiate key code option not set, modifier only keypress.";
  2211.   }
  2212.  
  2213.  
  2214.   // to receive the Terminate event
  2215.   if (state & CompAction::StateInitKey)
  2216.     action->setState(action->state() | CompAction::StateTermKey);
  2217.   hud_keypress_time_ = options[7].value().i();  // XEvent time in millisec
  2218.  
  2219.   // pass key through
  2220.   return false;
  2221. }
  2222.  
  2223. bool UnityScreen::ShowHudTerminate(CompAction* action,
  2224.                                    CompAction::State state,
  2225.                                    CompOption::Vector& options)
  2226. {
  2227.   // Remember StateCancel and StateCommit will be broadcast to all actions
  2228.   // so we need to verify that we are actually being toggled...
  2229.   if (!(state & CompAction::StateTermKey))
  2230.     return false;
  2231.  
  2232.   action->setState(action->state() & ~CompAction::StateTermKey);
  2233.  
  2234.   // If we have a modifier only keypress, check for tap and timing.
  2235.   if (!(state & CompAction::StateTermTapped))
  2236.     return false;
  2237.  
  2238.   int release_time = options[7].value().i();  // XEvent time in millisec
  2239.   int tap_duration = release_time - hud_keypress_time_;
  2240.   if (tap_duration > local::ALT_TAP_DURATION)
  2241.   {
  2242.     LOG_DEBUG(logger) << "Tap too long";
  2243.     return false;
  2244.   }
  2245.  
  2246.   return ShowHud();
  2247. }
  2248.  
  2249. gboolean UnityScreen::initPluginActions(gpointer data)
  2250. {
  2251.   CompPlugin* p = CompPlugin::find("expo");
  2252.  
  2253.   if (p)
  2254.   {
  2255.     MultiActionList expoActions(0);
  2256.  
  2257.     foreach(CompOption & option, p->vTable->getOptions())
  2258.     {
  2259.       if (option.name() == "expo_key" ||
  2260.           option.name() == "expo_button" ||
  2261.           option.name() == "expo_edge")
  2262.       {
  2263.         CompAction* action = &option.value().action();
  2264.         expoActions.AddNewAction(action, false);
  2265.         break;
  2266.       }
  2267.     }
  2268.  
  2269.     PluginAdapter::Default()->SetExpoAction(expoActions);
  2270.   }
  2271.  
  2272.   p = CompPlugin::find("scale");
  2273.  
  2274.   if (p)
  2275.   {
  2276.     MultiActionList scaleActions(0);
  2277.  
  2278.     foreach(CompOption & option, p->vTable->getOptions())
  2279.     {
  2280.       if (option.name() == "initiate_all_key" ||
  2281.           option.name() == "initiate_all_edge" ||
  2282.           option.name() == "initiate_key" ||
  2283.           option.name() == "initiate_button" ||
  2284.           option.name() == "initiate_edge" ||
  2285.           option.name() == "initiate_group_key" ||
  2286.           option.name() == "initiate_group_button" ||
  2287.           option.name() == "initiate_group_edge" ||
  2288.           option.name() == "initiate_output_key" ||
  2289.           option.name() == "initiate_output_button" ||
  2290.           option.name() == "initiate_output_edge")
  2291.       {
  2292.         CompAction* action = &option.value().action();
  2293.         scaleActions.AddNewAction(action, false);
  2294.       }
  2295.       else if (option.name() == "initiate_all_button")
  2296.       {
  2297.         CompAction* action = &option.value().action();
  2298.         scaleActions.AddNewAction(action, true);
  2299.       }
  2300.     }
  2301.  
  2302.     PluginAdapter::Default()->SetScaleAction(scaleActions);
  2303.   }
  2304.  
  2305.   p = CompPlugin::find("unitymtgrabhandles");
  2306.  
  2307.   if (p)
  2308.   {
  2309.     foreach(CompOption & option, p->vTable->getOptions())
  2310.     {
  2311.       if (option.name() == "show_handles_key")
  2312.         PluginAdapter::Default()->SetShowHandlesAction(&option.value().action());
  2313.       else if (option.name() == "hide_handles_key")
  2314.         PluginAdapter::Default()->SetHideHandlesAction(&option.value().action());
  2315.       else if (option.name() == "toggle_handles_key")
  2316.         PluginAdapter::Default()->SetToggleHandlesAction(&option.value().action());
  2317.     }
  2318.   }
  2319.  
  2320.   return FALSE;
  2321. }
  2322.  
  2323. /* Set up expo and scale actions on the launcher */
  2324. bool UnityScreen::initPluginForScreen(CompPlugin* p)
  2325. {
  2326.   if (p->vTable->name() == "expo" ||
  2327.       p->vTable->name() == "scale")
  2328.   {
  2329.     initPluginActions(this);
  2330.   }
  2331.  
  2332.   bool result = screen->initPluginForScreen(p);
  2333.   if (p->vTable->name() == "unityshell")
  2334.     initAltTabNextWindow();
  2335.  
  2336.   return result;
  2337. }
  2338.  
  2339. void UnityScreen::AddProperties(GVariantBuilder* builder)
  2340. {
  2341. }
  2342.  
  2343. std::string UnityScreen::GetName() const
  2344. {
  2345.   return "Unity";
  2346. }
  2347.  
  2348. bool isNuxWindow (CompWindow* value)
  2349. {
  2350.   std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
  2351.   auto id = value->id();
  2352.  
  2353.   // iterate loop by hand rather than use std::find as this is considerably faster
  2354.   // we care about performance here becuase of the high frequency in which this function is
  2355.   // called (nearly every frame)
  2356.   unsigned int size = xwns.size();
  2357.   for (unsigned int i = 0; i < size; ++i)
  2358.   {
  2359.     if (xwns[i] == id)
  2360.       return true;
  2361.   }
  2362.   return false;
  2363. }
  2364.  
  2365. void UnityScreen::RaiseInputWindows()
  2366. {
  2367.   std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
  2368.  
  2369.   for (auto window : xwns)
  2370.   {
  2371.     CompWindow* cwin = screen->findWindow(window);
  2372.     if (cwin)
  2373.       cwin->raise();
  2374.   }
  2375. }
  2376.  
  2377. /* detect occlusions
  2378.  *
  2379.  * core passes down the PAINT_WINDOW_OCCLUSION_DETECTION
  2380.  * mask when it is doing occlusion detection, so use that
  2381.  * order to fill our occlusion buffer which we'll flip
  2382.  * to nux later
  2383.  */
  2384. bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,
  2385.                           const GLMatrix& matrix,
  2386.                           const CompRegion& region,
  2387.                           unsigned int mask)
  2388. {
  2389.   /*
  2390.    * The occlusion pass tests windows from TOP to BOTTOM. That's opposite to
  2391.    * the actual painting loop.
  2392.    *
  2393.    * Detect uScreen->fullscreenRegion here. That represents the region which
  2394.    * fully covers the shell on its output. It does not include regular windows
  2395.    * stacked above the shell like DnD icons or Onboard etc.
  2396.    */
  2397.   if (isNuxWindow(window))
  2398.   {
  2399.     if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
  2400.     {
  2401.       uScreen->nuxRegion += window->geometry();
  2402.       uScreen->nuxRegion -= uScreen->fullscreenRegion;
  2403.     }
  2404.     return false;  // Ensure nux windows are never painted by compiz
  2405.   }
  2406.   else if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
  2407.   {
  2408.     static const unsigned int nonOcclusionBits =
  2409.                               PAINT_WINDOW_TRANSLUCENT_MASK |
  2410.                               PAINT_WINDOW_TRANSFORMED_MASK |
  2411.                               PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
  2412.     if (!(mask & nonOcclusionBits) &&
  2413.         (window->state() & CompWindowStateFullscreenMask))
  2414.         // And I've been advised to test other things, but they don't work:
  2415.         // && (attrib.opacity == OPAQUE)) <-- Doesn't work; Only set in glDraw
  2416.         // && !window->alpha() <-- Doesn't work; Opaque windows often have alpha
  2417.     {
  2418.       uScreen->fullscreenRegion += window->geometry();
  2419.       uScreen->fullscreenRegion -= uScreen->nuxRegion;
  2420.     }
  2421.     if (uScreen->nuxRegion.isEmpty())
  2422.       uScreen->firstWindowAboveShell = window;
  2423.   }
  2424.  
  2425.   GLWindowPaintAttrib wAttrib = attrib;
  2426.  
  2427.   if (mMinimizeHandler)
  2428.   {
  2429.     mask |= mMinimizeHandler->getPaintMask ();
  2430.   }
  2431.   else if (mShowdesktopHandler)
  2432.   {
  2433.     mShowdesktopHandler->PaintOpacity (wAttrib.opacity);
  2434.     mask |= mShowdesktopHandler->GetPaintMask ();
  2435.   }
  2436.  
  2437.   std::vector<Window> const& tray_xids = uScreen->panel_controller_->GetTrayXids();
  2438.   if (std::find(tray_xids.begin(), tray_xids.end(), window->id()) != tray_xids.end() &&
  2439.       !uScreen->allowWindowPaint)
  2440.   {
  2441.     if (!uScreen->painting_tray_)
  2442.     {
  2443.       uScreen->tray_paint_mask_ = mask;
  2444.       mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
  2445.     }
  2446.   }
  2447.  
  2448.   return gWindow->glPaint(wAttrib, matrix, region, mask);
  2449. }
  2450.  
  2451. /* handle window painting in an opengl context
  2452.  *
  2453.  * we want to paint underneath other windows here,
  2454.  * so we need to find if this window is actually
  2455.  * stacked on top of one of the nux input windows
  2456.  * and if so paint nux and stop us from painting
  2457.  * other windows or on top of the whole screen */
  2458. bool UnityWindow::glDraw(const GLMatrix& matrix,
  2459. #ifndef USE_GLES
  2460.                          GLFragment::Attrib& attrib,
  2461. #else
  2462.                          const GLWindowPaintAttrib& attrib,
  2463. #endif
  2464.                          const CompRegion& region,
  2465.                          unsigned int mask)
  2466. {
  2467.   if (uScreen->doShellRepaint && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask)
  2468.   {
  2469.     guint32 id = window->id();
  2470.     bool maximized = WindowManager::Default()->IsWindowMaximized(id);
  2471.     bool on_current = window->onCurrentDesktop();
  2472.     bool override_redirect = window->overrideRedirect();
  2473.     bool managed = window->managed();
  2474.     CompPoint viewport = window->defaultViewport();
  2475.     int output = window->outputDevice();
  2476.  
  2477.     if (maximized && on_current && !override_redirect && managed && viewport == uScreen->screen->vp() && output == (int)uScreen->screen->currentOutputDev().id())
  2478.     {
  2479.       uScreen->paint_panel_ = true;
  2480.     }
  2481.   }
  2482.  
  2483.   if (uScreen->doShellRepaint &&
  2484.       !uScreen->forcePaintOnTop () &&
  2485.       window == uScreen->firstWindowAboveShell &&
  2486.       !uScreen->fullscreenRegion.contains(window->geometry())
  2487.      )
  2488.   {
  2489. #ifdef USE_GLES
  2490.     uScreen->paintDisplay();
  2491. #else
  2492.     uScreen->paintDisplay(region, matrix, mask);
  2493. #endif
  2494.   }
  2495.  
  2496.   if (window->type() == CompWindowTypeDesktopMask)
  2497.     uScreen->setPanelShadowMatrix(matrix);
  2498.  
  2499.   Window active_window = screen->activeWindow();
  2500.   if (window->id() == active_window && window->type() != CompWindowTypeDesktopMask)
  2501.   {
  2502.     uScreen->paintPanelShadow(matrix);
  2503.   }
  2504.  
  2505.   bool ret = gWindow->glDraw(matrix, attrib, region, mask);
  2506.  
  2507.   if ((active_window == 0 || active_window == window->id()) &&
  2508.       (window->type() == CompWindowTypeDesktopMask))
  2509.   {
  2510.     uScreen->paintPanelShadow(matrix);
  2511.   }
  2512.  
  2513.  
  2514.   return ret;
  2515. }
  2516.  
  2517. void
  2518. UnityWindow::minimize ()
  2519. {
  2520.   if (!window->managed ())
  2521.     return;
  2522.  
  2523.   if (!mMinimizeHandler)
  2524.   {
  2525.     mMinimizeHandler.reset (new UnityMinimizedHandler (window, this));
  2526.     mMinimizeHandler->minimize ();
  2527.   }
  2528. }
  2529.  
  2530. void
  2531. UnityWindow::unminimize ()
  2532. {
  2533.   if (mMinimizeHandler)
  2534.   {
  2535.     mMinimizeHandler->unminimize ();
  2536.     mMinimizeHandler.reset ();
  2537.   }
  2538. }
  2539.  
  2540. bool
  2541. UnityWindow::focus ()
  2542. {
  2543.   if (!mMinimizeHandler)
  2544.     return window->focus ();
  2545.  
  2546.   if (window->overrideRedirect ())
  2547.     return false;
  2548.  
  2549.   if (!window->managed ())
  2550.     return false;
  2551.  
  2552.   if (!window->onCurrentDesktop ())
  2553.     return false;
  2554.  
  2555.   /* Only withdrawn windows
  2556.    * which are marked hidden
  2557.    * are excluded */
  2558.   if (!window->shaded () &&
  2559.       !window->minimized () &&
  2560.       (window->state () & CompWindowStateHiddenMask))
  2561.     return false;
  2562.  
  2563.   if (window->geometry ().x () + window->geometry ().width ()  <= 0 ||
  2564.       window->geometry ().y () + window->geometry ().height () <= 0 ||
  2565.       window->geometry ().x () >= (int) screen->width ()||
  2566.       window->geometry ().y () >= (int) screen->height ())
  2567.     return false;
  2568.  
  2569.   return true;
  2570. }
  2571.  
  2572. bool
  2573. UnityWindow::minimized ()
  2574. {
  2575.   return mMinimizeHandler.get () != nullptr;
  2576. }
  2577.  
  2578. gboolean
  2579. UnityWindow::FocusDesktopTimeout(gpointer data)
  2580. {
  2581.   UnityWindow *self = reinterpret_cast<UnityWindow*>(data);
  2582.  
  2583.   self->focusdesktop_handle_ = 0;
  2584.  
  2585.   for (CompWindow *w : screen->clientList ())
  2586.   {
  2587.     if (!(w->type() & NO_FOCUS_MASK) && w->focus ())
  2588.       return FALSE;
  2589.   }
  2590.   self->window->moveInputFocusTo();
  2591.  
  2592.   return FALSE;
  2593. }
  2594.  
  2595. /* Called whenever a window is mapped, unmapped, minimized etc */
  2596. void UnityWindow::windowNotify(CompWindowNotify n)
  2597. {
  2598.   PluginAdapter::Default()->Notify(window, n);
  2599.  
  2600.   switch (n)
  2601.   {
  2602.     case CompWindowNotifyMap:
  2603.       if (window->type() == CompWindowTypeDesktopMask) {
  2604.         if (!focusdesktop_handle_)
  2605.            focusdesktop_handle_ = g_timeout_add (1000, &UnityWindow::FocusDesktopTimeout, this);
  2606.       }
  2607.     /* Fall through an re-evaluate wraps on map and unmap too */
  2608.     case CompWindowNotifyUnmap:
  2609.       if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
  2610.           window->mapNum ())
  2611.       {
  2612.         bool wasMinimized = window->minimized ();
  2613.         if (wasMinimized)
  2614.           window->unminimize ();
  2615.         window->focusSetEnabled (this, true);
  2616.         window->minimizeSetEnabled (this, true);
  2617.         window->unminimizeSetEnabled (this, true);
  2618.         window->minimizedSetEnabled (this, true);
  2619.  
  2620.         if (wasMinimized)
  2621.           window->minimize ();
  2622.       }
  2623.       else
  2624.       {
  2625.         window->focusSetEnabled (this, false);
  2626.         window->minimizeSetEnabled (this, false);
  2627.         window->unminimizeSetEnabled (this, false);
  2628.         window->minimizedSetEnabled (this, false);
  2629.       }
  2630.         break;
  2631.       default:
  2632.         break;
  2633.   }
  2634.  
  2635.  
  2636.   window->windowNotify(n);
  2637.  
  2638.   if (mMinimizeHandler)
  2639.   {
  2640.     /* The minimize handler will short circuit the frame
  2641.      * region update func and ensure that the frame
  2642.      * does not have a region */
  2643.     mMinimizeHandler->windowNotify (n);
  2644.   }
  2645.   else if (mShowdesktopHandler)
  2646.   {
  2647.     if (n == CompWindowNotifyFocusChange)
  2648.       mShowdesktopHandler->WindowFocusChangeNotify ();
  2649.   }
  2650.  
  2651.   // We do this after the notify to ensure input focus has actually been moved.
  2652.   if (n == CompWindowNotifyFocusChange)
  2653.   {
  2654.     UnityScreen* us = UnityScreen::get(screen);
  2655.     CompWindow *lw;
  2656.  
  2657.     if (us->launcher_controller_->IsOverlayOpen())
  2658.     {
  2659.       lw = screen->findWindow(us->launcher_controller_->LauncherWindowId(0));
  2660.       lw->moveInputFocusTo();
  2661.     }
  2662.   }
  2663. }
  2664.  
  2665. void UnityWindow::stateChangeNotify(unsigned int lastState)
  2666. {
  2667.   if (window->state () & CompWindowStateFullscreenMask &&
  2668.       !(lastState & CompWindowStateFullscreenMask))
  2669.     UnityScreen::get (screen)->fullscreen_windows_.push_back(window);
  2670.   else if (lastState & CompWindowStateFullscreenMask &&
  2671.      !(window->state () & CompWindowStateFullscreenMask))
  2672.     UnityScreen::get (screen)->fullscreen_windows_.remove(window);
  2673.  
  2674.   PluginAdapter::Default()->NotifyStateChange(window, window->state(), lastState);
  2675.   window->stateChangeNotify(lastState);
  2676. }
  2677.  
  2678. void UnityWindow::updateFrameRegion(CompRegion &region)
  2679. {
  2680.   /* The minimize handler will short circuit the frame
  2681.    * region update func and ensure that the frame
  2682.    * does not have a region */
  2683.  
  2684.   if (mMinimizeHandler)
  2685.     mMinimizeHandler->updateFrameRegion (region);
  2686.   else if (mShowdesktopHandler)
  2687.     mShowdesktopHandler->UpdateFrameRegion (region);
  2688.   else
  2689.     window->updateFrameRegion (region);
  2690. }
  2691.  
  2692. void UnityWindow::moveNotify(int x, int y, bool immediate)
  2693. {
  2694.   PluginAdapter::Default()->NotifyMoved(window, x, y);
  2695.   window->moveNotify(x, y, immediate);
  2696. }
  2697.  
  2698. void UnityWindow::resizeNotify(int x, int y, int w, int h)
  2699. {
  2700.   PluginAdapter::Default()->NotifyResized(window, x, y, w, h);
  2701.   window->resizeNotify(x, y, w, h);
  2702. }
  2703.  
  2704. CompPoint UnityWindow::tryNotIntersectUI(CompPoint& pos)
  2705. {
  2706.   UnityScreen* us = UnityScreen::get(screen);
  2707.   auto window_geo = window->borderRect ();
  2708.   nux::Geometry target_monitor;
  2709.   nux::Point result(pos.x(), pos.y());
  2710.  
  2711.   // seriously why does compiz not track monitors XRandR style???
  2712.   auto monitors = UScreen::GetDefault()->GetMonitors();
  2713.   for (auto monitor : monitors)
  2714.   {
  2715.     if (monitor.IsInside(result))
  2716.     {
  2717.       target_monitor = monitor;
  2718.       break;
  2719.     }
  2720.   }
  2721.  
  2722.   auto launchers = us->launcher_controller_->launchers();
  2723.   for (auto launcher : launchers)
  2724.   {
  2725.     nux::Geometry geo = launcher->GetAbsoluteGeometry();
  2726.  
  2727.     if (launcher->Hidden() || launcher->options()->hide_mode == LAUNCHER_HIDE_NEVER || launcher->options()->hide_mode == LAUNCHER_HIDE_AUTOHIDE)
  2728.       continue;
  2729.  
  2730.     if (geo.IsInside(result))
  2731.     {
  2732.       if (geo.x + geo.width + 1 + window_geo.width() < target_monitor.x + target_monitor.width)
  2733.       {
  2734.         result.x = geo.x + geo.width + 1;
  2735.       }
  2736.     }
  2737.   }
  2738.  
  2739.   for (nux::Geometry &geo : us->panel_controller_->GetGeometries ())
  2740.   {
  2741.     if (geo.IsInside(result))
  2742.     {
  2743.       if (geo.y + geo.height + window_geo.height() < target_monitor.y + target_monitor.height)
  2744.       {
  2745.         result.y = geo.y + geo.height;
  2746.       }
  2747.     }
  2748.   }
  2749.  
  2750.   pos.setX(result.x);
  2751.   pos.setY(result.y);
  2752.   return pos;
  2753. }
  2754.  
  2755. bool UnityWindow::place(CompPoint& pos)
  2756. {
  2757.   bool was_maximized = PluginAdapter::Default ()->MaximizeIfBigEnough(window);
  2758.  
  2759.   if (!was_maximized)
  2760.   {
  2761.     bool result = window->place(pos);
  2762.  
  2763.     if (window->type() & NO_FOCUS_MASK)
  2764.       return result;
  2765.  
  2766.     pos = tryNotIntersectUI(pos);
  2767.     return result;
  2768.   }
  2769.  
  2770.   return true;
  2771. }
  2772.  
  2773.  
  2774. /* Start up nux after OpenGL is initialized */
  2775. void UnityScreen::initUnity(nux::NThread* thread, void* InitData)
  2776. {
  2777.   Timer timer;
  2778.   UnityScreen* self = reinterpret_cast<UnityScreen*>(InitData);
  2779.   self->initLauncher();
  2780.  
  2781.   nux::ColorLayer background(nux::color::Transparent);
  2782.   static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
  2783.   LOG_INFO(logger) << "UnityScreen::initUnity: " << timer.ElapsedSeconds() << "s";
  2784. }
  2785.  
  2786. gboolean UnityScreen::OnRedrawTimeout(gpointer data)
  2787. {
  2788.   UnityScreen *self = reinterpret_cast<UnityScreen*>(data);
  2789.  
  2790.   self->_redraw_handle = 0;
  2791.   self->onRedrawRequested();
  2792.  
  2793.   return FALSE;
  2794. }
  2795.  
  2796. void UnityScreen::onRedrawRequested()
  2797. {
  2798.   nuxDamageCompiz();
  2799. }
  2800.  
  2801. /* Handle option changes and plug that into nux windows */
  2802. void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num)
  2803. {
  2804.   // Note: perhaps we should put the options here into the controller.
  2805.   unity::launcher::Options::Ptr launcher_options = launcher_controller_->options();
  2806.   switch (num)
  2807.   {
  2808.     case UnityshellOptions::NumLaunchers:
  2809.       launcher_controller_->multiple_launchers = optionGetNumLaunchers() == 0;
  2810.       dash_controller_->use_primary = !launcher_controller_->multiple_launchers();
  2811.       hud_controller_->multiple_launchers = launcher_controller_->multiple_launchers();
  2812.       break;
  2813.     case UnityshellOptions::LauncherCaptureMouse:
  2814.       launcher_options->edge_resist = optionGetLauncherCaptureMouse();
  2815.       break;
  2816.     case UnityshellOptions::BackgroundColor:
  2817.     {
  2818.       nux::Color override_color (optionGetBackgroundColorRed() / 65535.0f,
  2819.                                  optionGetBackgroundColorGreen() / 65535.0f,
  2820.                                  optionGetBackgroundColorBlue() / 65535.0f,
  2821.                                  optionGetBackgroundColorAlpha() / 65535.0f);
  2822.  
  2823.       override_color.red = override_color.red / override_color.alpha;
  2824.       override_color.green = override_color.green / override_color.alpha;
  2825.       override_color.blue = override_color.blue / override_color.alpha;
  2826.       _bghash.OverrideColor(override_color);
  2827.       break;
  2828.     }
  2829.     case UnityshellOptions::LauncherHideMode:
  2830.     {
  2831.       launcher_options->hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
  2832.       hud_controller_->launcher_locked_out = (launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
  2833.       break;
  2834.     }
  2835.     case UnityshellOptions::BacklightMode:
  2836.       launcher_options->backlight_mode = (unity::launcher::BacklightMode) optionGetBacklightMode();
  2837.       break;
  2838.     case UnityshellOptions::RevealTrigger:
  2839.       launcher_options->reveal_trigger = (unity::launcher::RevealTrigger) optionGetRevealTrigger();
  2840.       break;
  2841.     case UnityshellOptions::LaunchAnimation:
  2842.       launcher_options->launch_animation = (unity::launcher::LaunchAnimation) optionGetLaunchAnimation();
  2843.       break;
  2844.     case UnityshellOptions::UrgentAnimation:
  2845.       launcher_options->urgent_animation = (unity::launcher::UrgentAnimation) optionGetUrgentAnimation();
  2846.       break;
  2847.     case UnityshellOptions::PanelOpacity:
  2848.       panel_controller_->SetOpacity(optionGetPanelOpacity());
  2849.       break;
  2850.     case UnityshellOptions::PanelOpacityMaximizedToggle:
  2851.       panel_controller_->SetOpacityMaximizedToggle(optionGetPanelOpacityMaximizedToggle());
  2852.       break;
  2853.     case UnityshellOptions::MenusFadein:
  2854.     case UnityshellOptions::MenusFadeout:
  2855.     case UnityshellOptions::MenusDiscoveryFadein:
  2856.     case UnityshellOptions::MenusDiscoveryFadeout:
  2857.     case UnityshellOptions::MenusDiscoveryDuration:
  2858.       panel_controller_->SetMenuShowTimings(optionGetMenusFadein(),
  2859.                                             optionGetMenusFadeout(),
  2860.                                             optionGetMenusDiscoveryDuration(),
  2861.                                             optionGetMenusDiscoveryFadein(),
  2862.                                             optionGetMenusDiscoveryFadeout());
  2863.       break;
  2864.     case UnityshellOptions::LauncherOpacity:
  2865.       launcher_options->background_alpha = optionGetLauncherOpacity();
  2866.       break;
  2867.     case UnityshellOptions::IconSize:
  2868.     {
  2869.       CompPlugin         *p = CompPlugin::find ("expo");
  2870.  
  2871.       launcher_options->icon_size = optionGetIconSize();
  2872.       launcher_options->tile_size = optionGetIconSize() + 6;
  2873.  
  2874.       hud_controller_->icon_size = launcher_options->icon_size();
  2875.       hud_controller_->tile_size = launcher_options->tile_size();
  2876.  
  2877.       /* The launcher geometry includes 1px used to draw the right margin
  2878.        * that must not be considered when drawing an overlay */
  2879.       hud_controller_->launcher_width = launcher_controller_->launcher().GetAbsoluteWidth() - 1;
  2880.       dash_controller_->launcher_width = launcher_controller_->launcher().GetAbsoluteWidth() - 1;
  2881.  
  2882.       if (p)
  2883.       {
  2884.         CompOption::Vector &opts = p->vTable->getOptions ();
  2885.  
  2886.         for (CompOption &o : opts)
  2887.         {
  2888.           if (o.name () == std::string ("x_offset"))
  2889.           {
  2890.             CompOption::Value v;
  2891.             v.set (static_cast <int> (optionGetIconSize() + 18));
  2892.  
  2893.             screen->setOptionForPlugin (p->vTable->name ().c_str (), o.name ().c_str (), v);
  2894.             break;
  2895.           }
  2896.         }
  2897.       }
  2898.       break;
  2899.     }
  2900.     case UnityshellOptions::AutohideAnimation:
  2901.       launcher_options->auto_hide_animation = (unity::launcher::AutoHideAnimation) optionGetAutohideAnimation();
  2902.       break;
  2903.     case UnityshellOptions::DashBlurExperimental:
  2904.       BackgroundEffectHelper::blur_type = (unity::BlurType)optionGetDashBlurExperimental();
  2905.       break;
  2906.     case UnityshellOptions::AutomaximizeValue:
  2907.       PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);
  2908.       break;
  2909.     case UnityshellOptions::DevicesOption:
  2910.       unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption());
  2911.       break;
  2912.     case UnityshellOptions::AltTabTimeout:
  2913.       switcher_controller_->detail_on_timeout = optionGetAltTabTimeout();
  2914.     case UnityshellOptions::AltTabBiasViewport:
  2915.       PluginAdapter::Default()->bias_active_to_viewport = optionGetAltTabBiasViewport();
  2916.       break;
  2917.     case UnityshellOptions::ShowMinimizedWindows:
  2918.       compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::setFunctions (optionGetShowMinimizedWindows ());
  2919.       screen->enterShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
  2920.       screen->leaveShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
  2921.       break;
  2922.     case UnityshellOptions::ShortcutOverlay:
  2923.       enable_shortcut_overlay_ = optionGetShortcutOverlay();
  2924.       shortcut_controller_->SetEnabled(enable_shortcut_overlay_);
  2925.       break;
  2926.     case UnityshellOptions::ShowDesktopIcon:
  2927.       launcher_controller_->SetShowDesktopIcon(optionGetShowDesktopIcon());
  2928.       break;
  2929.     case UnityshellOptions::DecayRate:
  2930.       launcher_options->edge_decay_rate = optionGetDecayRate() * 100;
  2931.       break;
  2932.     case UnityshellOptions::OvercomePressure:
  2933.       launcher_options->edge_overcome_pressure = optionGetOvercomePressure() * 100;
  2934.       break;
  2935.     case UnityshellOptions::StopVelocity:
  2936.       launcher_options->edge_stop_velocity = optionGetStopVelocity() * 100;
  2937.       break;
  2938.     case UnityshellOptions::RevealPressure:
  2939.       launcher_options->edge_reveal_pressure = optionGetRevealPressure() * 100;
  2940.     case UnityshellOptions::EdgeResponsiveness:
  2941.       launcher_options->edge_responsiveness = optionGetEdgeResponsiveness();
  2942.       break;
  2943.     default:
  2944.       break;
  2945.   }
  2946. }
  2947.  
  2948. void UnityScreen::NeedsRelayout()
  2949. {
  2950.   needsRelayout = true;
  2951. }
  2952.  
  2953. void UnityScreen::ScheduleRelayout(guint timeout)
  2954. {
  2955.   if (relayoutSourceId == 0)
  2956.     relayoutSourceId = g_timeout_add(timeout, &UnityScreen::RelayoutTimeout, this);
  2957. }
  2958.  
  2959. void UnityScreen::Relayout()
  2960. {
  2961.   nux::Geometry geometry (0, 0, screen->width (), screen->height ());
  2962.  
  2963.   if (!needsRelayout)
  2964.     return;
  2965.  
  2966. #ifndef USE_GLES
  2967.   if (GL::fbo)
  2968.   {
  2969.     uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
  2970.     uScreen->_fbo->onScreenSizeChanged (geometry);
  2971.   }
  2972. #endif
  2973.  
  2974.   UScreen *uscreen = UScreen::GetDefault();
  2975.   int primary_monitor = uscreen->GetPrimaryMonitor();
  2976.   auto geo = uscreen->GetMonitorGeometry(primary_monitor);
  2977.  
  2978.   primary_monitor_ = nux::Geometry(geo.x, geo.y, geo.width, geo.height);
  2979.   wt->SetWindowSize(geo.width, geo.height);
  2980.  
  2981.   LOG_DEBUG(logger) << "Setting to primary screen rect:"
  2982.                     << " x=" << primary_monitor_().x
  2983.                     << " y=" << primary_monitor_().y
  2984.                     << " w=" << primary_monitor_().width
  2985.                     << " h=" << primary_monitor_().height;
  2986.  
  2987.   needsRelayout = false;
  2988. }
  2989.  
  2990. gboolean UnityScreen::RelayoutTimeout(gpointer data)
  2991. {
  2992.   UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);
  2993.  
  2994.   uScr->NeedsRelayout ();
  2995.   uScr->Relayout();
  2996.   uScr->relayoutSourceId = 0;
  2997.  
  2998.   uScr->cScreen->damageScreen();
  2999.  
  3000.   return FALSE;
  3001. }
  3002.  
  3003. /* Handle changes in the number of workspaces by showing the switcher
  3004.  * or not showing the switcher */
  3005. bool UnityScreen::setOptionForPlugin(const char* plugin, const char* name,
  3006.                                      CompOption::Value& v)
  3007. {
  3008.   bool status = screen->setOptionForPlugin(plugin, name, v);
  3009.   if (status)
  3010.   {
  3011.     if (strcmp(plugin, "core") == 0 && strcmp(name, "hsize") == 0)
  3012.     {
  3013.       launcher_controller_->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
  3014.     }
  3015.   }
  3016.   return status;
  3017. }
  3018.  
  3019. void UnityScreen::outputChangeNotify()
  3020. {
  3021.   screen->outputChangeNotify ();
  3022.  
  3023.   ScheduleRelayout(500);
  3024. }
  3025.  
  3026. void UnityScreen::OnDashRealized ()
  3027. {
  3028.   /* stack any windows named "onboard" above us */
  3029.   for (CompWindow *w : screen->windows ())
  3030.   {
  3031.     if (w->resName() == "onboard")
  3032.     {
  3033.       Window xid = dash_controller_->window()->GetInputWindowId();
  3034.       XSetTransientForHint (screen->dpy(), w->id(), xid);
  3035.       w->raise ();
  3036.     }
  3037.   }
  3038. }
  3039.  
  3040. /* Start up the launcher */
  3041. void UnityScreen::initLauncher()
  3042. {
  3043.   Timer timer;
  3044.   launcher_controller_ = std::make_shared<launcher::Controller>(screen->dpy());
  3045.   AddChild(launcher_controller_.get());
  3046.  
  3047.   switcher_controller_ = std::make_shared<switcher::Controller>();
  3048.   AddChild(switcher_controller_.get());
  3049.  
  3050.   LOG_INFO(logger) << "initLauncher-Launcher " << timer.ElapsedSeconds() << "s";
  3051.  
  3052.   /* Setup panel */
  3053.   timer.Reset();
  3054.   panel_controller_ = std::make_shared<panel::Controller>();
  3055.   AddChild(panel_controller_.get());
  3056.   panel_controller_->SetMenuShowTimings(optionGetMenusFadein(),
  3057.                                         optionGetMenusFadeout(),
  3058.                                         optionGetMenusDiscoveryDuration(),
  3059.                                         optionGetMenusDiscoveryFadein(),
  3060.                                         optionGetMenusDiscoveryFadeout());
  3061.   LOG_INFO(logger) << "initLauncher-Panel " << timer.ElapsedSeconds() << "s";
  3062.  
  3063.   /* Setup Places */
  3064.   dash_controller_ = std::make_shared<dash::Controller>();
  3065.   dash_controller_->on_realize.connect(sigc::mem_fun(this, &UnityScreen::OnDashRealized));
  3066.  
  3067.   /* Setup Hud */
  3068.   hud_controller_ = std::make_shared<hud::Controller>();
  3069.   auto hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
  3070.   hud_controller_->launcher_locked_out = (hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
  3071.   hud_controller_->multiple_launchers = (optionGetNumLaunchers() == 0);
  3072.   hud_controller_->icon_size = launcher_controller_->options()->icon_size();
  3073.   hud_controller_->tile_size = launcher_controller_->options()->tile_size();
  3074.   AddChild(hud_controller_.get());
  3075.   LOG_INFO(logger) << "initLauncher-hud " << timer.ElapsedSeconds() << "s";
  3076.  
  3077.   // Setup Shortcut Hint
  3078.   InitHints();
  3079.   shortcut_controller_ = std::make_shared<shortcut::Controller>(hints_);
  3080.   AddChild(shortcut_controller_.get());
  3081.  
  3082.   AddChild(dash_controller_.get());
  3083.  
  3084.   ScheduleRelayout(0);
  3085. }
  3086.  
  3087. void UnityScreen::InitHints()
  3088. {
  3089.   // TODO move category text into a vector...
  3090.  
  3091.   // Launcher...
  3092.   std::string const launcher(_("Launcher"));
  3093.  
  3094.   hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" (Press)"), _("Open Launcher, displays shortcuts."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher" ));
  3095.   hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "", _("Open Launcher keyboard navigation mode."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "keyboard_focus"));
  3096.   hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "", _("Switch applications via Launcher."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "launcher_switcher_forward"));
  3097.   hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + 1 to 9"), _("Same as clicking on a Launcher icon."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
  3098.   hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + Shift + 1 to 9"), _("Open new window of the app."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
  3099.   hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", " + T", _("Open the Trash."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
  3100.  
  3101.   // Dash...
  3102.   std::string const dash( _("Dash"));
  3103.  
  3104.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", _(" (Tap)"), _("Open the Dash Home."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
  3105.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + A", _("Open the Dash App Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
  3106.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + F", _("Open the Dash Files Lens."), shortcut::COMPIZ_KEY_OPTION,"unityshell", "show_launcher"));
  3107.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + M", _("Open the Dash Music Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
  3108.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Switches between Lenses."), shortcut::HARDCODED_OPTION, _("Ctrl + Tab")));
  3109.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Keys")));
  3110.   hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Open currently focused item."), shortcut::HARDCODED_OPTION, _("Enter & Return")));
  3111.  
  3112.   // Menu Bar
  3113.   std::string const menubar(_("HUD & Menu Bar"));
  3114.  
  3115.   hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Tap)"), _("Open the HUD."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_hud"));
  3116.   hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Press)"), _("Reveals application menu."), shortcut::HARDCODED_OPTION, "Alt"));
  3117.   hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "", _("Opens the indicator menu."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "panel_first_menu"));
  3118.   hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "", _("Moves focus between indicators."), shortcut::HARDCODED_OPTION, _("Cursor Left or Right")));
  3119.  
  3120.   // Switching
  3121.   std::string const switching(_("Switching"));
  3122.  
  3123.   hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "", _("Switch between applications."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_forward"));
  3124.   hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "", _("Switch windows of current application."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_next_window"));
  3125.   hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Left or Right")));
  3126.  
  3127.   // Workspaces
  3128.   std::string const workspaces(_("Workspaces"));
  3129.  
  3130.   hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", "", _("Spread workspaces."), shortcut::COMPIZ_KEY_OPTION, "expo", "expo_key"));
  3131.   hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "",  _(" + Cursor Keys"), _("Switch workspaces."), shortcut::COMPIZ_METAKEY_OPTION, "wall", "left_key"));
  3132.   hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "",  _(" + Cursor Keys"), _("Move focused window to different workspace."), shortcut::COMPIZ_METAKEY_OPTION, "wall", "left_window_key"));
  3133.  
  3134.   // Windows
  3135.   std::string const windows(_("Windows"));
  3136.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Spreads all windows in the current workspace."), shortcut::COMPIZ_KEY_OPTION, "scale", "initiate_all_key"));
  3137.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Minimises all windows."), shortcut::COMPIZ_KEY_OPTION, "core", "show_desktop_key"));
  3138.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Maximises the current window."), shortcut::COMPIZ_KEY_OPTION, "core", "maximize_window_key"));
  3139.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Restores or minimises current window."), shortcut::COMPIZ_KEY_OPTION, "core", "unmaximize_window_key"));
  3140.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" or Right"), _("Semi-maximises current window."), shortcut::COMPIZ_KEY_OPTION, "grid", "put_left_key"));
  3141.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Closes current window."), shortcut::COMPIZ_KEY_OPTION, "core", "close_window_key"));
  3142.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Opens window accessibility menu."), shortcut::HARDCODED_OPTION, _("Alt + Space")));
  3143.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Places window in corresponding positions."), shortcut::HARDCODED_OPTION, _("Ctrl + Alt + Num")));
  3144.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Move window."), shortcut::COMPIZ_MOUSE_OPTION, "move", "initiate_button"));
  3145.   hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button"));
  3146. }
  3147.  
  3148. /* Window init */
  3149. UnityWindow::UnityWindow(CompWindow* window)
  3150.   : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
  3151.   , PluginClassHandler<UnityWindow, CompWindow>(window)
  3152.   , window(window)
  3153.   , gWindow(GLWindow::get(window))
  3154.   , mMinimizeHandler()
  3155.   , mShowdesktopHandler(nullptr)
  3156.   , focusdesktop_handle_(0)
  3157. {
  3158.   WindowInterface::setHandler(window);
  3159.   GLWindowInterface::setHandler(gWindow);
  3160.  
  3161.   if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
  3162.       window->mapNum ())
  3163.   {
  3164.     bool wasMinimized = window->minimized ();
  3165.     if (wasMinimized)
  3166.       window->unminimize ();
  3167.     window->minimizeSetEnabled (this, true);
  3168.     window->unminimizeSetEnabled (this, true);
  3169.     window->minimizedSetEnabled (this, true);
  3170.  
  3171.     if (wasMinimized)
  3172.       window->minimize ();
  3173.   }
  3174.   else
  3175.   {
  3176.     window->minimizeSetEnabled (this, false);
  3177.     window->unminimizeSetEnabled (this, false);
  3178.     window->minimizedSetEnabled (this, false);
  3179.   }
  3180.  
  3181.   if (window->state () & CompWindowStateFullscreenMask)
  3182.     UnityScreen::get (screen)->fullscreen_windows_.push_back(window);
  3183.  
  3184.   /* We might be starting up so make sure that
  3185.    * we don't deref the dashcontroller that doesnt
  3186.    * exist */
  3187.   dash::Controller::Ptr dp = UnityScreen::get(screen)->dash_controller_;
  3188.  
  3189.   if (dp)
  3190.   {
  3191.     nux::BaseWindow* w = dp->window ();
  3192.  
  3193.     if (w)
  3194.     {
  3195.       if (window->resName() == "onboard")
  3196.       {
  3197.         Window xid = dp->window()->GetInputWindowId();
  3198.         XSetTransientForHint (screen->dpy(), window->id(), xid);
  3199.       }
  3200.     }
  3201.   }
  3202. }
  3203.  
  3204. UnityWindow::~UnityWindow()
  3205. {
  3206.   UnityScreen* us = UnityScreen::get(screen);
  3207.   if (us->newFocusedWindow && (UnityWindow::get(us->newFocusedWindow) == this))
  3208.     us->newFocusedWindow = NULL;
  3209.  
  3210.   if (!window->destroyed ())
  3211.   {
  3212.     bool wasMinimized = window->minimized ();
  3213.     if (wasMinimized)
  3214.       window->unminimize ();
  3215.     window->focusSetEnabled (this, false);
  3216.     window->minimizeSetEnabled (this, false);
  3217.     window->unminimizeSetEnabled (this, false);
  3218.     if (wasMinimized)
  3219.       window->minimize ();
  3220.   }
  3221.  
  3222.   ShowdesktopHandler::animating_windows.remove (static_cast <ShowdesktopHandlerWindowInterface *> (this));
  3223.  
  3224.   if (mShowdesktopHandler)
  3225.     delete mShowdesktopHandler;
  3226.  
  3227.   if (focusdesktop_handle_)
  3228.     g_source_remove(focusdesktop_handle_);
  3229.  
  3230.   if (window->state () & CompWindowStateFullscreenMask)
  3231.     UnityScreen::get (screen)->fullscreen_windows_.remove(window);
  3232.  
  3233.   PluginAdapter::Default ()->OnWindowClosed (window);
  3234. }
  3235.  
  3236. /* vtable init */
  3237. bool UnityPluginVTable::init()
  3238. {
  3239.   if (!CompPlugin::checkPluginABI("core", CORE_ABIVERSION))
  3240.     return false;
  3241.   if (!CompPlugin::checkPluginABI("composite", COMPIZ_COMPOSITE_ABI))
  3242.     return false;
  3243.   if (!CompPlugin::checkPluginABI("opengl", COMPIZ_OPENGL_ABI))
  3244.     return false;
  3245.  
  3246.   /*
  3247.    * GTK needs to be initialized or else unity's gdk/gtk calls will crash.
  3248.    * This is already done in compiz' main() if using ubuntu packages, but not
  3249.    * if you're using the regular (upstream) compiz.
  3250.    * Admittedly this is the same as what the "gtkloader" plugin does. But it
  3251.    * is faster, more efficient (one less plugin in memory), and more reliable
  3252.    * to do the init here where its needed. And yes, init'ing multiple times is
  3253.    * safe, and does nothing after the first init.
  3254.    */
  3255.   if (!gtk_init_check(&programArgc, &programArgv))
  3256.   {
  3257.     compLogMessage("unityshell", CompLogLevelError, "GTK init failed\n");
  3258.     return false;
  3259.   }
  3260.  
  3261.   return true;
  3262. }
  3263.  
  3264.  
  3265. namespace
  3266. {
  3267.  
  3268. void reset_glib_logging()
  3269. {
  3270.   // Reinstate the default glib logger.
  3271.   g_log_set_default_handler(g_log_default_handler, NULL);
  3272. }
  3273.  
  3274. void configure_logging()
  3275. {
  3276.   // The default behaviour of the logging infrastructure is to send all output
  3277.   // to std::cout for warning or above.
  3278.  
  3279.   // TODO: write a file output handler that keeps track of backups.
  3280.   nux::logging::configure_logging(::getenv("UNITY_LOG_SEVERITY"));
  3281.   g_log_set_default_handler(capture_g_log_calls, NULL);
  3282. }
  3283.  
  3284. /* Checks whether an extension is supported by the GLX or OpenGL implementation
  3285.  * given the extension name and the list of supported extensions. */
  3286. gboolean is_extension_supported(const gchar* extensions, const gchar* extension)
  3287. {
  3288.   if (extensions != NULL && extension != NULL)
  3289.   {
  3290.     const gsize len = strlen(extension);
  3291.     gchar* p = (gchar*) extensions;
  3292.     gchar* end = p + strlen(p);
  3293.  
  3294.     while (p < end)
  3295.     {
  3296.       const gsize size = strcspn(p, " ");
  3297.       if (len == size && strncmp(extension, p, size) == 0)
  3298.         return TRUE;
  3299.       p += size + 1;
  3300.     }
  3301.   }
  3302.  
  3303.   return FALSE;
  3304. }
  3305.  
  3306. /* Gets the OpenGL version as a floating-point number given the string. */
  3307. gfloat get_opengl_version_f32(const gchar* version_string)
  3308. {
  3309.   gfloat version = 0.0f;
  3310.   gint32 i;
  3311.  
  3312.   for (i = 0; isdigit(version_string[i]); i++)
  3313.     version = version * 10.0f + (version_string[i] - 48);
  3314.  
  3315.   if ((version_string[i] == '.' || version_string[i] == ',') &&
  3316.       isdigit(version_string[i + 1]))
  3317.   {
  3318.     version = version * 10.0f + (version_string[i + 1] - 48);
  3319.     return (version + 0.1f) * 0.1f;
  3320.   }
  3321.   else
  3322.     return 0.0f;
  3323. }
  3324.  
  3325. nux::logging::Level glog_level_to_nux(GLogLevelFlags log_level)
  3326. {
  3327.   // For some weird reason, ERROR is more critical than CRITICAL in gnome.
  3328.   if (log_level & G_LOG_LEVEL_ERROR)
  3329.     return nux::logging::Critical;
  3330.   if (log_level & G_LOG_LEVEL_CRITICAL)
  3331.     return nux::logging::Error;
  3332.   if (log_level & G_LOG_LEVEL_WARNING)
  3333.     return nux::logging::Warning;
  3334.   if (log_level & G_LOG_LEVEL_MESSAGE ||
  3335.       log_level & G_LOG_LEVEL_INFO)
  3336.     return nux::logging::Info;
  3337.   // default to debug.
  3338.   return nux::logging::Debug;
  3339. }
  3340.  
  3341. void capture_g_log_calls(const gchar* log_domain,
  3342.                          GLogLevelFlags log_level,
  3343.                          const gchar* message,
  3344.                          gpointer user_data)
  3345. {
  3346.   // If nothing else, all log messages from unity should be identified as such
  3347.   std::string module("unity");
  3348.   if (log_domain)
  3349.   {
  3350.     module += std::string(".") + log_domain;
  3351.   }
  3352.   nux::logging::Logger logger(module);
  3353.   nux::logging::Level level = glog_level_to_nux(log_level);
  3354.   if (level >= logger.GetEffectiveLogLevel())
  3355.   {
  3356.     nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
  3357.         << message;
  3358.     if (level >= nux::logging::Error)
  3359.     {
  3360.       nux::logging::Backtrace();
  3361.     }
  3362.   }
  3363. }
  3364.  
  3365. } // anonymous namespace
  3366. } // namespace unity
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top