diff options
| -rw-r--r-- | launcher/SwitcherModel.h | 4 | ||||
| -rw-r--r-- | launcher/SwitcherView.cpp | 78 | ||||
| -rw-r--r-- | launcher/SwitcherView.h | 26 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tests/test_switcher_controller.cpp | 4 | ||||
| -rw-r--r-- | tests/test_switcher_view.cpp | 198 |
6 files changed, 253 insertions, 58 deletions
diff --git a/launcher/SwitcherModel.h b/launcher/SwitcherModel.h index 2ab0fa040..86e644cd5 100644 --- a/launcher/SwitcherModel.h +++ b/launcher/SwitcherModel.h @@ -26,8 +26,6 @@ #include "LauncherModel.h" #include "unity-shared/Introspectable.h" - -#include <boost/shared_ptr.hpp> #include <sigc++/sigc++.h> namespace unity @@ -53,7 +51,7 @@ class SwitcherModel : public debug::Introspectable, public sigc::trackable { public: - typedef boost::shared_ptr<SwitcherModel> Ptr; + typedef std::shared_ptr<SwitcherModel> Ptr; typedef std::vector<launcher::AbstractLauncherIcon::Ptr> Applications; typedef Applications::iterator iterator; diff --git a/launcher/SwitcherView.cpp b/launcher/SwitcherView.cpp index 993ed1017..adbe551f4 100644 --- a/launcher/SwitcherView.cpp +++ b/launcher/SwitcherView.cpp @@ -142,7 +142,10 @@ void SwitcherView::OnDetailSelectionChanged(bool detail) text_view_->SetVisible(!detail); if (!detail) + { text_view_->SetText(model_->Selection()->tooltip_text()); + render_targets_.clear(); + } SaveLast(); QueueDraw(); @@ -210,7 +213,7 @@ RenderArg SwitcherView::InterpolateRenderArgs(RenderArg const& start, RenderArg return result; } -nux::Geometry SwitcherView::InterpolateBackground (nux::Geometry const& start, nux::Geometry const& end, float progress) +nux::Geometry SwitcherView::InterpolateBackground(nux::Geometry const& start, nux::Geometry const& end, float progress) { progress = -pow(progress - 1.0f, 2) + 1; @@ -224,12 +227,10 @@ nux::Geometry SwitcherView::InterpolateBackground (nux::Geometry const& start, n return result; } -nux::Geometry SwitcherView::UpdateRenderTargets(nux::Point const& center, timespec const& current) +nux::Geometry SwitcherView::UpdateRenderTargets(float progress) { std::vector<Window> const& xids = model_->DetailXids(); - - DeltaTime ms_since_change = TimeUtil::TimeDelta(¤t, &save_time_); - float progress = std::min<float>(1.0f, ms_since_change / static_cast<float>(animation_length())); + render_targets_.clear(); for (Window window : xids) { @@ -241,33 +242,39 @@ nux::Geometry SwitcherView::UpdateRenderTargets(nux::Point const& center, timesp render_targets_.push_back(layout_window); } - nux::Geometry max_bounds; - nux::Geometry const& absolute = GetAbsoluteGeometry(); + nux::Geometry max_bounds = GetAbsoluteGeometry(); nux::Size const& spread_size = SpreadSize(); - max_bounds.x = absolute.x + center.x - spread_size.width / 2; - max_bounds.y = absolute.y + center.y - spread_size.height / 2; + max_bounds.x -= spread_size.width / 2; + max_bounds.y -= spread_size.height / 2; max_bounds.width = spread_size.width; max_bounds.height = spread_size.height; - nux::Geometry final_bounds; - layout_system_.LayoutWindows(render_targets_, max_bounds, final_bounds); + nux::Geometry layout_geo; + layout_system_.LayoutWindows(render_targets_, max_bounds, layout_geo); + + return layout_geo; +} + +void SwitcherView::ResizeRenderTargets(nux::Geometry const& layout_geo, float progress) +{ + if (progress >= 1.0f) + return; - if (progress < 1.0f) + // Animate the windows thumbnail sizes to make them grow with the switcher + float to_finish = 1.0f - progress; + nux::Point layout_abs_center((layout_geo.x + layout_geo.width/2.0f) * to_finish, + (layout_geo.y + layout_geo.height/2.0f) * to_finish); + + for (LayoutWindow::Ptr const& win : render_targets_) { - // Animate the windows thumbnail sizes to make them grow with the switcher - for (LayoutWindow::Ptr const& win : render_targets_) - { - auto old_geo = win->result; - win->result = old_geo * progress; - win->result.x += (old_geo.width - win->result.width) / 4; - win->result.y += (old_geo.height - win->result.height) / 4; - } + auto final_geo = win->result; + win->result = final_geo * progress; + win->result.x += layout_abs_center.x; + win->result.y += layout_abs_center.y; } - - return final_bounds; } -void SwitcherView::OffsetRenderTargets (int x, int y) +void SwitcherView::OffsetRenderTargets(int x, int y) { for (LayoutWindow::Ptr const& target : render_targets_) { @@ -361,13 +368,11 @@ void SwitcherView::GetFlatIconPositions (int n_flat_icons, } } -std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, int selection, timespec const& current) +std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, int selection, float progress) { std::list<RenderArg> results; nux::Geometry const& base = GetGeometry(); - render_targets_.clear (); - bool detail_selection = model_->detail_selection; background_geo.y = base.y + base.height / 2 - (vertical_size / 2); @@ -385,7 +390,8 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, int spread_padded_width = 0; if (detail_selection) { - nux::Geometry const& spread_bounds = UpdateRenderTargets(nux::Point(), current); + nux::Geometry const& spread_bounds = UpdateRenderTargets(progress); + ResizeRenderTargets(spread_bounds, progress); // remove extra space consumed by spread spread_padded_width = spread_bounds.width + 100; max_width -= spread_padded_width - tile_size; @@ -455,10 +461,7 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, x += (half_size + flat_spacing) * scalar; - if (should_flat) - arg.render_center = nux::Point3((int) x, y, 0); - else - arg.render_center = nux::Point3(x, y, 0); + arg.render_center = nux::Point3(should_flat ? std::floor(x) : x, y, 0); x += (half_size + flat_spacing) * scalar; @@ -483,18 +486,15 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, if (i == selection && detail_selection) { arg.skip = true; - OffsetRenderTargets (arg.render_center.x, arg.render_center.y); + OffsetRenderTargets(arg.render_center.x, arg.render_center.y); } results.push_back(arg); ++i; } - DeltaTime ms_since_change = TimeUtil::TimeDelta(¤t, &save_time_); - if (saved_args_.size () == results.size () && ms_since_change < animation_length) + if (saved_args_.size () == results.size () && progress < 1.0f) { - float progress = (float) ms_since_change / (float) animation_length(); - std::list<RenderArg> end = results; results.clear(); @@ -504,7 +504,7 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, results.push_back(InterpolateRenderArgs(*start_it, *end_it, progress)); } - background_geo = InterpolateBackground (saved_background_, background_geo, progress); + background_geo = InterpolateBackground(saved_background_, background_geo, progress); } } @@ -514,6 +514,8 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, void SwitcherView::PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw) { clock_gettime(CLOCK_MONOTONIC, ¤t_); + DeltaTime ms_since_change = TimeUtil::TimeDelta(¤t_, &save_time_); + float progress = std::min<float>(1.0f, ms_since_change / static_cast<float>(animation_length())); if (!target_sizes_set_) { @@ -522,7 +524,7 @@ void SwitcherView::PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw) } nux::Geometry background_geo; - last_args_ = RenderArgsFlat(background_geo, model_->SelectionIndex(), current_); + last_args_ = RenderArgsFlat(background_geo, model_->SelectionIndex(), progress); last_background_ = background_geo; icon_renderer_->PreprocessIcons(last_args_, GetGeometry()); diff --git a/launcher/SwitcherView.h b/launcher/SwitcherView.h index 2349bf286..ddfb0ebe4 100644 --- a/launcher/SwitcherView.h +++ b/launcher/SwitcherView.h @@ -81,9 +81,9 @@ protected: nux::Geometry GetBackgroundGeometry(); ui::RenderArg InterpolateRenderArgs(ui::RenderArg const& start, ui::RenderArg const& end, float progress); - nux::Geometry InterpolateBackground (nux::Geometry const& start, nux::Geometry const& end, float progress); + nux::Geometry InterpolateBackground(nux::Geometry const& start, nux::Geometry const& end, float progress); - std::list<ui::RenderArg> RenderArgsFlat(nux::Geometry& background_geo, int selection, timespec const& current); + std::list<ui::RenderArg> RenderArgsFlat(nux::Geometry& background_geo, int selection, float progress); ui::RenderArg CreateBaseArgForIcon(launcher::AbstractLauncherIcon::Ptr const& icon); private: @@ -94,20 +94,16 @@ private: void OnIconSizeChanged (int size); void OnTileSizeChanged (int size); - nux::Geometry UpdateRenderTargets (nux::Point const& center, timespec const& current); - void OffsetRenderTargets (int x, int y); + nux::Geometry UpdateRenderTargets(float progress); + void ResizeRenderTargets(nux::Geometry const& layout_geo, float progress); + void OffsetRenderTargets(int x, int y); - nux::Size SpreadSize (); + nux::Size SpreadSize(); - void GetFlatIconPositions (int n_flat_icons, - int size, - int selection, - int &first_flat, - int &last_flat, - int &half_fold_left, - int &half_fold_right); - - void SaveLast (); + void GetFlatIconPositions(int n_flat_icons, int size, int selection, + int &first_flat, int &last_flat, + int &half_fold_left, int &half_fold_right); + void SaveLast(); SwitcherModel::Ptr model_; ui::LayoutSystem layout_system_; @@ -130,6 +126,8 @@ private: timespec save_time_; glib::Source::UniquePtr redraw_idle_; + + friend class TestSwitcherView; }; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ab06f0896..14dd47a7c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -236,6 +236,7 @@ if (ENABLE_X_SUPPORT) test_static_cairo_text.cpp test_switcher_controller.cpp test_switcher_model.cpp + test_switcher_view.cpp test_texture_cache.cpp test_text_input.cpp test_thumbnail_generator.cpp diff --git a/tests/test_switcher_controller.cpp b/tests/test_switcher_controller.cpp index f73f4caa2..1735eb0e2 100644 --- a/tests/test_switcher_controller.cpp +++ b/tests/test_switcher_controller.cpp @@ -60,8 +60,7 @@ TEST(TestSwitcherController, LazyConstructionTimeoutLength) EXPECT_EQ(controller.GetConstructTimeout(), DEFAULT_LAZY_CONSTRUCT_TIMEOUT); } -/* -TEST(TestSwitcherController, LazyWindowConstruction) +TEST(TestSwitcherController, DISABLED_LazyWindowConstruction) { // Setting the timeout to a lower value to speed-up the test StubSwitcherController controller(2); @@ -78,7 +77,6 @@ TEST(TestSwitcherController, LazyWindowConstruction) Utils::WaitUntil(controller.window_constructed_, controller.GetConstructTimeout() + 1); EXPECT_TRUE(controller.window_constructed_); } -*/ TEST(TestSwitcherController, InitialDetailTimeout) { diff --git a/tests/test_switcher_view.cpp b/tests/test_switcher_view.cpp new file mode 100644 index 000000000..5658f6a9f --- /dev/null +++ b/tests/test_switcher_view.cpp @@ -0,0 +1,198 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> + * + */ + +#include <gtest/gtest.h> + +#include "SwitcherModel.h" +#include "SwitcherView.h" +#include "MockLauncherIcon.h" +#include "StandaloneWindowManager.h" +#include "unity-shared/IconRenderer.h" +#include "unity-shared/UnitySettings.h" + +namespace unity +{ +using namespace launcher; +namespace switcher +{ +namespace +{ + struct MockMockLauncherIcon : MockLauncherIcon + { + WindowList Windows() { return windows_; } + void AddWindow(Window xid) { windows_.push_back(std::make_shared<MockApplicationWindow>(xid)); } + + WindowList windows_; + }; + + int rand_coord() { return g_random_int_range(1, 1024); } +} + +struct TestSwitcherView : testing::Test +{ + TestSwitcherView() + : WM(dynamic_cast<StandaloneWindowManager*>(&WindowManager::Default())) + {} + + struct MockSwitcherView : SwitcherView + { + using SwitcherView::UpdateRenderTargets; + using SwitcherView::ResizeRenderTargets; + using SwitcherView::SpreadSize; + using SwitcherView::text_view_; + using SwitcherView::icon_renderer_; + using SwitcherView::model_; + }; + + StandaloneWindow::Ptr AddFakeWindowToWM(Window xid) + { + const unsigned top_deco = 5; + auto fake_window = std::make_shared<StandaloneWindow>(xid); + fake_window->geo = nux::Geometry(rand_coord(), rand_coord(), rand_coord(), rand_coord()); + fake_window->deco_sizes[unsigned(WindowManager::Edge::TOP)] = nux::Size(fake_window->geo.width, top_deco); + + WM->AddStandaloneWindow(fake_window); + + return fake_window; + } + + AbstractLauncherIcon::Ptr AddFakeApplicationToSwitcher(unsigned num_of_windows = 5) + { + MockMockLauncherIcon* app = new MockMockLauncherIcon(); + + for (unsigned i = 0; i < num_of_windows; ++i) + { + Window xid = g_random_int(); + AddFakeWindowToWM(xid); + app->AddWindow(xid); + } + + SwitcherModel::Applications apps; + apps.push_back(AbstractLauncherIcon::Ptr(app)); + switcher.SetModel(std::make_shared<SwitcherModel>(apps)); + + return apps[0]; + } + + StandaloneWindowManager* WM; + unity::Settings settings; + MockSwitcherView switcher; +}; + +TEST_F(TestSwitcherView, Initiate) +{ + EXPECT_FALSE(switcher.render_boxes); + EXPECT_EQ(switcher.border_size, 50); + EXPECT_EQ(switcher.flat_spacing, 10); + EXPECT_EQ(switcher.icon_size, 128); + EXPECT_EQ(switcher.minimum_spacing, 10); + EXPECT_EQ(switcher.tile_size, 150); + EXPECT_EQ(switcher.vertical_size, switcher.tile_size + 80); + EXPECT_EQ(switcher.text_size, 15); + EXPECT_EQ(switcher.animation_length, 250); + EXPECT_EQ(switcher.monitor, -1); + EXPECT_EQ(switcher.spread_size, 3.5f); + ASSERT_NE(switcher.text_view_, nullptr); + ASSERT_NE(switcher.icon_renderer_, nullptr); + EXPECT_EQ(switcher.icon_renderer_->pip_style, ui::OVER_TILE); +} + +TEST_F(TestSwitcherView, SetModel) +{ + SwitcherModel::Applications apps; + apps.push_back(AbstractLauncherIcon::Ptr(new MockLauncherIcon())); + apps.push_back(AbstractLauncherIcon::Ptr(new MockLauncherIcon())); + apps.push_back(AbstractLauncherIcon::Ptr(new MockLauncherIcon())); + auto model = std::make_shared<SwitcherModel>(apps); + + switcher.SetModel(model); + ASSERT_EQ(switcher.model_, model); + ASSERT_EQ(switcher.GetModel(), model); + EXPECT_FALSE(switcher.model_->selection_changed.empty()); + EXPECT_FALSE(switcher.model_->detail_selection.changed.empty()); + EXPECT_FALSE(switcher.model_->detail_selection_index.changed.empty()); +} + +TEST_F(TestSwitcherView, UpdateRenderTargets) +{ + float progress = 0.55; + + AddFakeApplicationToSwitcher(); + auto const& model = switcher.GetModel(); + + switcher.UpdateRenderTargets(progress); + auto const& render_targets = switcher.ExternalTargets(); + + ASSERT_EQ(render_targets.size(), model->DetailXids().size()); + + for (Window xid : model->DetailXids()) + { + auto win_it = std::find_if (render_targets.begin(), render_targets.end(), + [xid] (ui::LayoutWindow::Ptr const& win) { return win->xid == xid; }); + + ASSERT_NE(win_it, render_targets.end()); + auto const& layout_win = *win_it; + bool should_be_selected = (xid == model->DetailSelectionWindow()); + ASSERT_EQ(layout_win->selected, should_be_selected); + ASSERT_EQ(layout_win->alpha, (should_be_selected ? 1.0f : 0.9f) * progress); + } +} + +TEST_F(TestSwitcherView, ResizeRenderTargets) +{ + AddFakeApplicationToSwitcher(); + + for (float progress = 0.1f; progress <= 1.0f; progress += 0.1f) + { + auto const& layout_geo = switcher.UpdateRenderTargets(progress); + std::map<Window, nux::Geometry> old_thumbs; + + for (auto const& win : switcher.ExternalTargets()) + old_thumbs[win->xid] = win->result; + + float to_finish = 1.0f - progress; + nux::Point layout_abs_center((layout_geo.x + layout_geo.width/2.0f) * to_finish, + (layout_geo.y + layout_geo.height/2.0f) * to_finish); + + switcher.ResizeRenderTargets(layout_geo, progress); + + for (auto const& win : switcher.ExternalTargets()) + { + auto const& thumb_geo = win->result; + auto const& old_thumb_geo = old_thumbs[win->xid]; + + nux::Geometry expected_geo; + expected_geo.x = old_thumb_geo.x * progress + layout_abs_center.x; + expected_geo.y = old_thumb_geo.y * progress + layout_abs_center.y; + expected_geo.width = old_thumb_geo.width * progress; + expected_geo.height = old_thumb_geo.height * progress; + + // Like ASSERT_EQ(thumb_geo, expected_geo), but more informative on failure + ASSERT_EQ(thumb_geo.x, expected_geo.x); + ASSERT_EQ(thumb_geo.y, expected_geo.y); + ASSERT_EQ(thumb_geo.width, expected_geo.width); + ASSERT_EQ(thumb_geo.height, expected_geo.height); + ASSERT_EQ(thumb_geo, expected_geo); + } + } +} + +} +} |
