summaryrefslogtreecommitdiff
diff options
-rw-r--r--launcher/SwitcherModel.h4
-rw-r--r--launcher/SwitcherView.cpp78
-rw-r--r--launcher/SwitcherView.h26
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/test_switcher_controller.cpp4
-rw-r--r--tests/test_switcher_view.cpp198
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(&current, &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(&current, &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, &current_);
+ DeltaTime ms_since_change = TimeUtil::TimeDelta(&current_, &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);
+ }
+ }
+}
+
+}
+}