diff options
| -rw-r--r-- | manual-tests/Launcher.txt | 31 | ||||
| -rw-r--r-- | plugins/unityshell/src/BamfLauncherIcon.cpp | 11 | ||||
| -rw-r--r-- | plugins/unityshell/src/BamfLauncherIcon.h | 1 | ||||
| -rw-r--r-- | plugins/unityshell/src/PluginAdapter.cpp | 14 | ||||
| -rw-r--r-- | plugins/unityshell/src/PluginAdapter.h | 1 | ||||
| -rw-r--r-- | plugins/unityshell/src/WindowManager.cpp | 9 | ||||
| -rw-r--r-- | plugins/unityshell/src/WindowManager.h | 16 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.cpp | 2 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.h | 4 | ||||
| -rw-r--r-- | tests/autopilot/autopilot/emulators/unity/quicklist.py | 4 | ||||
| -rw-r--r-- | tests/autopilot/autopilot/emulators/unity/window_manager.py | 22 | ||||
| -rw-r--r-- | tests/autopilot/autopilot/keybindings.py | 3 | ||||
| -rw-r--r-- | tests/autopilot/autopilot/tests/__init__.py | 7 | ||||
| -rw-r--r-- | tests/autopilot/autopilot/tests/test_quicklist.py | 85 |
14 files changed, 193 insertions, 17 deletions
diff --git a/manual-tests/Launcher.txt b/manual-tests/Launcher.txt index ebedd4311..9b3c1caed 100644 --- a/manual-tests/Launcher.txt +++ b/manual-tests/Launcher.txt @@ -490,6 +490,36 @@ The Firefox icon should *not* be highlighted during the drag&drop. Firefox should open the folder in a new Firefox window. +Test Launcher with Chromium Web apps +------------------------------------ +This tests shows the integration of unity with the Chromium Web Apps + +Setup: + * Open Chromium and go to a website, say ubuntu.com + * Go to the menu "File" -> "Create Application Shortcuts..." + * Select the checkbox "Applications Menu" (you can deselect the "Desktop" one) + * A new window is opened, and the launcher will continue matching it like a + chromium application. + * Close the chromium window. + +Actions: + * Open the dash and search for "chrom" + * An application called "Home | Ubuntu" should be shown + * Launch it + +Expected Results: + * The launcher will show an icon for the "Home | Ubuntu" application + +Actions: + * Open a standard chromium window + +Expected Results: + * The new chromium window will be associated to the standard chromium + application icon. + * Clicking the "Home | Ubuntu" will activate its window, while clicking + in the chromium icon will activate a chromium window. + + Test Launcher raises focused non-top windows -------------------------------------------- This tests shows how the focused windows should be raised to the top of the @@ -510,4 +540,3 @@ Actions: Expected Results: * Terminal window will be raised to the top of the stack (over the GIMP window) - diff --git a/plugins/unityshell/src/BamfLauncherIcon.cpp b/plugins/unityshell/src/BamfLauncherIcon.cpp index 54ee82cd5..01205fc24 100644 --- a/plugins/unityshell/src/BamfLauncherIcon.cpp +++ b/plugins/unityshell/src/BamfLauncherIcon.cpp @@ -149,6 +149,9 @@ BamfLauncherIcon::~BamfLauncherIcon() if (_fill_supported_types_id != 0) g_source_remove(_fill_supported_types_id); + if (_quicklist_activated_id != 0) + g_source_remove(_quicklist_activated_id); + if (_window_moved_id != 0) g_source_remove(_window_moved_id); @@ -973,7 +976,13 @@ std::list<DbusmenuMenuitem*> BamfLauncherIcon::GetMenus() _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [&] (DbusmenuMenuitem*, int) { - ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0)); + _quicklist_activated_id = + g_idle_add([] (gpointer data) -> gboolean { + auto self = static_cast<BamfLauncherIcon*>(data); + self->ActivateLauncherIcon(ActionArg()); + self->_quicklist_activated_id = 0; + return FALSE; + }, this); })); _menu_items_extra["AppName"] = glib::Object<DbusmenuMenuitem>(item); diff --git a/plugins/unityshell/src/BamfLauncherIcon.h b/plugins/unityshell/src/BamfLauncherIcon.h index e7752902c..279e8a8a2 100644 --- a/plugins/unityshell/src/BamfLauncherIcon.h +++ b/plugins/unityshell/src/BamfLauncherIcon.h @@ -126,6 +126,7 @@ private: bool _supported_types_filled; guint _fill_supported_types_id; guint _window_moved_id; + guint _quicklist_activated_id; std::string _remote_uri; std::string _desktop_file; diff --git a/plugins/unityshell/src/PluginAdapter.cpp b/plugins/unityshell/src/PluginAdapter.cpp index b733f9939..e9008c224 100644 --- a/plugins/unityshell/src/PluginAdapter.cpp +++ b/plugins/unityshell/src/PluginAdapter.cpp @@ -23,6 +23,7 @@ #include "UScreen.h" #include <NuxCore/Logger.h> +#include <UnityCore/Variant.h> namespace { @@ -1299,3 +1300,16 @@ PluginAdapter::OnWindowClosed(CompWindow *w) _last_focused_window = NULL; } +void +PluginAdapter::AddProperties(GVariantBuilder* builder) +{ + unity::variant::BuilderWrapper wrapper(builder); + wrapper.add(GetScreenGeometry()) + .add("workspace_count", WorkspaceCount()) + .add("active_window", GetActiveWindow()) + .add("screen_grabbed", IsScreenGrabbed()) + .add("scale_active", IsScaleActive()) + .add("scale_active_for_group", IsScaleActiveForGroup()) + .add("expo_active", IsExpoActive()) + .add("viewport_switch_running", IsViewPortSwitchStarted()); +} diff --git a/plugins/unityshell/src/PluginAdapter.h b/plugins/unityshell/src/PluginAdapter.h index c7ff0e56c..70d5e433c 100644 --- a/plugins/unityshell/src/PluginAdapter.h +++ b/plugins/unityshell/src/PluginAdapter.h @@ -166,6 +166,7 @@ public: protected: PluginAdapter(CompScreen* screen); + void AddProperties(GVariantBuilder* builder); private: std::string MatchStringForXids(std::vector<Window> *windows); diff --git a/plugins/unityshell/src/WindowManager.cpp b/plugins/unityshell/src/WindowManager.cpp index ded12e730..cde2dc149 100644 --- a/plugins/unityshell/src/WindowManager.cpp +++ b/plugins/unityshell/src/WindowManager.cpp @@ -219,6 +219,10 @@ class WindowManagerDummy : public WindowManager { g_debug("%s", G_STRFUNC); } + + void AddProperties(GVariantBuilder* builder) + { + } }; WindowManager* @@ -236,6 +240,11 @@ WindowManager::SetDefault(WindowManager* manager) window_manager = manager; } +std::string WindowManager::GetName() const +{ + return "WindowManager"; +} + #define NET_WM_MOVERESIZE_MOVE 8 void WindowManager::StartMove(guint32 xid, int x, int y) diff --git a/plugins/unityshell/src/WindowManager.h b/plugins/unityshell/src/WindowManager.h index a7a85cfff..4e74b022a 100644 --- a/plugins/unityshell/src/WindowManager.h +++ b/plugins/unityshell/src/WindowManager.h @@ -19,24 +19,18 @@ #ifndef WINDOW_MANAGER_H #define WINDOW_MANAGER_H -#include <glib.h> -#include <sigc++/sigc++.h> #include <Nux/Nux.h> -#include <Nux/WindowThread.h> -#include <NuxGraphics/GLWindowManager.h> #include <gdk/gdkx.h> #include <core/core.h> -class WindowManager +#include "Introspectable.h" + +class WindowManager : public unity::debug::Introspectable { // This is a glue interface that breaks the dependancy of Unity with Compiz // Basically it has a default implementation that does nothing useful, but // the idea is that unity.cpp uses SetDefault() early enough in it's // initialization so the things that require it get a usable implementation - // - // Currently only the Panel uses it but hopefully we'll get more of - // PluginAdaptor features moved into here and also get the Launcher to use - // it. public: WindowManager() : @@ -143,6 +137,10 @@ public: sigc::signal<void, const char*, const char*, CompOption::Vector&> compiz_event; +protected: + std::string GetName() const; + virtual void AddProperties(GVariantBuilder* builder) = 0; + private: Atom m_MoveResizeAtom; }; diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index a4e94a797..e85c32467 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -217,6 +217,7 @@ UnityScreen::UnityScreen(CompScreen* screen) PluginAdapter::Initialize(screen); WindowManager::SetDefault(PluginAdapter::Default()); + AddChild(PluginAdapter::Default()); StartupNotifyService::Default()->SetSnDisplay(screen->snDisplay(), screen->screenNum()); @@ -243,7 +244,6 @@ UnityScreen::UnityScreen(CompScreen* screen) wt->Run(NULL); uScreen = this; - _in_paint = false; #ifndef USE_GLES diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index d15d55423..a648ed693 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -241,7 +241,7 @@ private: internal::FavoriteStoreGSettings favorite_store_; /* The window thread should be the last thing removed, as c++ does it in reverse order */ - std::unique_ptr<nux::WindowThread> wt; + std::unique_ptr<nux::WindowThread> wt; /* These must stay below the window thread, please keep the order */ launcher::Controller::Ptr launcher_controller_; @@ -250,7 +250,7 @@ private: switcher::Controller::Ptr switcher_controller_; hud::Controller::Ptr hud_controller_; shortcut::Controller::Ptr shortcut_controller_; - debug::DebugDBusInterface debugger_; + debug::DebugDBusInterface debugger_; std::list<shortcut::AbstractHint::Ptr> hints_; bool enable_shortcut_overlay_; diff --git a/tests/autopilot/autopilot/emulators/unity/quicklist.py b/tests/autopilot/autopilot/emulators/unity/quicklist.py index 359d662e3..8cb0280f1 100644 --- a/tests/autopilot/autopilot/emulators/unity/quicklist.py +++ b/tests/autopilot/autopilot/emulators/unity/quicklist.py @@ -40,6 +40,10 @@ class Quicklist(UnityIntrospectionObject): return matches[0] if matches else None + def get_quicklist_application_item(self, application_name): + """Returns the QuicklistMenuItemLabel for the given application_name""" + return self.get_quicklist_item_by_text("<b>"+application_name+"</b>") + def click_item(self, item): """Click one of the quicklist items.""" if not isinstance(item, QuicklistMenuItem): diff --git a/tests/autopilot/autopilot/emulators/unity/window_manager.py b/tests/autopilot/autopilot/emulators/unity/window_manager.py new file mode 100644 index 000000000..5e54bd06c --- /dev/null +++ b/tests/autopilot/autopilot/emulators/unity/window_manager.py @@ -0,0 +1,22 @@ +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- +# Copyright 2012 Canonical +# Author: Marco Trevisan (TreviƱo) +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 3, as published +# by the Free Software Foundation. +# + +import logging +from autopilot.emulators.unity import UnityIntrospectionObject + +logger = logging.getLogger(__name__) + + +class WindowManager(UnityIntrospectionObject): + """The WindowManager class.""" + + @property + def screen_geometry(self): + """Returns a tuple of (x,y,w,h) for the screen.""" + return (self.x, self.y, self.width, self.height) diff --git a/tests/autopilot/autopilot/keybindings.py b/tests/autopilot/autopilot/keybindings.py index 92973855a..1b43cedb9 100644 --- a/tests/autopilot/autopilot/keybindings.py +++ b/tests/autopilot/autopilot/keybindings.py @@ -112,6 +112,9 @@ _keys = { # expo plugin: "expo/start": ("expo", "expo_key"), "expo/cancel": "Escape", + # spread (scale) plugin: + "spread/start": ("scale", "initiate_all_key"), + "spread/cancel": "Escape", } diff --git a/tests/autopilot/autopilot/tests/__init__.py b/tests/autopilot/autopilot/tests/__init__.py index b158e3ed6..d472d562f 100644 --- a/tests/autopilot/autopilot/tests/__init__.py +++ b/tests/autopilot/autopilot/tests/__init__.py @@ -27,6 +27,7 @@ from autopilot.emulators.unity.hud import Hud from autopilot.emulators.unity.launcher import LauncherController from autopilot.emulators.unity.panel import PanelController from autopilot.emulators.unity.switcher import Switcher +from autopilot.emulators.unity.window_manager import WindowManager from autopilot.emulators.unity.workspace import WorkspaceManager from autopilot.emulators.X11 import ScreenGeometry, Keyboard, Mouse, reset_display from autopilot.glibrunner import GlibRunner @@ -239,6 +240,7 @@ class AutopilotTestCase(VideoCapturedTestCase, KeybindingsHelper): self.launcher = self._get_launcher_controller() self.panels = self._get_panel_controller() self.switcher = Switcher() + self.window_manager = self._get_window_manager() self.workspace = WorkspaceManager() self.screen_geo = ScreenGeometry() self.addCleanup(self.workspace.switch_to, self.workspace.current_workspace) @@ -336,6 +338,11 @@ class AutopilotTestCase(VideoCapturedTestCase, KeybindingsHelper): self.assertThat(len(controllers), Equals(1)) return controllers[0] + def _get_window_manager(self): + managers = WindowManager.get_all_instances() + self.assertThat(len(managers), Equals(1)) + return managers[0] + def assertVisibleWindowStack(self, stack_start): """Check that the visible window stack starts with the windows passed in. diff --git a/tests/autopilot/autopilot/tests/test_quicklist.py b/tests/autopilot/autopilot/tests/test_quicklist.py index 4c78715b0..c4349f24a 100644 --- a/tests/autopilot/autopilot/tests/test_quicklist.py +++ b/tests/autopilot/autopilot/tests/test_quicklist.py @@ -24,6 +24,11 @@ class QuicklistActionTests(AutopilotTestCase): ('remmina', {'app_name': 'Remmina'}), ] + def open_quicklist_for_icon(self, launcher_icon): + launcher = self.launcher.get_launcher_for_monitor(0) + launcher.click_launcher_icon(launcher_icon, button=3) + self.addCleanup(self.keyboard.press_and_release, "Escape") + def test_quicklist_actions(self): """Test that all actions present in the destop file are shown in the quicklist.""" self.start_app(self.app_name) @@ -37,9 +42,7 @@ class QuicklistActionTests(AutopilotTestCase): self.assertThat(launcher_icon, NotEquals(None)) # open the icon quicklist, and get all the text labels: - launcher = self.launcher.get_launcher_for_monitor(0) - launcher.click_launcher_icon(launcher_icon, button=3) - self.addCleanup(self.keyboard.press_and_release, "Escape") + self.open_quicklist_for_icon(launcher_icon) ql = launcher_icon.get_quicklist() ql_item_texts = [i.text for i in ql.items if type(i) is QuicklistMenuItemLabel] @@ -53,6 +56,82 @@ class QuicklistActionTests(AutopilotTestCase): name = de.content[key]['Name'] self.assertThat(ql_item_texts, Contains(name)) + def test_quicklist_application_item_focus_last_active_window(self): + """This tests shows that when you activate a quicklist application item + only the last focused instance of that application is rasied. + + This is tested by opening 2 Mahjongg and a Calculator. + Then we activate the Calculator quicklist item. + Then we actiavte the Mahjongg launcher icon. + """ + mahj = self.start_app("Mahjongg") + [mah_win1] = mahj.get_windows() + self.assertTrue(mah_win1.is_focused) + + calc = self.start_app("Calculator") + [calc_win] = calc.get_windows() + self.assertTrue(calc_win.is_focused) + + self.start_app("Mahjongg") + # Sleeping due to the start_app only waiting for the bamf model to be + # updated with the application. Since the app has already started, + # and we are just waiting on a second window, however a defined sleep + # here is likely to be problematic. + # TODO: fix bamf emulator to enable waiting for new windows. + sleep(1) + [mah_win2] = [w for w in mahj.get_windows() if w.x_id != mah_win1.x_id] + self.assertTrue(mah_win2.is_focused) + + self.assertVisibleWindowStack([mah_win2, calc_win, mah_win1]) + + mahj_icon = self.launcher.model.get_icon_by_desktop_id(mahj.desktop_file) + calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file) + + self.open_quicklist_for_icon(calc_icon) + calc_ql = calc_icon.get_quicklist() + calc_ql.get_quicklist_application_item(calc.name).mouse_click() + sleep(1) + self.assertTrue(calc_win.is_focused) + self.assertVisibleWindowStack([calc_win, mah_win2, mah_win1]) + + self.open_quicklist_for_icon(mahj_icon) + mahj_ql = mahj_icon.get_quicklist() + mahj_ql.get_quicklist_application_item(mahj.name).mouse_click() + sleep(1) + self.assertTrue(mah_win2.is_focused) + self.assertVisibleWindowStack([mah_win2, calc_win, mah_win1]) + + def test_quicklist_application_item_initiate_spread(self): + """This tests shows that when you activate a quicklist application item + when an application window is focused, the spread is initiated. + """ + calc = self.start_app("Calculator") + [calc_win1] = calc.get_windows() + self.assertTrue(calc_win1.is_focused) + + self.start_app("Calculator") + # Sleeping due to the start_app only waiting for the bamf model to be + # updated with the application. Since the app has already started, + # and we are just waiting on a second window, however a defined sleep + # here is likely to be problematic. + # TODO: fix bamf emulator to enable waiting for new windows. + sleep(1) + [calc_win2] = [w for w in calc.get_windows() if w.x_id != calc_win1.x_id] + + self.assertVisibleWindowStack([calc_win2, calc_win1]) + self.assertTrue(calc_win2.is_focused) + + calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file) + + self.open_quicklist_for_icon(calc_icon) + calc_ql = calc_icon.get_quicklist() + app_item = calc_ql.get_quicklist_application_item(calc.name) + + self.addCleanup(self.keybinding, "spread/cancel") + app_item.mouse_click() + self.assertThat(self.window_manager.scale_active, Eventually(Equals(True))) + self.assertThat(self.window_manager.scale_active_for_group, Eventually(Equals(True))) + class QuicklistKeyNavigationTests(AutopilotTestCase): """Tests for the quicklist key navigation.""" |
