Advertisement
Duckcarer

Unity-5.18.0 unityshell.cpp

Mar 20th, 2013
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 110.32 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement