summaryrefslogtreecommitdiff
diff options
authorJussi Pakkanen <jussi.pakkanen@canonical.com>2012-12-04 17:18:32 +0200
committerJussi Pakkanen <jussi.pakkanen@canonical.com>2012-12-04 17:18:32 +0200
commita1d64289da408e4452458f6dbf41105a1432554e (patch)
treee100f849375990ca59dc20e328ba3080568ffc2e
parent0c7afea16da13ad4e959b8066839b29637b0e43d (diff)
parent3703413309e0baf15af6e39908090585d3d0b13a (diff)
Merged with trunk.
(bzr r2934.3.6)
-rw-r--r--CMakeLists.txt19
-rw-r--r--UnityCore/AppmenuIndicator.cpp4
-rw-r--r--UnityCore/AppmenuIndicator.h4
-rw-r--r--UnityCore/DBusIndicators.cpp126
-rw-r--r--UnityCore/DBusIndicators.h12
-rw-r--r--UnityCore/Indicator.cpp11
-rw-r--r--UnityCore/Indicator.h8
-rw-r--r--UnityCore/IndicatorEntry.cpp12
-rw-r--r--UnityCore/IndicatorEntry.h10
-rw-r--r--UnityCore/Indicators.h15
-rw-r--r--dash/previews/ActionLink.cpp248
-rw-r--r--dash/previews/ActionLink.h100
-rw-r--r--dash/previews/CMakeLists.txt1
-rw-r--r--dash/previews/PreviewContainer.cpp2
-rw-r--r--dash/previews/StandaloneApplicationPreview.cpp7
-rw-r--r--hud/HudController.cpp54
-rw-r--r--launcher/AbstractLauncherIcon.h3
-rw-r--r--launcher/ApplicationLauncherIcon.cpp548
-rw-r--r--launcher/ApplicationLauncherIcon.h15
-rw-r--r--launcher/CMakeLists.txt10
-rw-r--r--launcher/ExpoLauncherIcon.cpp48
-rw-r--r--launcher/ExpoLauncherIcon.h7
-rw-r--r--launcher/Launcher.cpp28
-rw-r--r--launcher/LauncherController.cpp82
-rw-r--r--launcher/LauncherControllerPrivate.h6
-rw-r--r--launcher/LauncherIcon.cpp2
-rw-r--r--launcher/LauncherIcon.h2
-rw-r--r--launcher/LauncherModel.h3
-rw-r--r--launcher/MockLauncherIcon.h41
-rw-r--r--launcher/SoftwareCenterLauncherIcon.cpp23
-rw-r--r--launcher/SoftwareCenterLauncherIcon.h3
-rw-r--r--launcher/SwitcherController.cpp6
-rw-r--r--launcher/SwitcherModel.cpp5
-rw-r--r--launcher/SwitcherView.cpp6
-rw-r--r--panel/PanelIndicatorEntryView.cpp9
-rw-r--r--panel/PanelMenuView.cpp2
-rw-r--r--panel/PanelView.cpp7
-rw-r--r--panel/PanelView.h3
-rw-r--r--plugins/unityshell/CMakeLists.txt2
-rw-r--r--plugins/unityshell/src/ElapsedTimeMonitor.cpp2
-rw-r--r--plugins/unityshell/src/unityshell.cpp10
-rw-r--r--services/panel-main.c76
-rw-r--r--services/panel-service.c24
-rw-r--r--services/panel-service.h49
-rw-r--r--tests/CMakeLists.txt8
-rw-r--r--tests/autopilot/unity/emulators/dash.py5
-rw-r--r--tests/autopilot/unity/emulators/launcher.py15
-rw-r--r--tests/autopilot/unity/emulators/unity.py5
-rw-r--r--tests/autopilot/unity/tests/launcher/test_keynav.py5
-rw-r--r--tests/autopilot/unity/tests/test_hud.py12
-rw-r--r--tests/logger_helper.cpp100
-rw-r--r--tests/logger_helper.h50
-rw-r--r--tests/mock-application.cpp32
-rw-r--r--tests/mock-application.h150
-rw-r--r--tests/test_action_link.cpp188
-rw-r--r--tests/test_animator.cpp46
-rw-r--r--tests/test_application_launcher_icon.cpp66
-rw-r--r--tests/test_expo_launcher_icon.cpp73
-rw-r--r--tests/test_glib_source.cpp39
-rw-r--r--tests/test_indicator.cpp19
-rw-r--r--tests/test_indicator_appmenu.cpp9
-rw-r--r--tests/test_indicator_entry.cpp11
-rw-r--r--tests/test_indicators.cpp38
-rw-r--r--tests/test_launcher_controller.cpp116
-rw-r--r--tests/test_main.cpp5
-rw-r--r--tests/test_mock_devices.h6
-rw-r--r--tests/test_previews_application.cpp2
-rw-r--r--tests/test_previews_generic.cpp2
-rw-r--r--tests/test_previews_movie.cpp2
-rw-r--r--tests/test_previews_music.cpp2
-rw-r--r--tests/test_previews_social.cpp3
-rw-r--r--tests/test_static_cairo_text.cpp73
-rw-r--r--tests/test_time_util.cpp36
-rw-r--r--unity-shared/ApplicationManager.cpp47
-rw-r--r--unity-shared/ApplicationManager.h142
-rw-r--r--unity-shared/BamfApplicationManager.cpp662
-rw-r--r--unity-shared/BamfApplicationManager.h173
-rw-r--r--unity-shared/BamfApplicationManagerFactory.cpp31
-rw-r--r--unity-shared/CMakeLists.txt13
-rw-r--r--unity-shared/PluginAdapter.cpp16
-rw-r--r--unity-shared/PluginAdapter.h4
-rw-r--r--unity-shared/StandaloneAppManager.cpp245
-rw-r--r--unity-shared/StandaloneWindowManager.cpp25
-rw-r--r--unity-shared/StandaloneWindowManager.h7
-rw-r--r--unity-shared/StaticCairoText.cpp225
-rw-r--r--unity-shared/StaticCairoText.h13
-rw-r--r--unity-shared/TimeUtil.h17
-rw-r--r--unity-shared/WindowManager.h5
-rw-r--r--unity-standalone/CMakeLists.txt1
89 files changed, 3335 insertions, 1064 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fe91b4afe..cd90a6dc4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,25 @@ else ()
set (UNITY_STANDALONE_LADD "-lunity-core-${UNITY_API_VERSION} -lm -lpthread -ldl -lGL -lGLU")
endif ()
+if (CMAKE_BUILD_TYPE MATCHES coverage)
+ set (COVERAGE_XML_FILE "${CMAKE_BINARY_DIR}/coverage.xml")
+
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage" )
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage" )
+ set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage" )
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage" )
+
+ find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin")
+ if (NOT GCOVR_EXECUTABLE)
+ message(FATAL_ERROR "Cannot enable coverage targets because gcovr was not found.")
+ else ()
+ message (STATUS "Enabling XML coverage report")
+ add_custom_target (coverage-xml
+ COMMAND "${GCOVR_EXECUTABLE}" --exclude="tests.*" --exclude="obj-.*" -x -r "${CMAKE_SOURCE_DIR}" -o "${COVERAGE_XML_FILE}")
+ endif()
+endif (CMAKE_BUILD_TYPE MATCHES coverage)
+
+
#
# Niceties
#
diff --git a/UnityCore/AppmenuIndicator.cpp b/UnityCore/AppmenuIndicator.cpp
index 5ddbacd8d..ea1ba90cd 100644
--- a/UnityCore/AppmenuIndicator.cpp
+++ b/UnityCore/AppmenuIndicator.cpp
@@ -28,9 +28,9 @@ AppmenuIndicator::AppmenuIndicator(std::string const& name)
: Indicator(name)
{}
-void AppmenuIndicator::ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const
+void AppmenuIndicator::ShowAppmenu(unsigned int xid, int x, int y) const
{
- on_show_appmenu.emit(xid, x, y, timestamp);
+ on_show_appmenu.emit(xid, x, y);
}
} // namespace indicator
diff --git a/UnityCore/AppmenuIndicator.h b/UnityCore/AppmenuIndicator.h
index 7393c60af..38ec62f17 100644
--- a/UnityCore/AppmenuIndicator.h
+++ b/UnityCore/AppmenuIndicator.h
@@ -34,9 +34,9 @@ public:
virtual bool IsAppmenu() const { return true; }
- void ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const;
+ void ShowAppmenu(unsigned xid, int x, int y) const;
- sigc::signal<void, unsigned int, int, int, unsigned int> on_show_appmenu;
+ sigc::signal<void, unsigned, int, int> on_show_appmenu;
};
}
diff --git a/UnityCore/DBusIndicators.cpp b/UnityCore/DBusIndicators.cpp
index 8432c7ddb..9c659b92d 100644
--- a/UnityCore/DBusIndicators.cpp
+++ b/UnityCore/DBusIndicators.cpp
@@ -65,12 +65,9 @@ public:
virtual void OnEntryScroll(std::string const& entry_id, int delta);
virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
- int x, int y, unsigned int button,
- unsigned int timestamp);
- virtual void OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp);
- virtual void OnShowAppMenu(unsigned int xid, int x, int y,
- unsigned int timestamp);
+ int x, int y, unsigned int button);
+ virtual void OnEntrySecondaryActivate(std::string const& entry_id);
+ virtual void OnShowAppMenu(unsigned int xid, int x, int y);
DBusIndicators* owner_;
@@ -189,7 +186,7 @@ void DBusIndicators::Impl::OnEntryActivatedRequest(GVariant* parameters)
void DBusIndicators::Impl::OnEntryShowNowChanged(GVariant* parameters)
{
glib::String entry_name;
- gboolean show_now;
+ gboolean show_now;
g_variant_get(parameters, "(sb)", &entry_name, &show_now);
if (entry_name)
@@ -211,43 +208,40 @@ void DBusIndicators::Impl::RequestSyncIndicator(std::string const& name)
void DBusIndicators::Impl::OnEntryShowMenu(std::string const& entry_id,
unsigned int xid, int x, int y,
- unsigned int button,
- unsigned int timestamp)
+ unsigned int button)
{
- owner_->on_entry_show_menu.emit(entry_id, xid, x, y, button, timestamp);
+ owner_->on_entry_show_menu.emit(entry_id, xid, x, y, button);
// We have to do this because on certain systems X won't have time to
// respond to our request for XUngrabPointer and this will cause the
// menu not to show
show_entry_idle_.reset(new glib::Idle(glib::Source::Priority::DEFAULT));
- show_entry_idle_->Run([&, entry_id, xid, x, y, button, timestamp] {
- gproxy_.Call("ShowEntry", g_variant_new("(suiiuu)", entry_id.c_str(), xid,
- x, y, button, timestamp));
+ show_entry_idle_->Run([&, entry_id, xid, x, y, button] {
+ gproxy_.Call("ShowEntry", g_variant_new("(suiiu)", entry_id.c_str(), xid,
+ x, y, button));
return false;
});
}
-void DBusIndicators::Impl::OnShowAppMenu(unsigned int xid, int x, int y,
- unsigned int timestamp)
+void DBusIndicators::Impl::OnShowAppMenu(unsigned int xid, int x, int y)
{
- owner_->on_show_appmenu.emit(xid, x, y, timestamp);
+ owner_->on_show_appmenu.emit(xid, x, y);
// We have to do this because on certain systems X won't have time to
// respond to our request for XUngrabPointer and this will cause the
// menu not to show
show_entry_idle_.reset(new glib::Idle(glib::Source::Priority::DEFAULT));
- show_entry_idle_->Run([&, xid, x, y, timestamp] {
- gproxy_.Call("ShowEntry", g_variant_new("(uiiu)", xid, x, y, timestamp));
+ show_entry_idle_->Run([&, xid, x, y] {
+ gproxy_.Call("ShowEntry", g_variant_new("(uii)", xid, x, y));
return false;
});
}
-void DBusIndicators::Impl::OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp)
+void DBusIndicators::Impl::OnEntrySecondaryActivate(std::string const& entry_id)
{
- gproxy_.Call("SecondaryActivateEntry", g_variant_new("(su)", entry_id.c_str(), timestamp));
+ gproxy_.Call("SecondaryActivateEntry", g_variant_new("(s)", entry_id.c_str()));
}
void DBusIndicators::Impl::OnEntryScroll(std::string const& entry_id, int delta)
@@ -257,6 +251,9 @@ void DBusIndicators::Impl::OnEntryScroll(std::string const& entry_id, int delta)
void DBusIndicators::Impl::Sync(GVariant* args)
{
+ if (!args)
+ return;
+
GVariantIter* iter = nullptr;
gchar* name_hint = nullptr;
gchar* indicator_id = nullptr;
@@ -270,13 +267,9 @@ void DBusIndicators::Impl::Sync(GVariant* args)
gboolean image_visible = false;
gint32 priority = -1;
- // sanity check
- if (!args)
- return;
-
std::map<Indicator::Ptr, Indicator::Entries> indicators;
- int wantedIndex = 0;
- bool anyIndexDifferent = false;
+ int wanted_idx = 0;
+ bool any_different_idx = false;
g_variant_get(args, "(a(ssssbbusbbi))", &iter);
while (g_variant_iter_loop(iter, "(ssssbbusbbi)",
@@ -292,8 +285,8 @@ void DBusIndicators::Impl::Sync(GVariant* args)
&image_visible,
&priority))
{
- std::string entry(entry_id);
- std::string indicator_name(indicator_id);
+ std::string entry(G_LIKELY(entry_id) ? entry_id : "");
+ std::string indicator_name(G_LIKELY(indicator_id) ? indicator_id : "");
Indicator::Ptr indicator = owner_->GetIndicator(indicator_name);
if (!indicator)
@@ -303,20 +296,23 @@ void DBusIndicators::Impl::Sync(GVariant* args)
Indicator::Entries& entries = indicators[indicator];
- // Null entries (entry_id == "") are empty indicators.
- if (entry != "")
+ // Empty entries are empty indicators.
+ if (!entry.empty())
{
Entry::Ptr e;
- if (!anyIndexDifferent)
+ if (!any_different_idx)
{
// Indicators can only add or remove entries, so if
// there is a index change we can't reuse the existing ones
// after that index
- int existingEntryIndex = indicator->EntryIndex(entry_id);
- if (wantedIndex == existingEntryIndex)
+ if (indicator->EntryIndex(entry_id) == wanted_idx)
+ {
e = indicator->GetEntry(entry_id);
+ }
else
- anyIndexDifferent = true;
+ {
+ any_different_idx = true;
+ }
}
if (!e)
@@ -333,7 +329,7 @@ void DBusIndicators::Impl::Sync(GVariant* args)
}
entries.push_back(e);
- wantedIndex++;
+ ++wanted_idx;
}
}
g_variant_iter_free(iter);
@@ -350,45 +346,39 @@ void DBusIndicators::Impl::Sync(GVariant* args)
void DBusIndicators::Impl::SyncGeometries(std::string const& name,
EntryLocationMap const& locations)
{
- if (!gproxy_.IsConnected())
+ if (!gproxy_.IsConnected() || G_UNLIKELY(name.empty()))
return;
- GVariantBuilder b;
bool found_changed_locations = false;
- g_variant_builder_init(&b, G_VARIANT_TYPE("(a(ssiiii))"));
- g_variant_builder_open(&b, G_VARIANT_TYPE("a(ssiiii)"));
- EntryLocationMap& cached_loc = cached_locations_[name];
+ EntryLocationMap& cached_locations = cached_locations_[name];
+
+ GVariantBuilder b;
+ g_variant_builder_init(&b, G_VARIANT_TYPE("(sa(siiii))"));
+ g_variant_builder_add(&b, "s", name.c_str());
+
+ g_variant_builder_open(&b, G_VARIANT_TYPE("a(siiii)"));
// Only send to panel service the geometries of items that have changed
- for (auto i = locations.begin(), end = locations.end(); i != end; ++i)
+ for (auto const& location : locations)
{
- auto rect = i->second;
+ auto const& id = location.first;
+ auto const& rect = location.second;
- if (cached_loc[i->first] != rect)
+ if (cached_locations[id] != rect)
{
- g_variant_builder_add(&b, "(ssiiii)",
- name.c_str(),
- i->first.c_str(),
- rect.x,
- rect.y,
- rect.width,
- rect.height);
+ g_variant_builder_add(&b, "(siiii)", id.c_str(), rect.x, rect.y, rect.width, rect.height);
found_changed_locations = true;
}
}
// Inform panel service of the entries that have been removed sending invalid values
- for (auto i = cached_loc.begin(), end = cached_loc.end(); i != end; ++i)
+ for (auto const& location : cached_locations)
{
- if (locations.find(i->first) == locations.end())
+ auto const& id = location.first;
+
+ if (locations.find(id) == locations.end())
{
- g_variant_builder_add(&b, "(ssiiii)",
- name.c_str(),
- i->first.c_str(),
- 0,
- 0,
- -1,
- -1);
+ g_variant_builder_add(&b, "(siiii)", id.c_str(), 0, 0, -1, -1);
found_changed_locations = true;
}
}
@@ -402,7 +392,7 @@ void DBusIndicators::Impl::SyncGeometries(std::string const& name,
g_variant_builder_close(&b);
gproxy_.Call("SyncGeometries", g_variant_builder_end(&b));
- cached_loc = locations;
+ cached_locations = locations;
}
DBusIndicators::DBusIndicators()
@@ -434,21 +424,19 @@ void DBusIndicators::OnEntryScroll(std::string const& entry_id, int delta)
void DBusIndicators::OnEntryShowMenu(std::string const& entry_id,
unsigned int xid, int x, int y,
- unsigned int button, unsigned int timestamp)
+ unsigned int button)
{
- pimpl->OnEntryShowMenu(entry_id, xid, x, y, button, timestamp);
+ pimpl->OnEntryShowMenu(entry_id, xid, x, y, button);
}
-void DBusIndicators::OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp)
+void DBusIndicators::OnEntrySecondaryActivate(std::string const& entry_id)
{
- pimpl->OnEntrySecondaryActivate(entry_id, timestamp);
+ pimpl->OnEntrySecondaryActivate(entry_id);
}
-void DBusIndicators::OnShowAppMenu(unsigned int xid, int x, int y,
- unsigned int timestamp)
+void DBusIndicators::OnShowAppMenu(unsigned int xid, int x, int y)
{
- pimpl->OnShowAppMenu(xid, x, y, timestamp);
+ pimpl->OnShowAppMenu(xid, x, y);
}
} // namespace indicator
diff --git a/UnityCore/DBusIndicators.h b/UnityCore/DBusIndicators.h
index 5ac1111c8..fe5dbc178 100644
--- a/UnityCore/DBusIndicators.h
+++ b/UnityCore/DBusIndicators.h
@@ -38,17 +38,13 @@ public:
DBusIndicators();
~DBusIndicators();
- void SyncGeometries(std::string const& name,
- EntryLocationMap const& locations);
+ void SyncGeometries(std::string const& name, EntryLocationMap const& locations);
virtual void OnEntryScroll(std::string const& entry_id, int delta);
virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
- int x, int y, unsigned int button,
- unsigned int timestamp);
- virtual void OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp);
- virtual void OnShowAppMenu(unsigned int xid, int x, int y,
- unsigned int timestamp);
+ int x, int y, unsigned int button);
+ virtual void OnEntrySecondaryActivate(std::string const& entry_id);
+ virtual void OnShowAppMenu(unsigned int xid, int x, int y);
protected:
DBusIndicators(std::string const& dbus_name);
diff --git a/UnityCore/Indicator.cpp b/UnityCore/Indicator.cpp
index 688d3c110..42d8bb675 100644
--- a/UnityCore/Indicator.cpp
+++ b/UnityCore/Indicator.cpp
@@ -130,16 +130,15 @@ int Indicator::EntryIndex(std::string const& entry_id) const
return -1;
}
-void Indicator::OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
- int x, int y, unsigned int button, unsigned int timestamp)
+void Indicator::OnEntryShowMenu(std::string const& entry_id, unsigned xid,
+ int x, int y, unsigned button)
{
- on_show_menu.emit(entry_id, xid, x, y, button, timestamp);
+ on_show_menu.emit(entry_id, xid, x, y, button);
}
-void Indicator::OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp)
+void Indicator::OnEntrySecondaryActivate(std::string const& entry_id)
{
- on_secondary_activate.emit(entry_id, timestamp);
+ on_secondary_activate.emit(entry_id);
}
void Indicator::OnEntryScroll(std::string const& entry_id, int delta)
diff --git a/UnityCore/Indicator.h b/UnityCore/Indicator.h
index 23b4bd575..682c4d1e0 100644
--- a/UnityCore/Indicator.h
+++ b/UnityCore/Indicator.h
@@ -54,13 +54,13 @@ public:
// Signals
sigc::signal<void, Entry::Ptr const&> on_entry_added;
sigc::signal<void, std::string const&> on_entry_removed;
- sigc::signal<void, std::string const&, unsigned int, int, int, unsigned int, unsigned int> on_show_menu;
- sigc::signal<void, std::string const&, unsigned int> on_secondary_activate;
+ sigc::signal<void, std::string const&, unsigned, int, int, unsigned> on_show_menu;
+ sigc::signal<void, std::string const&> on_secondary_activate;
sigc::signal<void, std::string const&, int> on_scroll;
protected:
- void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, int x, int y, unsigned int button, unsigned int timestamp);
- void OnEntrySecondaryActivate(std::string const& entry_id, unsigned int timestamp);
+ void OnEntryShowMenu(std::string const& entry_id, unsigned xid, int x, int y, unsigned button);
+ void OnEntrySecondaryActivate(std::string const& entry_id);
void OnEntryScroll(std::string const& entry_id, int delta);
Entries entries_;
diff --git a/UnityCore/IndicatorEntry.cpp b/UnityCore/IndicatorEntry.cpp
index 34784841b..63a7ec415 100644
--- a/UnityCore/IndicatorEntry.cpp
+++ b/UnityCore/IndicatorEntry.cpp
@@ -205,19 +205,19 @@ void Entry::set_show_now(bool show_now)
updated.emit();
}
-void Entry::ShowMenu(int x, int y, unsigned int button, unsigned int timestamp)
+void Entry::ShowMenu(int x, int y, unsigned button)
{
- ShowMenu(0, x, y, button, timestamp);
+ ShowMenu(0, x, y, button);
}
-void Entry::ShowMenu(unsigned int xid, int x, int y, unsigned int button, unsigned int timestamp)
+void Entry::ShowMenu(unsigned int xid, int x, int y, unsigned button)
{
- on_show_menu.emit(id_, xid, x, y, button, timestamp);
+ on_show_menu.emit(id_, xid, x, y, button);
}
-void Entry::SecondaryActivate(unsigned int timestamp)
+void Entry::SecondaryActivate()
{
- on_secondary_activate.emit(id_, timestamp);
+ on_secondary_activate.emit(id_);
}
void Entry::Scroll(int delta)
diff --git a/UnityCore/IndicatorEntry.h b/UnityCore/IndicatorEntry.h
index 73928be8e..ffe1b0414 100644
--- a/UnityCore/IndicatorEntry.h
+++ b/UnityCore/IndicatorEntry.h
@@ -85,9 +85,9 @@ public:
bool show_now() const;
void set_show_now(bool show_now);
- void ShowMenu(int x, int y, unsigned int button, unsigned int timestamp);
- void ShowMenu(unsigned int xid, int x, int y, unsigned int button, unsigned int timestamp);
- void SecondaryActivate(unsigned int timestamp);
+ void ShowMenu(int x, int y, unsigned button);
+ void ShowMenu(unsigned int xid, int x, int y, unsigned button);
+ void SecondaryActivate();
void Scroll(int delta);
void setLabel(std::string const& label, bool sensitive, bool visible);
@@ -100,8 +100,8 @@ public:
sigc::signal<void, nux::Rect const&> geometry_changed;
sigc::signal<void, bool> show_now_changed;
- sigc::signal<void, std::string const&, unsigned int, int, int, unsigned int, unsigned int> on_show_menu;
- sigc::signal<void, std::string const&, unsigned int> on_secondary_activate;
+ sigc::signal<void, std::string const&, unsigned, int, int, unsigned> on_show_menu;
+ sigc::signal<void, std::string const&> on_secondary_activate;
sigc::signal<void, std::string const&, int> on_scroll;
private:
diff --git a/UnityCore/Indicators.h b/UnityCore/Indicators.h
index 024f0c2f6..53b4d004f 100644
--- a/UnityCore/Indicators.h
+++ b/UnityCore/Indicators.h
@@ -59,20 +59,17 @@ public:
* internal
*/
virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
- int x, int y, unsigned int button,
- unsigned int timestamp) = 0;
+ int x, int y, unsigned int button) = 0;
/**
* internal
*/
- virtual void OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp) = 0;
+ virtual void OnEntrySecondaryActivate(std::string const& entry_id) = 0;
/**
* internal
*/
- virtual void OnShowAppMenu(unsigned int xid, int x, int y,
- unsigned int timestamp) = 0;
+ virtual void OnShowAppMenu(unsigned int xid, int x, int y) = 0;
// Signals
sigc::signal<void, Indicator::Ptr const&> on_object_added;
@@ -104,18 +101,16 @@ public:
* @param x coordinate
* @param y coordinate
* @param button pressed button
- * @param timestamp current time
*/
- sigc::signal<void, std::string const&, unsigned int, int, int, unsigned int, unsigned int> on_entry_show_menu;
+ sigc::signal<void, std::string const&, unsigned, int, int, unsigned> on_entry_show_menu;
/**
* The service is about to show an appmenu.
* @param xid window xid
* @param x coordinate
* @param y coordinate
- * @param timestamp current time
*/
- sigc::signal<void, unsigned int, int, int, unsigned int> on_show_appmenu;
+ sigc::signal<void, unsigned, int, int> on_show_appmenu;
protected:
Indicator::Ptr GetIndicator(std::string const& name);
diff --git a/dash/previews/ActionLink.cpp b/dash/previews/ActionLink.cpp
new file mode 100644
index 000000000..c7eb7c5f0
--- /dev/null
+++ b/dash/previews/ActionLink.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser 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 applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser General Public
+ * License version 3 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authored by: Manuel de la Pena <manuel.delapena@canonical.com>
+ *
+ */
+
+#include "ActionLink.h"
+#include <NuxCore/Logger.h>
+#include <Nux/VLayout.h>
+#include <UnityCore/Variant.h>
+#include "unity-shared/DashStyle.h"
+#include "unity-shared/IconTexture.h"
+#include "unity-shared/StaticCairoText.h"
+
+namespace
+{
+nux::logging::Logger logger("unity.dash.actionlink");
+const double LINK_NORMAL_ALPHA_VALUE = 4;
+const double LINK_HIGHLIGHTED_ALPHA_VALUE = 1;
+}
+
+namespace unity
+{
+namespace dash
+{
+
+ActionLink::ActionLink(std::string const& action_hint, std::string const& label, NUX_FILE_LINE_DECL)
+ : nux::AbstractButton(NUX_FILE_LINE_PARAM)
+ , action_hint_(action_hint)
+ , aligment_(nux::StaticCairoText::NUX_ALIGN_CENTRE)
+ , underline_(nux::StaticCairoText::NUX_UNDERLINE_SINGLE)
+{
+ Init();
+ BuildLayout(label);
+}
+
+std::string ActionLink::GetName() const
+{
+ return "ActionLink";
+}
+
+void ActionLink::AddProperties(GVariantBuilder* builder)
+{
+ variant::BuilderWrapper(builder)
+ .add(GetAbsoluteGeometry())
+ .add("action", action_hint_)
+ .add("label", label_)
+ .add("font-hint", font_hint)
+ .add("active", active_)
+ .add("text-aligment", text_aligment)
+ .add("underline-state", underline_state);
+}
+
+void ActionLink::Init()
+{
+ SetAcceptKeyNavFocusOnMouseDown(false);
+ SetAcceptKeyNavFocusOnMouseEnter(true);
+
+ // set properties to ensure that we do redraw when one of them changes
+ text_aligment.SetSetterFunction(sigc::mem_fun(this, &ActionLink::set_aligment));
+ text_aligment.SetGetterFunction(sigc::mem_fun(this, &ActionLink::get_aligment));
+
+ underline_state.SetSetterFunction(sigc::mem_fun(this, &ActionLink::set_underline));
+ underline_state.SetGetterFunction(sigc::mem_fun(this, &ActionLink::get_underline));
+
+ font_hint.SetSetterFunction(sigc::mem_fun(this, &ActionLink::set_font_hint));
+ font_hint.SetGetterFunction(sigc::mem_fun(this, &ActionLink::get_font_hint));
+
+ key_nav_focus_change.connect([&] (nux::Area*, bool, nux::KeyNavDirection)
+ {
+ QueueDraw();
+ });
+
+ key_nav_focus_activate.connect([&](nux::Area*)
+ {
+ if (GetInputEventSensitivity())
+ activate.emit(this, action_hint_);
+ });
+}
+
+void ActionLink::BuildLayout(std::string const& label)
+{
+
+ if (label != label_)
+ {
+ label_ = label;
+ if (static_text_)
+ {
+ static_text_.Release();
+ static_text_ = NULL;
+ }
+
+ if (!label_.empty())
+ {
+ static_text_ = new nux::StaticCairoText(label_, true, NUX_TRACKER_LOCATION);
+ if (!font_hint_.empty())
+ static_text_->SetFont(font_hint_);
+ static_text_->SetInputEventSensitivity(false);
+ static_text_->SetTextAlignment(aligment_);
+ static_text_->SetUnderline(underline_);
+ }
+ }
+
+ RemoveLayout();
+
+ nux::VLayout* layout = new nux::VLayout();
+ if (static_text_)
+ {
+ layout->AddView(static_text_.GetPointer(),
+ 1, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL,
+ 100.0f, nux::NUX_LAYOUT_END);
+ }
+ SetLayout(layout);
+
+ ComputeContentSize();
+ QueueDraw();
+}
+
+int ActionLink::GetLinkAlpha(nux::ButtonVisualState state)
+{
+ if (state == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT)
+ return LINK_HIGHLIGHTED_ALPHA_VALUE;
+ else
+ return LINK_NORMAL_ALPHA_VALUE;
+}
+
+void ActionLink::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+ nux::Geometry const& geo = GetGeometry();
+
+ gPainter.PaintBackground(GfxContext, geo);
+ // set up our texture mode
+ nux::TexCoordXForm texxform;
+ texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
+ texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
+
+ // clear what is behind us
+ unsigned int alpha = 0, src = 0, dest = 0;
+
+ // set the alpha of the text according to its state
+ static_text_->SetTextAlpha(GetLinkAlpha(GetVisualState()));
+
+ GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
+ GfxContext.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ nux::Color col = nux::color::Black;
+ col.alpha = 0;
+ GfxContext.QRP_Color(geo.x,
+ geo.y,
+ geo.width,
+ geo.height,
+ col);
+
+ GfxContext.GetRenderStates().SetBlend(alpha, src, dest);
+
+ if (GetCompositionLayout())
+ {
+ gPainter.PushPaintLayerStack();
+ {
+
+ GfxContext.PushClippingRectangle(geo);
+ gPainter.PushPaintLayerStack();
+ GetCompositionLayout()->ProcessDraw(GfxContext, force_draw);
+ gPainter.PopPaintLayerStack();
+ GfxContext.PopClippingRectangle();
+ }
+ gPainter.PopPaintLayerStack();
+ }
+}
+
+void ActionLink::RecvClick(int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ activate.emit(this, action_hint_);
+}
+
+bool ActionLink::set_aligment(nux::StaticCairoText::AlignState aligment)
+{
+ if(static_text_ && aligment_ != aligment)
+ {
+ static_text_->SetTextAlignment(aligment_);
+ aligment_ = aligment;
+ ComputeContentSize();
+ QueueDraw();
+ }
+ return true;
+}
+
+nux::StaticCairoText::AlignState ActionLink::get_aligment()
+{
+ return aligment_;
+}
+
+bool ActionLink::set_underline(nux::StaticCairoText::UnderlineState underline)
+{
+ if(static_text_ && underline_ != underline)
+ {
+ static_text_->SetUnderline(underline_);
+ underline_ = underline;
+ ComputeContentSize();
+ QueueDraw();
+ }
+ return true;
+}
+
+nux::StaticCairoText::UnderlineState ActionLink::get_underline()
+{
+ return underline_;
+}
+
+bool ActionLink::set_font_hint(std::string font_hint)
+{
+ if(static_text_ && font_hint_ != font_hint)
+ {
+ static_text_->SetFont(font_hint_);
+ font_hint_ = font_hint;
+ ComputeContentSize();
+ QueueDraw();
+ }
+ return true;
+}
+
+std::string ActionLink::get_font_hint()
+{
+ return font_hint_;
+}
+
+std::string ActionLink::GetLabel() const
+{
+ return label_;
+}
+
+} // namespace dash
+} // namespace unity
diff --git a/dash/previews/ActionLink.h b/dash/previews/ActionLink.h
new file mode 100644
index 000000000..8fb974e95
--- /dev/null
+++ b/dash/previews/ActionLink.h
@@ -0,0 +1,100 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser 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 applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser General Public
+ * License version 3 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authored by: Manuel de la Pena <manuel.delapena@canonical.com>
+ *
+ */
+
+#ifndef ACTIONLINK_H
+#define ACTIONLINK_H
+
+#include <Nux/Nux.h>
+#include <Nux/CairoWrapper.h>
+#include <Nux/AbstractButton.h>
+#include "unity-shared/Introspectable.h"
+#include "unity-shared/StaticCairoText.h"
+
+
+namespace unity
+{
+class IconTexture;
+
+namespace dash
+{
+
+class ActionLink : public nux::AbstractButton, public debug::Introspectable
+{
+public:
+ ActionLink(std::string const& action_hint, std::string const& label, NUX_FILE_LINE_PROTO);
+
+ sigc::signal<void, ActionLink*, std::string const&> activate;
+
+ nux::RWProperty<nux::StaticCairoText::AlignState> text_aligment;
+ nux::RWProperty<nux::StaticCairoText::UnderlineState> underline_state;
+ nux::RWProperty<std::string> font_hint;
+
+ void Activate() {}
+ void Deactivate() {}
+
+ virtual bool AcceptKeyNavFocus() const { return true; }
+
+ std::string GetLabel() const;
+ std::string GetExtraText() const;
+
+protected:
+ nux::ObjectPtr<nux::StaticCairoText> static_text_;
+
+ int GetLinkAlpha(nux::ButtonVisualState state);
+
+ void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
+ void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) {}
+ void RecvClick(int x, int y, unsigned long button_flags, unsigned long key_flags);
+
+ void Init();
+
+ void BuildLayout(std::string const& label);
+
+ // From debug::Introspectable
+ std::string GetName() const;
+ void AddProperties(GVariantBuilder* builder);
+
+ // this methods/vars could be private but are protected to make testing
+ // easier
+ bool set_aligment(nux::StaticCairoText::AlignState aligment);
+ nux::StaticCairoText::AlignState get_aligment();
+
+ bool set_underline(nux::StaticCairoText::UnderlineState underline);
+ nux::StaticCairoText::UnderlineState get_underline();
+
+ bool set_font_hint(std::string font_hint);
+ std::string get_font_hint();
+
+ std::string action_hint_;
+ std::string font_hint_;
+ nux::StaticCairoText::AlignState aligment_;
+ nux::StaticCairoText::UnderlineState underline_;
+private:
+ typedef std::unique_ptr<nux::CairoWrapper> NuxCairoPtr;
+
+
+};
+
+} // namespace dash
+} // namespace unity
+
+#endif // ACTIONLINK_H
diff --git a/dash/previews/CMakeLists.txt b/dash/previews/CMakeLists.txt
index ececae50e..bfa20d9d8 100644
--- a/dash/previews/CMakeLists.txt
+++ b/dash/previews/CMakeLists.txt
@@ -23,6 +23,7 @@ include_directories (.. ../services ../UnityCore ${UNITY_SRC} ${CMAKE_BINARY_DIR
#
set (PREVIEWS_SOURCES
ActionButton.cpp
+ ActionLink.cpp
ApplicationPreview.cpp
GenericPreview.cpp
MusicPreview.cpp
diff --git a/dash/previews/PreviewContainer.cpp b/dash/previews/PreviewContainer.cpp
index fa6dc7497..fc3e4b850 100644
--- a/dash/previews/PreviewContainer.cpp
+++ b/dash/previews/PreviewContainer.cpp
@@ -571,7 +571,7 @@ static float easeInOutQuart(float t)
float PreviewContainer::GetSwipeAnimationProgress(struct timespec const& current) const
{
- int time_delta = TimeUtil::TimeDelta(&current, &last_progress_time_);
+ DeltaTime time_delta = TimeUtil::TimeDelta(&current, &last_progress_time_);
float progress = content_layout_->GetAnimationProgress() + (navigation_progress_speed_ * time_delta);
return progress;
diff --git a/dash/previews/StandaloneApplicationPreview.cpp b/dash/previews/StandaloneApplicationPreview.cpp
index 324d35666..409785ecf 100644
--- a/dash/previews/StandaloneApplicationPreview.cpp
+++ b/dash/previews/StandaloneApplicationPreview.cpp
@@ -156,8 +156,9 @@ void TestRunner::Init ()
app_name << "Skype";
const char* subtitle = "Version 3.2, Size 32 MB";
- const char* description = "Skype is a proprietary voice-over-Internet Protocol service and software application originally created by Niklas Zennström and Janus Friis in 2003, and owned by Microsoft since 2011. \
-The service allows users to communicate with peers by voice, video, and instant messaging over the Internet. Phone calls may be placed to recipients on the traditional telephone networks. Calls to other users within the Skype service are free of charge, while calls to landline telephones and mobile phones are charged via a debit-based user account system.";
+ std::stringstream description;
+ for (int i = 0; i < 700; i++)
+ description << "Application description " << i << std::endl;
// creates a generic preview object
glib::Object<GIcon> iconHint1(g_icon_new_for_string("/usr/share/unity/5/lens-nav-music.svg", NULL));
@@ -179,7 +180,7 @@ The service allows users to communicate with peers by voice, video, and instant
unity_protocol_preview_set_image_source_uri(proto_obj, "file:///home/nick/Skype.png");
unity_protocol_preview_set_title(proto_obj, app_name.str().c_str());
unity_protocol_preview_set_subtitle(proto_obj, subtitle);
- unity_protocol_preview_set_description(proto_obj, description);
+ unity_protocol_preview_set_description(proto_obj, description.str().c_str());
unity_protocol_preview_add_action(proto_obj, "uninstall", "Uninstall", iconHint1, 0);
unity_protocol_preview_add_action_with_hints(proto_obj, "launch", "Download", iconHint2, 0, action_hints1);
unity_protocol_preview_add_info_hint(proto_obj, "time", "Total time", iconHint1, g_variant_new("s", "16 h 34miin 45sec"));
diff --git a/hud/HudController.cpp b/hud/HudController.cpp
index 484b1ce9f..0a264e692 100644
--- a/hud/HudController.cpp
+++ b/hud/HudController.cpp
@@ -22,13 +22,14 @@
#include <Nux/HLayout.h>
#include <UnityCore/Variant.h>
+#include "unity-shared/ApplicationManager.h"
#include "unity-shared/WindowManager.h"
#include "unity-shared/PanelStyle.h"
#include "unity-shared/UBusMessages.h"
#include "unity-shared/UScreen.h"
#include "config.h"
-#include <libbamf/libbamf.h>
+
namespace unity
{
@@ -313,52 +314,15 @@ void Controller::ShowHud()
view_->ShowEmbeddedIcon(!IsLockedToLauncher(monitor_index_));
view_->AboutToShow();
- // We first want to grab the currently active window
- glib::Object<BamfMatcher> matcher(bamf_matcher_get_default());
- BamfWindow* active_win = bamf_matcher_get_active_window(matcher);
-
- Window active_xid = bamf_window_get_xid(active_win);
- std::vector<Window> const& unity_xids = nux::XInputWindow::NativeHandleList();
-
- // If the active window is an unity window, we must get the top-most valid window
- if (std::find(unity_xids.begin(), unity_xids.end(), active_xid) != unity_xids.end())
- {
- // Windows list stack for all the monitors
- GList *windows = bamf_matcher_get_window_stack_for_monitor(matcher, -1);
-
- // Reset values, in case we can't find a window ie. empty current desktop
- active_xid = 0;
- active_win = nullptr;
-
- for (GList *l = windows; l; l = l->next)
- {
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- auto win = static_cast<BamfWindow*>(l->data);
- auto view = static_cast<BamfView*>(l->data);
- Window xid = bamf_window_get_xid(win);
-
- if (bamf_view_is_user_visible(view) && bamf_window_get_window_type(win) != BAMF_WINDOW_DOCK &&
- wm.IsWindowOnCurrentDesktop(xid) &&
- wm.IsWindowVisible(xid) &&
- std::find(unity_xids.begin(), unity_xids.end(), xid) == unity_xids.end())
- {
- active_win = win;
- active_xid = xid;
- }
- }
-
- g_list_free(windows);
- }
-
- BamfApplication* active_app = bamf_matcher_get_application_for_window(matcher, active_win);
+ ApplicationManager& app_manager = ApplicationManager::Default();
+ ApplicationPtr active_application;
+ ApplicationWindowPtr active_window = app_manager.GetActiveWindow();
+ if (active_window)
+ active_application = active_window->application();
- if (BAMF_IS_VIEW(active_app))
+ if (active_application)
{
- auto active_view = reinterpret_cast<BamfView*>(active_app);
- glib::String view_icon(bamf_view_get_icon(active_view));
- focused_app_icon_ = view_icon.Str();
+ focused_app_icon_ = active_application->icon();
}
else
{
diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h
index 495317a87..936020daa 100644
--- a/launcher/AbstractLauncherIcon.h
+++ b/launcher/AbstractLauncherIcon.h
@@ -29,6 +29,7 @@
#include <libdbusmenu-glib/menuitem.h>
#include "DndData.h"
+#include <unity-shared/ApplicationManager.h>
#include "unity-shared/Introspectable.h"
#include "unity-shared/IconTextureSource.h"
#include "unity-shared/WindowManager.h"
@@ -156,7 +157,7 @@ public:
virtual int SortPriority() = 0;
- virtual std::vector<Window> Windows() = 0;
+ virtual WindowList Windows() = 0;
virtual std::vector<Window> WindowsForMonitor(int monitor) = 0;
diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp
index b3782e256..e9cc7bde8 100644
--- a/launcher/ApplicationLauncherIcon.cpp
+++ b/launcher/ApplicationLauncherIcon.cpp
@@ -55,59 +55,53 @@ const std::string DEFAULT_ICON = "application-default-icon";
NUX_IMPLEMENT_OBJECT_TYPE(ApplicationLauncherIcon);
-ApplicationLauncherIcon::ApplicationLauncherIcon(BamfApplication* app)
+ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
: SimpleLauncherIcon(IconType::APPLICATION)
- , _bamf_app(app, glib::AddRef())
+ , app_(app)
, use_custom_bg_color_(false)
, bg_color_(nux::color::White)
{
- g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"),
- GUINT_TO_POINTER(1));
- auto bamf_view = glib::object_cast<BamfView>(_bamf_app);
-
- glib::String icon(bamf_view_get_icon(bamf_view));
-
- tooltip_text = BamfName();
- icon_name = (icon ? icon.Str() : DEFAULT_ICON);
-
- SetQuirk(Quirk::VISIBLE, bamf_view_is_user_visible(bamf_view));
- SetQuirk(Quirk::ACTIVE, bamf_view_is_active(bamf_view));
- SetQuirk(Quirk::RUNNING, bamf_view_is_running(bamf_view));
-
- glib::SignalBase* sig;
-
- sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-added",
- [this] (BamfView*, BamfView*) {
- EnsureWindowState();
- UpdateMenus();
- UpdateIconGeometries(GetCenters());
- });
- _gsignals.Add(sig);
-
- sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",
- [this] (BamfView*, BamfView*) { EnsureWindowState(); });
- _gsignals.Add(sig);
-
- sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-moved",
- [&] (BamfView *, BamfView *) {
- EnsureWindowState();
- });
- _gsignals.Add(sig);
-
- sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "urgent-changed",
- [this] (BamfView*, gboolean urgent) {
+ app->seen = true;
+
+ tooltip_text = app->title();
+ std::string icon = app->icon();
+ icon_name = (icon.empty() ? DEFAULT_ICON : icon);
+
+ SetQuirk(Quirk::VISIBLE, app->visible());
+ SetQuirk(Quirk::ACTIVE, app->active());
+ SetQuirk(Quirk::RUNNING, app->running());
+ // Make sure we set the LauncherIcon stick bit too...
+ if (app->sticky())
+ SimpleLauncherIcon::Stick(false); // don't emit the signal
+
+ LOG_INFO(logger) << "Created ApplicationLauncherIcon: "
+ << tooltip_text()
+ << ", icon: " << icon_name()
+ << ", sticky: " << (app->sticky() ? "yes" : "no")
+ << ", visible: " << (app->visible() ? "yes" : "no")
+ << ", active: " << (app->active() ? "yes" : "no")
+ << ", running: " << (app->running() ? "yes" : "no");
+
+ // Lambda functions should be fine here because when the application the icon
+ // is only ever removed when the application is closed.
+ app->window_opened.connect([this](ApplicationWindow const&) {
+ EnsureWindowState();
+ UpdateMenus();
+ UpdateIconGeometries(GetCenters());
+ });
+ app->window_closed.connect([this]() { EnsureWindowState(); });
+ app->window_moved.connect([this](ApplicationWindow const&) { EnsureWindowState(); });
+
+ app->urgent.changed.connect([this](bool const& urgent) {
+ LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false");
SetQuirk(Quirk::URGENT, urgent);
});
- _gsignals.Add(sig);
-
- sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "active-changed",
- [this] (BamfView*, gboolean active) {
+ app->active.changed.connect([this](bool const& active) {
+ LOG_DEBUG(logger) << tooltip_text() << " active now " << (active ? "true" : "false");
SetQuirk(Quirk::ACTIVE, active);
});
- _gsignals.Add(sig);
-
- sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "running-changed",
- [this] (BamfView* view, gboolean running) {
+ app->running.changed.connect([this](bool const& running) {
+ LOG_DEBUG(logger) << tooltip_text() << " running now " << (running ? "true" : "false");
SetQuirk(Quirk::RUNNING, running);
if (running)
@@ -119,29 +113,24 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(BamfApplication* app)
* very early, so we need to make sure that they
* are updated as soon as the view is re-opened. */
if (tooltip_text().empty())
- tooltip_text = BamfName();
+ tooltip_text = app_->title();
if (icon_name == DEFAULT_ICON)
{
- glib::String icon(bamf_view_get_icon(view));
- icon_name = (icon ? icon.Str() : DEFAULT_ICON);
+ std::string icon = app_->icon();
+ icon_name = (icon.empty() ? DEFAULT_ICON : icon);
}
EnsureWindowState();
UpdateIconGeometries(GetCenters());
}
});
- _gsignals.Add(sig);
-
- sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "user-visible-changed",
- [this] (BamfView*, gboolean visible) {
+ app->visible.changed.connect([this](bool const& visible) {
if (!IsSticky())
SetQuirk(Quirk::VISIBLE, visible);
});
- _gsignals.Add(sig);
- sig = new glib::Signal<void, BamfView*>(bamf_view, "closed",
- [this] (BamfView*) {
+ app->closed.connect([this]() {
if (!IsSticky())
{
SetQuirk(Quirk::VISIBLE, false);
@@ -158,7 +147,6 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(BamfApplication* app)
}, ICON_REMOVE_TIMEOUT);
}
});
- _gsignals.Add(sig);
WindowManager& wm = WindowManager::Default();
wm.window_minimized.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::OnWindowMinimized));
@@ -177,35 +165,31 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(BamfApplication* app)
ApplicationLauncherIcon::~ApplicationLauncherIcon()
{
- if (_bamf_app.IsType(BAMF_TYPE_APPLICATION))
+ if (app_)
{
- bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), FALSE);
- g_object_set_qdata(G_OBJECT(_bamf_app.RawPtr()),
- g_quark_from_static_string("unity-seen"), nullptr);
+ app_->sticky = false;
+ app_->seen = false;
}
}
void ApplicationLauncherIcon::Remove()
{
/* Removing the unity-seen flag to the wrapped bamf application, on remove
- * request we make sure that if the bamf application is re-opened while
- * the removal process is still ongoing, the application will be shown
- * on the launcher. Disconnecting from signals and nullifying the _bamf_app
- * we make sure that this icon won't be reused (no duplicated icon). */
- _gsignals.Disconnect(_bamf_app);
- g_object_set_qdata(G_OBJECT(_bamf_app.RawPtr()),
- g_quark_from_static_string("unity-seen"), nullptr);
- _bamf_app = nullptr;
-
+ * request we make sure that if the application is re-opened while the
+ * removal process is still ongoing, the application will be shown on the
+ * launcher. Disconnecting from signals we make sure that this icon won't be
+ * reused (no duplicated icon). */
+ app_->seen = false;
+ // Disconnect all our callbacks.
+ notify_callbacks(); // This is from sigc++::trackable
SimpleLauncherIcon::Remove();
}
bool ApplicationLauncherIcon::IsSticky() const
{
- if (!BAMF_IS_VIEW(_bamf_app.RawPtr()))
- return false;
- else
- return bamf_view_is_sticky(BAMF_VIEW(_bamf_app.RawPtr()));
+ if (app_)
+ return app_->sticky();
+ return false;
}
bool ApplicationLauncherIcon::IsActive() const
@@ -227,25 +211,30 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
SimpleLauncherIcon::ActivateLauncherIcon(arg);
WindowManager& wm = WindowManager::Default();
- bool scaleWasActive = wm.IsScaleActive();
- bool active = IsActive();
- bool user_visible = IsRunning();
-
- if (arg.target && OwnsWindow(arg.target))
+ // This is a little awkward as the target is only set from the switcher.
+ if (arg.target)
{
+ // thumper: should we Raise too? should the WM raise?
wm.Activate(arg.target);
return;
}
+ bool scaleWasActive = wm.IsScaleActive();
+ if (scaleWasActive)
+ {
+ wm.TerminateScale();
+ }
+
+ bool active = IsActive();
+ bool user_visible = IsRunning();
/* We should check each child to see if there is
* an unmapped (!= minimized) window around and
* if so force "Focus" behaviour */
if (arg.source != ActionArg::SWITCHER)
{
- auto bamf_view = glib::object_cast<BamfView>(_bamf_app);
- user_visible = bamf_view_is_user_visible(bamf_view);
+ user_visible = app_->visible();
if (active)
{
@@ -254,21 +243,10 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
bool any_on_top = false;
bool any_on_monitor = (arg.monitor < 0);
int active_monitor = arg.monitor;
- GList* children = bamf_view_get_children(bamf_view);
- for (GList* l = children; l; l = l->next)
+ for (auto& window : app_->GetWindows())
{
- auto view = static_cast<BamfView*>(l->data);
- auto win = static_cast<BamfWindow*>(l->data);
- Window xid;
-
- if (BAMF_IS_WINDOW(l->data))
- xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
- else if (BAMF_IS_TAB(l->data))
- xid = bamf_tab_get_xid(static_cast<BamfTab*>(l->data));
- else
- continue;
-
+ Window xid = window->window_id();
if (!any_visible && wm.IsWindowOnCurrentDesktop(xid))
{
@@ -285,20 +263,18 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
any_on_top = true;
}
- if (!any_on_monitor && bamf_window_get_monitor(win) == arg.monitor &&
+ if (!any_on_monitor && window->monitor() == arg.monitor &&
wm.IsWindowMapped(xid) && wm.IsWindowVisible(xid))
{
any_on_monitor = true;
}
- if (bamf_view_is_active(view))
+ if (window->active())
{
- active_monitor = bamf_window_get_monitor(win);
+ active_monitor = window->monitor();
}
}
- g_list_free(children);
-
if (!any_visible || !any_mapped || !any_on_top)
active = false;
@@ -320,11 +296,6 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
if (GetQuirk(Quirk::STARTING))
return;
- if (scaleWasActive)
- {
- wm.TerminateScale();
- }
-
SetQuirk(Quirk::STARTING, true);
OpenInstanceLauncherIcon();
}
@@ -334,7 +305,6 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
if (scaleWasActive) // #5 above
{
- wm.TerminateScale();
Focus(arg);
}
else // #2 above
@@ -349,7 +319,6 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
if (scaleWasActive) // #4 above
{
- wm.TerminateScale();
Focus(arg);
if (arg.source != ActionArg::SWITCHER)
Spread(true, 0, false);
@@ -362,56 +331,39 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
}
}
-std::vector<Window> ApplicationLauncherIcon::GetWindows(WindowFilterMask filter, int monitor)
+WindowList ApplicationLauncherIcon::GetWindows(WindowFilterMask filter, int monitor)
{
WindowManager& wm = WindowManager::Default();
- std::vector<Window> results;
-
- if (!BAMF_IS_VIEW(_bamf_app.RawPtr()))
- {
- if (_bamf_app)
- {
- LOG_WARNING(logger) << "Not a view but not null.";
- }
- return results;
- }
+ WindowList results;
monitor = (filter & WindowFilter::ON_ALL_MONITORS) ? -1 : monitor;
bool mapped = (filter & WindowFilter::MAPPED);
bool user_visible = (filter & WindowFilter::USER_VISIBLE);
bool current_desktop = (filter & WindowFilter::ON_CURRENT_DESKTOP);
- GList* children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
- for (GList* l = children; l; l = l->next)
+ for (auto& window : app_->GetWindows())
{
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- auto window = static_cast<BamfWindow*>(l->data);
- auto view = static_cast<BamfView*>(l->data);
-
- if ((monitor >= 0 && bamf_window_get_monitor(window) == monitor) || monitor < 0)
+ if ((monitor >= 0 && window->monitor() == monitor) || monitor < 0)
{
- if ((user_visible && bamf_view_is_user_visible(view)) || !user_visible)
+ if ((user_visible && window->visible()) || !user_visible)
{
- guint32 xid = bamf_window_get_xid(window);
+ Window xid = window->window_id();
if ((mapped && wm.IsWindowMapped(xid)) || !mapped)
{
if ((current_desktop && wm.IsWindowOnCurrentDesktop(xid)) || !current_desktop)
{
- results.push_back(xid);
+ results.push_back(window);
}
}
}
}
}
- g_list_free(children);
return results;
}
-std::vector<Window> ApplicationLauncherIcon::Windows()
+WindowList ApplicationLauncherIcon::Windows()
{
return GetWindows(WindowFilter::MAPPED|WindowFilter::ON_ALL_MONITORS);
}
@@ -424,7 +376,12 @@ std::vector<Window> ApplicationLauncherIcon::WindowsOnViewport()
filter |= WindowFilter::ON_CURRENT_DESKTOP;
filter |= WindowFilter::ON_ALL_MONITORS;
- return GetWindows(filter);
+ std::vector<Window> windows;
+ for (auto& window : GetWindows(filter))
+ {
+ windows.push_back(window->window_id());
+ }
+ return windows;
}
std::vector<Window> ApplicationLauncherIcon::WindowsForMonitor(int monitor)
@@ -434,12 +391,17 @@ std::vector<Window> ApplicationLauncherIcon::WindowsForMonitor(int monitor)
filter |= WindowFilter::USER_VISIBLE;
filter |= WindowFilter::ON_CURRENT_DESKTOP;
- return GetWindows(filter, monitor);
+ std::vector<Window> windows;
+ for (auto& window : GetWindows(filter, monitor))
+ {
+ windows.push_back(window->window_id());
+ }
+ return windows;
}
void ApplicationLauncherIcon::OnWindowMinimized(guint32 xid)
{
- if (!OwnsWindow(xid))
+ if (!app_->OwnsWindow(xid))
return;
Present(0.5f, 600);
@@ -448,7 +410,7 @@ void ApplicationLauncherIcon::OnWindowMinimized(guint32 xid)
void ApplicationLauncherIcon::OnWindowMoved(guint32 moved_win)
{
- if (!OwnsWindow(moved_win))
+ if (!app_->OwnsWindow(moved_win))
return;
_source_manager.AddTimeout(250, [&] {
@@ -461,17 +423,9 @@ void ApplicationLauncherIcon::OnWindowMoved(guint32 moved_win)
void ApplicationLauncherIcon::UpdateDesktopFile()
{
- if (!BAMF_IS_APPLICATION(_bamf_app.RawPtr()))
- {
- if (_bamf_app)
- {
- LOG_WARNING(logger) << "Not an app but not null.";
- }
- return;
- }
- const char* filename = bamf_application_get_desktop_file(_bamf_app);
+ std::string filename = app_->desktop_file();
- if (filename != nullptr && filename[0] != '\0' && _desktop_file != filename)
+ if (!filename.empty() && _desktop_file != filename)
{
_desktop_file = filename;
@@ -511,12 +465,6 @@ std::string ApplicationLauncherIcon::DesktopFile()
return _desktop_file;
}
-std::string ApplicationLauncherIcon::BamfName() const
-{
- glib::String name(bamf_view_get_name(BAMF_VIEW(_bamf_app.RawPtr())));
- return name.Str();
-}
-
void ApplicationLauncherIcon::AddProperties(GVariantBuilder* builder)
{
SimpleLauncherIcon::AddProperties(builder);
@@ -524,44 +472,18 @@ void ApplicationLauncherIcon::AddProperties(GVariantBuilder* builder)
GVariantBuilder xids_builder;
g_variant_builder_init(&xids_builder, G_VARIANT_TYPE ("au"));
- for (auto xid : GetWindows())
- g_variant_builder_add(&xids_builder, "u", xid);
+ for (auto& window : GetWindows())
+ g_variant_builder_add(&xids_builder, "u", window->window_id());
variant::BuilderWrapper(builder)
.add("desktop_file", DesktopFile())
.add("desktop_id", GetDesktopID())
- .add("application_id", GPOINTER_TO_UINT(_bamf_app.RawPtr()))
.add("xids", g_variant_builder_end(&xids_builder))
.add("sticky", IsSticky());
}
-bool ApplicationLauncherIcon::OwnsWindow(Window xid) const
-{
- GList* children, *l;
- bool owns = false;
-
- if (!xid || !_bamf_app)
- return owns;
-
- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
-
- for (l = children; l; l = l->next)
- {
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- if (bamf_window_get_xid(static_cast<BamfWindow*>(l->data)) == xid)
- {
- owns = true;
- break;
- }
- }
-
- g_list_free(children);
- return owns;
-}
-void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> uris)
+void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris)
{
glib::Error error;
glib::Object<GDesktopAppInfo> desktopInfo(g_desktop_app_info_new_from_filename(DesktopFile().c_str()));
@@ -596,7 +518,9 @@ void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> uris)
}
if (error)
- g_warning("%s\n", error.Message().c_str());
+ {
+ LOG_WARN(logger) << error;
+ }
UpdateQuirkTime(Quirk::STARTING);
}
@@ -607,122 +531,33 @@ void ApplicationLauncherIcon::OpenInstanceLauncherIcon()
OpenInstanceWithUris(empty);
}
-std::vector<Window> ApplicationLauncherIcon::GetFocusableWindows(ActionArg arg, bool &any_visible, bool &any_urgent)
+void ApplicationLauncherIcon::Focus(ActionArg arg)
{
- bool any_user_visible = false;
- WindowManager& wm = WindowManager::Default();
-
- std::vector<Window> windows;
- GList* children;
-
- BamfView *focusable_child = BAMF_VIEW(bamf_application_get_focusable_child(_bamf_app.RawPtr()));
-
- if (focusable_child != NULL)
- {
- Window xid = 0;
-
- if (BAMF_IS_WINDOW(focusable_child))
- {
- xid = bamf_window_get_xid(BAMF_WINDOW(focusable_child));
- }
- else if (BAMF_IS_TAB(focusable_child))
- {
- BamfTab *focusable_tab = BAMF_TAB(focusable_child);
- xid = bamf_tab_get_xid(focusable_tab);
- bamf_tab_raise(focusable_tab);
- }
-
- if (xid)
- {
- windows.push_back(xid);
- return windows;
- }
- }
- else
+ ApplicationWindowPtr window = app_->GetFocusableWindow();
+ if (window)
{
- if (g_strcmp0(bamf_application_get_application_type(_bamf_app.RawPtr()), "webapp") == 0)
- {
- OpenInstanceLauncherIcon();
-
- return windows;
- }
+ // If we have a window, try to focus it.
+ if (window->Focus())
+ return;
}
-
- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
-
- /* get the list of windows */
- for (GList* l = children; l; l = l->next)
+ else if (app_->type() == "webapp")
{
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- auto view = static_cast<BamfView*>(l->data);
-
- Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
- bool urgent = bamf_view_is_urgent(view);
- bool user_visible = bamf_view_is_user_visible(view);
-
- if (any_urgent)
- {
- if (urgent)
- windows.push_back(xid);
- }
- else if (any_user_visible && !urgent)
- {
- if (user_visible)
- windows.push_back(xid);
- }
- else
- {
- if (urgent || user_visible)
- {
- windows.clear();
- any_visible = false;
- any_urgent = (any_urgent || urgent);
- any_user_visible = (any_user_visible || user_visible);
- }
-
- windows.push_back(xid);
- }
-
- if (wm.IsWindowOnCurrentDesktop(xid) && wm.IsWindowVisible(xid))
- {
- any_visible = true;
- }
+ // Webapps are again special.
+ OpenInstanceLauncherIcon();
+ return;
}
- g_list_free(children);
-
- return windows;
-
+ bool show_only_visible = arg.source == ActionArg::SWITCHER;
+ app_->Focus(show_only_visible, arg.monitor);
}
-void ApplicationLauncherIcon::Focus(ActionArg arg)
+bool ApplicationLauncherIcon::Spread(bool current_desktop, int state, bool force)
{
- bool any_visible = false, any_urgent = false;
- std::vector<Window> windows = GetFocusableWindows(arg, any_visible, any_urgent);
-
- auto visibility = WindowManager::FocusVisibility::OnlyVisible;
-
- if (arg.source != ActionArg::SWITCHER)
+ std::vector<Window> windows;
+ for (auto& window : GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0))
{
- if (any_visible)
- {
- visibility = WindowManager::FocusVisibility::ForceUnminimizeInvisible;
- }
- else
- {
- visibility = WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop;
- }
+ windows.push_back(window->window_id());
}
-
- bool only_top_win = !any_urgent;
- WindowManager::Default().FocusWindowGroup(windows, visibility, arg.monitor, only_top_win);
-}
-
-bool ApplicationLauncherIcon::Spread(bool current_desktop, int state, bool force)
-{
- auto windows = GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0);
return WindowManager::Default().ScaleWindowGroup(windows, state, force);
}
@@ -731,47 +566,24 @@ void ApplicationLauncherIcon::EnsureWindowState()
std::vector<bool> monitors;
monitors.resize(max_num_monitors);
- if (BAMF_IS_VIEW(_bamf_app.RawPtr()))
+ for (auto& window: app_->GetWindows())
{
- GList* children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
- for (GList* l = children; l; l = l->next)
- {
- Window xid;
+ int monitor = window->monitor();
+ Window window_id = window->window_id();
- if (BAMF_IS_TAB(l->data))
+ if (WindowManager::Default().IsWindowOnCurrentDesktop(window_id))
+ {
+ // If monitor is -1 (or negative), show on all monitors.
+ if (monitor < 0)
{
- /* BamfTab does not support the monitor interface...so a bit of a nasty hack here. */
- xid = bamf_tab_get_xid (static_cast<BamfTab*>(l->data));
-
- if (WindowManager::Default().IsWindowOnCurrentDesktop(xid) == false)
- continue;
-
for (int j = 0; j < max_num_monitors; j++)
monitors[j] = true;
-
- continue;
}
-
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- auto window = static_cast<BamfWindow*>(l->data);
- xid = bamf_window_get_xid(window);
- int monitor = bamf_window_get_monitor(window);
-
- if (monitor >= 0 && WindowManager::Default().IsWindowOnCurrentDesktop(xid))
+ else
monitors[monitor] = true;
}
-
- g_list_free(children);
- }
- else
- {
- if (_bamf_app)
- {
- LOG_WARNING(logger) << "Not a view but not null.";
- }
}
+
for (int i = 0; i < max_num_monitors; i++)
SetWindowVisibleOnMonitor(monitors[i], i);
@@ -850,28 +662,17 @@ void ApplicationLauncherIcon::UpdateBackgroundColor()
void ApplicationLauncherIcon::UpdateMenus()
{
- GList* children, *l;
-
- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
- for (l = children; l; l = l->next)
+ for (auto& app_menu : app_->GetRemoteMenus())
{
- if (!BAMF_IS_INDICATOR(l->data))
- continue;
-
- auto indicator = static_cast<BamfIndicator*>(l->data);
- std::string path = bamf_indicator_get_dbus_menu_path(indicator);
-
// we already have this
- if (_menu_clients.find(path) != _menu_clients.end())
+ if (_menu_clients.find(app_menu.path) != _menu_clients.end())
continue;
- std::string address = bamf_indicator_get_remote_address(indicator);
- glib::Object<DbusmenuClient> client(dbusmenu_client_new(address.c_str(), path.c_str()));
- _menu_clients[path] = client;
+ glib::Object<DbusmenuClient> client(dbusmenu_client_new(app_menu.remote_address.c_str(),
+ app_menu.path.c_str()));
+ _menu_clients[app_menu.path] = client;
}
- g_list_free(children);
-
// add dynamic quicklist
if (_menuclient_dynamic_quicklist && _menuclient_dynamic_quicklist.IsType(DBUSMENU_TYPE_CLIENT))
{
@@ -895,26 +696,7 @@ void ApplicationLauncherIcon::UpdateMenus()
void ApplicationLauncherIcon::Quit()
{
- GList* children, *l;
-
- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
-
- for (l = children; l; l = l->next)
- {
- if (BAMF_IS_TAB (l->data))
- {
- // As Unity can not close a tab inside the provider application, we have to ask Bamf to delegate for us.
- bamf_tab_close (BAMF_TAB (l->data));
- continue;
- }
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
- WindowManager::Default().Close(xid);
- }
-
- g_list_free(children);
+ app_->Quit();
}
void ApplicationLauncherIcon::AboutToRemove()
@@ -928,8 +710,7 @@ void ApplicationLauncherIcon::Stick(bool save)
if (IsSticky())
return;
- bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), true);
-
+ app_->sticky = true;
SimpleLauncherIcon::Stick(save);
}
@@ -940,12 +721,8 @@ void ApplicationLauncherIcon::UnStick()
if (!IsSticky())
return;
- BamfView* view = BAMF_VIEW(_bamf_app.RawPtr());
- bamf_view_set_sticky(view, false);
-
- SetQuirk(Quirk::VISIBLE, bamf_view_is_user_visible(view));
-
- if (bamf_view_is_closed(view))
+ app_->sticky = false;
+ if (!app_->running())
Remove();
}
@@ -1086,7 +863,7 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
}
else
{
- glib::String app_name(g_markup_escape_text(BamfName().c_str(), -1));
+ glib::String app_name(g_markup_escape_text(app_->title().c_str(), -1));
std::ostringstream bold_app_name;
bold_app_name << "<b>" << app_name << "</b>";
@@ -1163,36 +940,25 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
void ApplicationLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> center)
{
- if (!BAMF_IS_VIEW(_bamf_app.RawPtr()))
- {
- if (_bamf_app)
- {
- LOG_WARNING(logger) << "Not a view but not null.";
- }
- return;
- }
-
nux::Geometry geo;
geo.width = 48;
geo.height = 48;
- GList* children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
-
- for (GList* l = children; l; l = l->next)
+ for (auto& window : app_->GetWindows())
{
- if (!BAMF_IS_WINDOW(l->data))
+ // We don't deal with tabs.
+ if (window->type() == "tab")
continue;
- Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
- int monitor = bamf_window_get_monitor(static_cast<BamfWindow*>(l->data));
+ Window xid = window->window_id();
+ int monitor = window->monitor();
monitor = std::max<int>(0, std::min<int>(center.size() - 1, monitor));
+ // TODO: replace 24 with icon_size / 2;
geo.x = center[monitor].x - 24;
geo.y = center[monitor].y - 24;
WindowManager::Default().SetWindowIconGeometry(xid, geo);
}
-
- g_list_free(children);
}
void ApplicationLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> center)
@@ -1324,22 +1090,17 @@ bool ApplicationLauncherIcon::ShowInSwitcher(bool current)
unsigned long long ApplicationLauncherIcon::SwitcherPriority()
{
- GList* children, *l;
unsigned long long result = 0;
+ // Webapps always go at the back.
+ if (app_->type() == "webapp")
+ return result;
- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
-
- /* get the list of windows */
- for (l = children; l; l = l->next)
+ for (auto& window : app_->GetWindows())
{
- if (!BAMF_IS_WINDOW(l->data))
- continue;
-
- Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
+ Window xid = window->window_id();
result = std::max(result, WindowManager::Default().GetWindowActiveNumber(xid));
}
- g_list_free(children);
return result;
}
@@ -1354,15 +1115,10 @@ nux::Color ApplicationLauncherIcon::BackgroundColor() const
const std::set<std::string> ApplicationLauncherIcon::GetSupportedTypes()
{
std::set<std::string> supported_types;
- std::unique_ptr<gchar*[], void(*)(gchar**)> mimes(bamf_application_get_supported_mime_types(_bamf_app),
- g_strfreev);
-
- if (!mimes)
- return supported_types;
- for (int i = 0; mimes[i]; i++)
+ for (auto& type : app_->GetSupportedMimeTypes())
{
- unity::glib::String super_type(g_content_type_from_mime_type(mimes[i]));
+ unity::glib::String super_type(g_content_type_from_mime_type(type.c_str()));
supported_types.insert(super_type.Str());
}
diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h
index 7e64df53f..ceef2323f 100644
--- a/launcher/ApplicationLauncherIcon.h
+++ b/launcher/ApplicationLauncherIcon.h
@@ -24,7 +24,6 @@
#include <UnityCore/GLibSignal.h>
#include <UnityCore/GLibWrapper.h>
-#include <libbamf/libbamf.h>
#include <libindicator/indicator-desktop-shortcuts.h>
#include "SimpleLauncherIcon.h"
@@ -40,7 +39,7 @@ class ApplicationLauncherIcon : public SimpleLauncherIcon
{
NUX_DECLARE_OBJECT_TYPE(ApplicationLauncherIcon, SimpleLauncherIcon);
public:
- ApplicationLauncherIcon(BamfApplication* app);
+ ApplicationLauncherIcon(ApplicationPtr const& app);
virtual ~ApplicationLauncherIcon();
virtual void ActivateLauncherIcon(ActionArg arg);
@@ -63,7 +62,7 @@ public:
virtual nux::Color BackgroundColor() const;
- std::vector<Window> Windows();
+ WindowList Windows();
std::vector<Window> WindowsOnViewport();
std::vector<Window> WindowsForMonitor(int monitor);
@@ -86,7 +85,6 @@ protected:
std::set<std::string> ValidateUrisForLaunch(DndData const& dnd_data);
std::string GetRemoteUri();
- std::string BamfName() const;
bool HandlesSpread() { return true; }
std::string GetName() const;
@@ -108,21 +106,18 @@ private:
void UpdateMenus();
void UpdateDesktopQuickList();
- void OpenInstanceWithUris(std::set<std::string> uris);
+ void OpenInstanceWithUris(std::set<std::string> const& uris);
void Focus(ActionArg arg);
- std::vector<Window> GetFocusableWindows(ActionArg arg, bool &any_visible, bool &any_urgent);
bool Spread(bool current_desktop, int state, bool force);
void OnWindowMinimized(guint32 xid);
void OnWindowMoved(guint32 xid);
- bool OwnsWindow(Window w) const;
-
- std::vector<Window> GetWindows(WindowFilterMask filter = 0, int monitor = -1);
+ WindowList GetWindows(WindowFilterMask filter = 0, int monitor = -1);
const std::set<std::string> GetSupportedTypes();
std::string GetDesktopID();
- glib::Object<BamfApplication> _bamf_app;
+ ApplicationPtr app_;
std::string _remote_uri;
std::string _desktop_file;
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index ad160d26e..bad70e7c5 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -93,13 +93,19 @@ set (SWITCHER_SOURCES
add_library (switcher-lib STATIC ${SWITCHER_SOURCES})
add_dependencies (switcher-lib unity-core-${UNITY_API_VERSION} unity-shared)
+set (LAUNCHER_LIBS
+ launcher-lib
+ unity-shared
+ unity-shared-bamf
+ unity-shared-standalone)
+
#
# Standalone variant
#
add_executable (launcher StandaloneLauncher.cpp)
-target_link_libraries (launcher launcher-lib unity-shared unity-shared-standalone)
+target_link_libraries (launcher ${LAUNCHER_LIBS})
if (ENABLE_X_SUPPORT)
add_executable (switcher StandaloneSwitcher.cpp)
- target_link_libraries (switcher switcher-lib launcher-lib unity-shared unity-shared-standalone)
+ target_link_libraries (switcher switcher-lib ${LAUNCHER_LIBS})
endif ()
diff --git a/launcher/ExpoLauncherIcon.cpp b/launcher/ExpoLauncherIcon.cpp
index 6f46a0899..17c2d64d7 100644
--- a/launcher/ExpoLauncherIcon.cpp
+++ b/launcher/ExpoLauncherIcon.cpp
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Marco Trevisan <marco.trevisan@canonical.com>
+ * Andrea Azzarone <andrea.azzarone@canonical.com>
*/
#include "ExpoLauncherIcon.h"
@@ -32,10 +33,51 @@ ExpoLauncherIcon::ExpoLauncherIcon()
: SimpleLauncherIcon(IconType::EXPO)
{
tooltip_text = _("Workspace Switcher");
- icon_name = "workspace-switcher";
+ icon_name = "workspace-switcher-top-left";
SetQuirk(Quirk::VISIBLE, false);
SetQuirk(Quirk::RUNNING, false);
SetShortcut('s');
+
+ auto& wm = WindowManager::Default();
+ OnViewportLayoutChanged(wm.GetViewportHSize(), wm.GetViewportVSize());
+
+ wm.viewport_layout_changed.connect(sigc::mem_fun(this, &ExpoLauncherIcon::OnViewportLayoutChanged));
+}
+
+void ExpoLauncherIcon::OnViewportLayoutChanged(int hsize, int vsize)
+{
+ if (hsize != 2 || vsize != 2)
+ {
+ icon_name = "workspace-switcher-top-left";
+ screen_viewport_switch_ended_connection_.disconnect();
+ terminate_expo_connection_.disconnect();
+ }
+ else
+ {
+ UpdateIcon();
+
+ if (!terminate_expo_connection_)
+ {
+ auto& wm = WindowManager::Default();
+ auto cb = sigc::mem_fun(this, &ExpoLauncherIcon::UpdateIcon);
+ screen_viewport_switch_ended_connection_ = wm.screen_viewport_switch_ended.connect(cb);
+ terminate_expo_connection_ = wm.terminate_expo.connect(cb);
+ }
+ }
+}
+
+void ExpoLauncherIcon::UpdateIcon()
+{
+ auto const& vp = WindowManager::Default().GetCurrentViewport();
+
+ if (vp.x == 0 and vp.y == 0)
+ icon_name = "workspace-switcher-top-left";
+ else if (vp.x == 0)
+ icon_name = "workspace-switcher-left-bottom";
+ else if (vp.y == 0)
+ icon_name = "workspace-switcher-right-top";
+ else
+ icon_name = "workspace-switcher-right-bottom";
}
void ExpoLauncherIcon::ActivateLauncherIcon(ActionArg arg)
@@ -44,13 +86,9 @@ void ExpoLauncherIcon::ActivateLauncherIcon(ActionArg arg)
WindowManager& wm = WindowManager::Default();
if (!wm.IsExpoActive())
- {
wm.InitiateExpo();
- }
else
- {
wm.TerminateExpo();
- }
}
void ExpoLauncherIcon::Stick(bool save)
diff --git a/launcher/ExpoLauncherIcon.h b/launcher/ExpoLauncherIcon.h
index b4a335675..af1ba244e 100644
--- a/launcher/ExpoLauncherIcon.h
+++ b/launcher/ExpoLauncherIcon.h
@@ -37,6 +37,13 @@ protected:
void ActivateLauncherIcon(ActionArg arg);
std::string GetName() const;
std::string GetRemoteUri();
+
+private:
+ void OnViewportLayoutChanged(int hsize, int vsize);
+ void UpdateIcon();
+
+ sigc::connection screen_viewport_switch_ended_connection_;
+ sigc::connection terminate_expo_connection_;
};
}
diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp
index ff6ff1046..0b43d27dd 100644
--- a/launcher/Launcher.cpp
+++ b/launcher/Launcher.cpp
@@ -493,13 +493,13 @@ float Launcher::IconVisibleProgress(AbstractLauncherIcon::Ptr const& icon, struc
if (icon->IsVisible())
{
struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
- int enter_ms = unity::TimeUtil::TimeDelta(&current, &icon_visible_time);
+ DeltaTime enter_ms = unity::TimeUtil::TimeDelta(&current, &icon_visible_time);
return CLAMP((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
}
else
{
struct timespec icon_hide_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
- int hide_ms = unity::TimeUtil::TimeDelta(&current, &icon_hide_time);
+ DeltaTime hide_ms = unity::TimeUtil::TimeDelta(&current, &icon_hide_time);
return 1.0f - CLAMP((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
}
}
@@ -531,7 +531,7 @@ void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec
float Launcher::IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec icon_present_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED);
- int ms = unity::TimeUtil::TimeDelta(&current, &icon_present_time);
+ DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &icon_present_time);
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PRESENTED))
@@ -543,7 +543,7 @@ float Launcher::IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struc
float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec icon_unfold_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
- int ms = unity::TimeUtil::TimeDelta(&current, &icon_unfold_time);
+ DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &icon_unfold_time);
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED))
@@ -555,7 +555,7 @@ float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct
float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);
- int urgent_ms = unity::TimeUtil::TimeDelta(&current, &urgent_time);
+ DeltaTime urgent_ms = unity::TimeUtil::TimeDelta(&current, &urgent_time);
float result;
if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
@@ -572,7 +572,7 @@ float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct
float Launcher::IconDropDimValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM);
- int dim_ms = unity::TimeUtil::TimeDelta(&current, &dim_time);
+ DeltaTime dim_ms = unity::TimeUtil::TimeDelta(&current, &dim_time);
float result = CLAMP((float) dim_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DROP_DIM))
@@ -584,7 +584,7 @@ float Launcher::IconDropDimValue(AbstractLauncherIcon::Ptr const& icon, struct t
float Launcher::IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT);
- int ms = unity::TimeUtil::TimeDelta(&current, &dim_time);
+ DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &dim_time);
float result = CLAMP((float) ms / (float) ANIM_DURATION_SHORT_SHORT, 0.0f, 1.0f);
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT))
@@ -596,14 +596,14 @@ float Launcher::IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct tim
float Launcher::IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec shimmer_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);
- int shimmer_ms = unity::TimeUtil::TimeDelta(&current, &shimmer_time);
+ DeltaTime shimmer_ms = unity::TimeUtil::TimeDelta(&current, &shimmer_time);
return CLAMP((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
}
float Launcher::IconCenterTransitionProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec save_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED);
- int save_ms = unity::TimeUtil::TimeDelta(&current, &save_time);
+ DeltaTime save_ms = unity::TimeUtil::TimeDelta(&current, &save_time);
return CLAMP((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
}
@@ -619,7 +619,7 @@ float Launcher::IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, stru
float Launcher::IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const &current) const
{
struct timespec pulse_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE);
- int pulse_ms = unity::TimeUtil::TimeDelta(&current, &pulse_time);
+ DeltaTime pulse_ms = unity::TimeUtil::TimeDelta(&current, &pulse_time);
double pulse_progress = (double) CLAMP((float) pulse_ms / (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), 0.0f, 1.0f);
if (pulse_progress == 1.0f)
@@ -646,7 +646,7 @@ float Launcher::IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon, st
return 1.0f;
struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
- int starting_ms = unity::TimeUtil::TimeDelta(&current, &starting_time);
+ DeltaTime starting_ms = unity::TimeUtil::TimeDelta(&current, &starting_time);
double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * STARTING_BLINK_LAMBDA), 0.0f, 1.0f);
double val = IsBackLightModeToggles() ? 3.0f : 4.0f;
return 1.0f-(0.5f + (float)(std::cos(M_PI * val * starting_progress)) * 0.5f);
@@ -661,7 +661,7 @@ float Launcher::IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon, st
return 1.0f;
struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
- int starting_ms = unity::TimeUtil::TimeDelta(&current, &starting_time);
+ DeltaTime starting_ms = unity::TimeUtil::TimeDelta(&current, &starting_time);
double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f);
if (starting_progress == 1.0f && !icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
@@ -678,7 +678,7 @@ float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, s
float result = 0.0f;
struct timespec running_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING);
- int running_ms = unity::TimeUtil::TimeDelta(&current, &running_time);
+ DeltaTime running_ms = unity::TimeUtil::TimeDelta(&current, &running_time);
float running_progress = CLAMP((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
@@ -743,7 +743,7 @@ float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, s
float Launcher::IconProgressBias(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
{
struct timespec icon_progress_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS);
- int ms = unity::TimeUtil::TimeDelta(&current, &icon_progress_time);
+ DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &icon_progress_time);
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PROGRESS))
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index e5c632b64..cf63cb04b 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -21,7 +21,6 @@
#include "config.h"
#include <glib/gi18n-lib.h>
-#include <libbamf/libbamf.h>
#include <Nux/Nux.h>
#include <Nux/HLayout.h>
@@ -99,7 +98,6 @@ GDBusInterfaceVTable Controller::Impl::interface_vtable =
Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager)
: parent_(parent)
, model_(std::make_shared<LauncherModel>())
- , matcher_(bamf_matcher_get_default())
, xdnd_manager_(xdnd_manager)
, device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>())
, expo_icon_(new ExpoLauncherIcon())
@@ -147,6 +145,7 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager)
WindowManager& wm = WindowManager::Default();
wm.window_focus_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnWindowFocusChanged));
+ wm.viewport_layout_changed.connect(sigc::group(sigc::mem_fun(this, &Controller::Impl::UpdateNumWorkspaces), sigc::_1 * sigc::_2));
ubus.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, [&](GVariant * args) {
if (reactivate_keynav)
@@ -181,7 +180,7 @@ Controller::Impl::~Impl()
}
if (gdbus_connection_ && reg_id_)
- g_dbus_connection_unregister_object(gdbus_connection_, reg_id_);
+ g_dbus_connection_unregister_object(gdbus_connection_, reg_id_);
g_bus_unown_name(dbus_owner_);
}
@@ -769,19 +768,11 @@ int Controller::Impl::GetLastIconPriority(std::string const& favorite_uri, bool
return icon_prio;
}
-void Controller::Impl::OnViewOpened(BamfMatcher* matcher, BamfView* view)
+void Controller::Impl::OnApplicationStarted(ApplicationPtr const& app)
{
- if (!BAMF_IS_APPLICATION(view))
+ if (app->sticky() || app->seen())
return;
- BamfApplication* app = BAMF_APPLICATION(view);
-
- if (bamf_view_is_sticky(view) ||
- g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
- {
- return;
- }
-
AbstractLauncherIcon::Ptr icon(new ApplicationLauncherIcon(app));
RegisterIcon(icon, GetLastIconPriority<ApplicationLauncherIcon>(local::RUNNING_APPS_URI));
}
@@ -814,20 +805,13 @@ AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const
if (!desktop_id.empty())
{
- BamfApplication* app;
std::string const& desktop_path = DesktopUtilities::GetDesktopPathById(desktop_id);
-
- app = bamf_matcher_get_application_for_desktop_file(matcher_, desktop_path.c_str(), true);
-
- if (!app)
+ ApplicationPtr app = ApplicationManager::Default().GetApplicationForDesktopFile(desktop_path);
+ if (!app || app->seen())
return result;
- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
- {
- bamf_view_set_sticky(BAMF_VIEW(app), true);
- return result;
- }
-
+ // Sticky apps are those that are in the launcher when not running.
+ app->sticky = true;
result = AbstractLauncherIcon::Ptr(new ApplicationLauncherIcon(app));
}
else if (icon_uri.find(FavoriteStore::URI_PREFIX_DEVICE) == 0)
@@ -884,20 +868,16 @@ SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::stri
std::string const& aptdaemon_trans_id,
std::string const& icon_path)
{
- BamfApplication* app;
SoftwareCenterLauncherIcon::Ptr result;
- app = bamf_matcher_get_application_for_desktop_file(matcher_, file_path.c_str(), true);
- if (!BAMF_IS_APPLICATION(app))
+ ApplicationPtr app = ApplicationManager::Default().GetApplicationForDesktopFile(file_path);
+ if (!app)
return result;
- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
- {
- bamf_view_set_sticky(BAMF_VIEW(app), true);
+ app->sticky = true;
+ if (app->seen)
return result;
- }
- bamf_view_set_sticky(BAMF_VIEW(app), true);
result = new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path);
return result;
@@ -905,20 +885,16 @@ SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::stri
void Controller::Impl::AddRunningApps()
{
- std::shared_ptr<GList> apps(bamf_matcher_get_applications(matcher_), g_list_free);
-
- for (GList *l = apps.get(); l; l = l->next)
+ for (auto& app : ApplicationManager::Default().GetRunningApplications())
{
- if (!BAMF_IS_APPLICATION(l->data))
- continue;
-
- BamfApplication* app = BAMF_APPLICATION(l->data);
-
- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
- continue;
-
- AbstractLauncherIcon::Ptr icon(new ApplicationLauncherIcon(app));
- RegisterIcon(icon, ++sort_priority_);
+ LOG_INFO(logger) << "Adding running app: " << app->title()
+ << ", seen already: "
+ << (app->seen() ? "yes" : "no");
+ if (!app->seen())
+ {
+ AbstractLauncherIcon::Ptr icon(new ApplicationLauncherIcon(app));
+ RegisterIcon(icon, ++sort_priority_);
+ }
}
}
@@ -938,38 +914,50 @@ void Controller::Impl::SetupIcons()
FavoriteList const& favs = favorite_store.GetFavorites();
bool running_apps_added = false;
bool devices_added = false;
-
for (auto const& fav_uri : favs)
{
if (fav_uri == local::RUNNING_APPS_URI)
{
+ LOG_INFO(logger) << "Adding running apps";
AddRunningApps();
running_apps_added = true;
continue;
}
else if (fav_uri == local::DEVICES_URI)
{
+ LOG_INFO(logger) << "Adding devices";
AddDevices();
devices_added = true;
continue;
}
+ LOG_INFO(logger) << "Adding favourite: " << fav_uri;
RegisterIcon(CreateFavoriteIcon(fav_uri), ++sort_priority_);
}
if (!running_apps_added)
+ {
+ LOG_INFO(logger) << "Adding running apps";
AddRunningApps();
+ }
if (model_->IconIndex(expo_icon_) < 0)
+ {
+ LOG_INFO(logger) << "Adding expo icon";
RegisterIcon(CreateFavoriteIcon(expo_icon_->RemoteUri()), ++sort_priority_);
+ }
if (!devices_added)
+ {
+ LOG_INFO(logger) << "Adding devices";
AddDevices();
+ }
if (std::find(favs.begin(), favs.end(), expo_icon_->RemoteUri()) == favs.end())
SaveIconsOrder();
- view_opened_signal_.Connect(matcher_, "view-opened", sigc::mem_fun(this, &Impl::OnViewOpened));
+ ApplicationManager::Default().application_started
+ .connect(sigc::mem_fun(this, &Impl::OnApplicationStarted));
device_section_.icon_added.connect(sigc::mem_fun(this, &Impl::OnDeviceIconAdded));
favorite_store.favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
favorite_store.favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
diff --git a/launcher/LauncherControllerPrivate.h b/launcher/LauncherControllerPrivate.h
index 6e35f182e..1fda57d2c 100644
--- a/launcher/LauncherControllerPrivate.h
+++ b/launcher/LauncherControllerPrivate.h
@@ -46,7 +46,7 @@ namespace unity
namespace launcher
{
-class Controller::Impl
+class Controller::Impl : public sigc::trackable
{
public:
Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager);
@@ -100,7 +100,7 @@ public:
void OnWindowFocusChanged (guint32 xid);
- void OnViewOpened(BamfMatcher* matcher, BamfView* view);
+ void OnApplicationStarted(ApplicationPtr const& app);
void ReceiveMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags);
@@ -126,7 +126,6 @@ public:
Controller* parent_;
LauncherModel::Ptr model_;
- glib::Object<BamfMatcher> matcher_;
nux::ObjectPtr<Launcher> launcher_;
nux::ObjectPtr<Launcher> keyboard_launcher_;
XdndManager::Ptr xdnd_manager_;
@@ -155,7 +154,6 @@ public:
GDBusConnection* gdbus_connection_;
unsigned reg_id_;
- glib::Signal<void, BamfMatcher*, BamfView*> view_opened_signal_;
glib::SourceManager sources_;
UBusManager ubus;
diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp
index 46d689f94..b35906c22 100644
--- a/launcher/LauncherIcon.cpp
+++ b/launcher/LauncherIcon.cpp
@@ -360,7 +360,7 @@ nux::BaseTexture* LauncherIcon::TextureFromGtkTheme(std::string icon_name, int s
// FIXME: we need to create some kind of -unity postfix to see if we are looking to the unity-icon-theme
// for dedicated unity icons, then remove the postfix and degrade to other icon themes if not found
- if (icon_name == "workspace-switcher" && IsMonoDefaultTheme())
+ if (icon_name.find("workspace-switcher") == 0)
result = TextureFromSpecificGtkTheme(GetUnityTheme(), icon_name, size, update_glow_colors);
if (!result)
diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h
index 0971dc3bc..b6712796c 100644
--- a/launcher/LauncherIcon.h
+++ b/launcher/LauncherIcon.h
@@ -97,7 +97,7 @@ public:
int SortPriority();
- virtual std::vector<Window> Windows() { return std::vector<Window> (); }
+ virtual WindowList Windows() { return WindowList(); }
virtual std::vector<Window> WindowsOnViewport() { return std::vector<Window> (); }
diff --git a/launcher/LauncherModel.h b/launcher/LauncherModel.h
index d093a8047..bc5c832eb 100644
--- a/launcher/LauncherModel.h
+++ b/launcher/LauncherModel.h
@@ -112,8 +112,7 @@ public:
{
std::list<AbstractLauncherIcon::Ptr> result;
- iterator it;
- for (it = begin(); it != end(); it++)
+ for (iterator it = begin(), e = end(); it != e; ++it)
{
T* var = dynamic_cast<T*>((*it).GetPointer());
diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h
index d00c6c569..147b34564 100644
--- a/launcher/MockLauncherIcon.h
+++ b/launcher/MockLauncherIcon.h
@@ -32,6 +32,7 @@
#include <sigc++/sigc++.h>
#include <libdbusmenu-glib/menuitem.h>
+#include "unity-shared/ApplicationManager.h"
#include "AbstractLauncherIcon.h"
@@ -39,6 +40,24 @@ namespace unity
{
namespace launcher
{
+class MockApplicationWindow : public ApplicationWindow
+{
+public:
+ MockApplicationWindow(Window xid) : xid_(xid) {}
+
+ std::string title() const { return "MockApplicationWindow"; }
+ virtual std::string icon() const { return ""; }
+ virtual std::string type() const { return "mock"; }
+
+ virtual Window window_id() const { return xid_; }
+ virtual int monitor() const { return -1; }
+ virtual ApplicationPtr application() const { return ApplicationPtr(); }
+ virtual bool Focus() const { return false; }
+ virtual void Quit() const {}
+private:
+ Window xid_;
+};
+
class MockLauncherIcon : public AbstractLauncherIcon
{
@@ -58,7 +77,7 @@ public:
}
std::string GetName() const { return "MockLauncherIcon"; }
-
+
void AddProperties(GVariantBuilder* builder) {}
void HideTooltip() {}
@@ -70,18 +89,18 @@ public:
return 0;
}
- std::vector<Window> Windows ()
+ WindowList Windows ()
{
- std::vector<Window> result;
+ WindowList result;
- result.push_back ((100 << 16) + 200);
- result.push_back ((500 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((200 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((100 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((600 << 16) + 200);
+ result.push_back(std::make_shared<MockApplicationWindow>((100 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((500 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((200 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((100 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((600 << 16) + 200));
return result;
}
diff --git a/launcher/SoftwareCenterLauncherIcon.cpp b/launcher/SoftwareCenterLauncherIcon.cpp
index cfd72265d..cd94f06ae 100644
--- a/launcher/SoftwareCenterLauncherIcon.cpp
+++ b/launcher/SoftwareCenterLauncherIcon.cpp
@@ -40,18 +40,19 @@ const int INSTALL_TIP_DURATION = 1500;
NUX_IMPLEMENT_OBJECT_TYPE(SoftwareCenterLauncherIcon);
-SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(BamfApplication* app,
+SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(ApplicationPtr const& app,
std::string const& aptdaemon_trans_id,
std::string const& icon_path)
-: ApplicationLauncherIcon(app),
- aptdaemon_trans_("org.debian.apt",
- aptdaemon_trans_id,
- "org.debian.apt.transaction",
- G_BUS_TYPE_SYSTEM,
- G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
-, finished_(true)
-, needs_urgent_(false)
-, aptdaemon_trans_id_(aptdaemon_trans_id)
+ : ApplicationLauncherIcon(app)
+ , aptdaemon_trans_("org.debian.apt",
+ aptdaemon_trans_id,
+ "org.debian.apt.transaction",
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
+ , finished_(true)
+ , needs_urgent_(false)
+ , aptdaemon_trans_id_(aptdaemon_trans_id)
+ , app_title_(app->title())
{
SetQuirk(Quirk::VISIBLE, false);
aptdaemon_trans_.Connect("PropertyChanged", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnPropertyChanged));
@@ -124,7 +125,7 @@ void SoftwareCenterLauncherIcon::OnFinished(GVariant *params)
if (exit_state.Str() == "exit-success")
{
- tooltip_text = BamfName();
+ tooltip_text = app_title_;
SetQuirk(Quirk::PROGRESS, false);
SetQuirk(Quirk::URGENT, true);
SetProgress(0.0f);
diff --git a/launcher/SoftwareCenterLauncherIcon.h b/launcher/SoftwareCenterLauncherIcon.h
index 6b586f0b9..6f0306855 100644
--- a/launcher/SoftwareCenterLauncherIcon.h
+++ b/launcher/SoftwareCenterLauncherIcon.h
@@ -38,7 +38,7 @@ class SoftwareCenterLauncherIcon : public ApplicationLauncherIcon
public:
typedef nux::ObjectPtr<SoftwareCenterLauncherIcon> Ptr;
- SoftwareCenterLauncherIcon(BamfApplication* app,
+ SoftwareCenterLauncherIcon(ApplicationPtr const& app,
std::string const& aptdaemon_trans_id,
std::string const& icon_path);
@@ -63,6 +63,7 @@ private:
bool needs_urgent_;
std::string aptdaemon_trans_id_;
+ std::string app_title_;
};
}
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index bdfb5b30c..73726ee0e 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -470,8 +470,9 @@ void Controller::SelectFirstItem()
unsigned int second_first = 0; // second icons first highest active
WindowManager& wm = WindowManager::Default();
- for (guint32 xid : first->Windows())
+ for (auto& window : first->Windows())
{
+ guint32 xid = window->window_id();
unsigned int num = wm.GetWindowActiveNumber(xid);
if (num > first_highest)
@@ -485,8 +486,9 @@ void Controller::SelectFirstItem()
}
}
- for (guint32 xid : second->Windows())
+ for (auto& window : second->Windows())
{
+ guint32 xid = window->window_id();
second_first = std::max<unsigned long long>(wm.GetWindowActiveNumber(xid), second_first);
}
diff --git a/launcher/SwitcherModel.cpp b/launcher/SwitcherModel.cpp
index 931ecb18d..b489adae8 100644
--- a/launcher/SwitcherModel.cpp
+++ b/launcher/SwitcherModel.cpp
@@ -150,7 +150,10 @@ bool WindowOnOtherViewport(Window xid)
std::vector<Window> SwitcherModel::DetailXids()
{
std::vector<Window> results;
- results = Selection()->Windows();
+ for (auto& window : Selection()->Windows())
+ {
+ results.push_back(window->window_id());
+ }
if (only_detail_on_viewport)
{
diff --git a/launcher/SwitcherView.cpp b/launcher/SwitcherView.cpp
index 3632a1414..e1d96a46c 100644
--- a/launcher/SwitcherView.cpp
+++ b/launcher/SwitcherView.cpp
@@ -223,7 +223,7 @@ nux::Geometry SwitcherView::UpdateRenderTargets(nux::Point const& center, timesp
{
std::vector<Window> const& xids = model_->DetailXids();
- int ms_since_change = TimeUtil::TimeDelta(&current, &save_time_);
+ DeltaTime ms_since_change = TimeUtil::TimeDelta(&current, &save_time_);
float progress = std::min<float>(1.0f, ms_since_change / static_cast<float>(animation_length()));
for (Window window : xids)
@@ -485,7 +485,7 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo,
++i;
}
- int ms_since_change = TimeUtil::TimeDelta(&current, &save_time_);
+ DeltaTime ms_since_change = TimeUtil::TimeDelta(&current, &save_time_);
if (saved_args_.size () == results.size () && ms_since_change < animation_length)
{
float progress = (float) ms_since_change / (float) animation_length();
@@ -585,7 +585,7 @@ void SwitcherView::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw,
text_view_->Draw(GfxContext, force_draw);
}
- int ms_since_change = TimeUtil::TimeDelta(&current_, &save_time_);
+ DeltaTime ms_since_change = TimeUtil::TimeDelta(&current_, &save_time_);
if (ms_since_change < animation_length && !redraw_idle_)
{
diff --git a/panel/PanelIndicatorEntryView.cpp b/panel/PanelIndicatorEntryView.cpp
index 31d053d13..14a1dee85 100644
--- a/panel/PanelIndicatorEntryView.cpp
+++ b/panel/PanelIndicatorEntryView.cpp
@@ -30,7 +30,6 @@
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>
-#include <time.h>
#include <boost/algorithm/string.hpp>
#include "unity-shared/CairoTexture.h"
@@ -102,10 +101,8 @@ void PanelIndicatorEntryView::ShowMenu(int button)
if (!wm.IsExpoActive() && !wm.IsScaleActive())
{
- proxy_->ShowMenu(GetAbsoluteX(),
- GetAbsoluteY() + panel::Style::Instance().panel_height,
- button,
- time(nullptr));
+ auto const& abs_geo = GetAbsoluteGeometry();
+ proxy_->ShowMenu(abs_geo.x, abs_geo.y + panel::Style::Instance().panel_height, button);
}
}
@@ -144,7 +141,7 @@ void PanelIndicatorEntryView::OnMouseUp(int x, int y, long button_flags, long ke
button == 2 && type_ == INDICATOR)
{
if (geo.IsPointInside(px, py))
- proxy_->SecondaryActivate(time(nullptr));
+ proxy_->SecondaryActivate();
SetOpacity(1.0f);
}
diff --git a/panel/PanelMenuView.cpp b/panel/PanelMenuView.cpp
index 575344479..eeb7772fe 100644
--- a/panel/PanelMenuView.cpp
+++ b/panel/PanelMenuView.cpp
@@ -1576,7 +1576,7 @@ void PanelMenuView::OnLauncherSelectionChanged(GVariant* data)
const gchar *title = g_variant_get_string(data, 0);
_panel_title = (title ? title : "");
- Refresh();
+ Refresh(true);
QueueDraw();
}
diff --git a/panel/PanelView.cpp b/panel/PanelView.cpp
index eb9a73218..69f319a6c 100644
--- a/panel/PanelView.cpp
+++ b/panel/PanelView.cpp
@@ -704,7 +704,7 @@ void PanelView::OnEntryActivateRequest(std::string const& entry_id)
bool PanelView::TrackMenuPointer()
{
- auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
+ nux::Point const& mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
if (_tracked_pointer_pos != mouse)
{
OnMenuPointerMoved(mouse.x, mouse.y);
@@ -742,9 +742,8 @@ void PanelView::OnEntryActivated(std::string const& entry_id, nux::Rect const& g
_ubus_manager.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
}
-void PanelView::OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
- int x, int y, unsigned int button,
- unsigned int timestamp)
+void PanelView::OnEntryShowMenu(std::string const& entry_id, unsigned xid,
+ int x, int y, unsigned button)
{
Display* d = nux::GetGraphicsDisplay()->GetX11Display();
XUngrabPointer(d, CurrentTime);
diff --git a/panel/PanelView.h b/panel/PanelView.h
index 769112a93..aa5b2a810 100644
--- a/panel/PanelView.h
+++ b/panel/PanelView.h
@@ -80,8 +80,7 @@ protected:
void OnMenuPointerMoved(int x, int y);
void OnEntryActivateRequest(std::string const& entry_id);
void OnEntryActivated(std::string const& entry_id, nux::Rect const& geo);
- void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, int x, int y,
- unsigned int button, unsigned int timestamp);
+ void OnEntryShowMenu(std::string const& entry_id, unsigned xid, int x, int y, unsigned button);
private:
void OnBackgroundUpdate(GVariant *data);
diff --git a/plugins/unityshell/CMakeLists.txt b/plugins/unityshell/CMakeLists.txt
index 36db0176c..d4d170ae2 100644
--- a/plugins/unityshell/CMakeLists.txt
+++ b/plugins/unityshell/CMakeLists.txt
@@ -11,7 +11,7 @@ compiz_plugin (unityshell
LIBDIRS "${CMAKE_BINARY_DIR}/UnityCore"
)
add_dependencies(unityshell unity-core-${UNITY_API_VERSION} dash-lib launcher-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-compiz)
-target_link_libraries(unityshell unity-core-${UNITY_API_VERSION} launcher-lib dash-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-compiz)
+target_link_libraries(unityshell unity-core-${UNITY_API_VERSION} launcher-lib dash-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-bamf unity-shared-compiz)
set_target_properties(unityshell
PROPERTIES INSTALL_RPATH "${CACHED_UNITY_PRIVATE_DEPS_LIBRARY_DIRS}"
INSTALL_RPATH_USE_LINK_PATH TRUE)
diff --git a/plugins/unityshell/src/ElapsedTimeMonitor.cpp b/plugins/unityshell/src/ElapsedTimeMonitor.cpp
index b5afc3aed..586ab6368 100644
--- a/plugins/unityshell/src/ElapsedTimeMonitor.cpp
+++ b/plugins/unityshell/src/ElapsedTimeMonitor.cpp
@@ -39,7 +39,7 @@ void ElapsedTimeMonitor::StopMonitor(GVariantBuilder* builder)
{
struct timespec current;
clock_gettime(CLOCK_MONOTONIC, &current);
- int diff = TimeUtil::TimeDelta(&current, &_start);
+ DeltaTime diff = TimeUtil::TimeDelta(&current, &_start);
variant::BuilderWrapper(builder)
.add("elapsed-time", diff);
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index e3181452f..869aa85d7 100644
--- a/plugins/unityshell/src/unityshell.cpp
+++ b/plugins/unityshell/src/unityshell.cpp
@@ -1853,8 +1853,11 @@ void UnityScreen::SendExecuteCommand()
adapter.TerminateScale();
}
+ ubus_manager_.SendMessage(UBUS_DASH_ABOUT_TO_SHOW, NULL, glib::Source::Priority::HIGH);
+
ubus_manager_.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
- g_variant_new("(sus)", "commands.lens", 0, ""));
+ g_variant_new("(sus)", "commands.lens", 0, ""),
+ glib::Source::Priority::LOW);
}
bool UnityScreen::executeCommand(CompAction* action,
@@ -3068,7 +3071,10 @@ bool UnityScreen::setOptionForPlugin(const char* plugin, const char* name,
if (strcmp(plugin, "core") == 0)
{
if (strcmp(name, "hsize") == 0 || strcmp(name, "vsize") == 0)
- launcher_controller_->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
+ {
+ WindowManager& wm = WindowManager::Default();
+ wm.viewport_layout_changed.emit(screen->vpSize().width(), screen->vpSize().height());
+ }
}
}
return status;
diff --git a/services/panel-main.c b/services/panel-main.c
index 07f2afe2f..2d3d74da6 100644
--- a/services/panel-main.c
+++ b/services/panel-main.c
@@ -28,21 +28,6 @@
static GDBusNodeInfo *introspection_data = NULL;
-/*
- * typedef struct {
- * gchar *indicator_id
- * gchar *entry_id;
- * gchar *label;
- * bool label_sensitive;
- * bool label_visible;
- * uint32 icon_hint;
- * gchar *icon_data;
- * bool icon_sensitive;
- * bool icon_visible;
- *
- * } EntryInfo;
- */
-
static const gchar introspection_xml[] =
"<node>"
" <interface name='com.canonical.Unity.Panel.Service'>"
@@ -57,7 +42,8 @@ static const gchar introspection_xml[] =
" </method>"
""
" <method name='SyncGeometries'>"
- " <arg type='a(ssiiii)' name='geometries' direction='in'/>"
+ " <arg type='s' name='panel_id' direction='in'/>"
+ " <arg type='a(siiii)' name='geometries' direction='in'/>"
" </method>"
""
" <method name='ShowEntry'>"
@@ -66,19 +52,16 @@ static const gchar introspection_xml[] =
" <arg type='i' name='x' direction='in'/>"
" <arg type='i' name='y' direction='in'/>"
" <arg type='u' name='button' direction='in'/>"
- " <arg type='u' name='timestamp' direction='in'/>"
" </method>"
""
" <method name='ShowAppMenu'>"
" <arg type='u' name='xid' direction='in'/>"
" <arg type='i' name='x' direction='in'/>"
" <arg type='i' name='y' direction='in'/>"
- " <arg type='u' name='timestamp' direction='in'/>"
" </method>"
""
" <method name='SecondaryActivateEntry'>"
" <arg type='s' name='entry_id' direction='in'/>"
- " <arg type='u' name='timestamp' direction='in'/>"
" </method>"
""
" <method name='ScrollEntry'>"
@@ -155,31 +138,34 @@ handle_method_call (GDBusConnection *connection,
gchar *id;
g_variant_get (parameters, "(s)", &id, NULL);
g_dbus_method_invocation_return_value (invocation,
- panel_service_sync_one (service,
- id));
+ panel_service_sync_one (service, id));
g_free (id);
}
else if (g_strcmp0 (method_name, "SyncGeometries") == 0)
{
GVariantIter *iter;
- gchar *indicator_id, *entry_id;
+ gchar *panel_id, *entry_id;
gint x, y, width, height;
- g_variant_get (parameters, "(a(ssiiii))", &iter);
- while (iter && g_variant_iter_loop (iter, "(ssiiii)",
- &indicator_id,
- &entry_id,
- &x,
- &y,
- &width,
- &height))
+ g_variant_get (parameters, "(sa(siiii))", &panel_id, &iter);
+
+ if (panel_id)
{
- panel_service_sync_geometry (service, indicator_id,
- entry_id, x, y, width, height);
+ if (iter)
+ {
+ while (g_variant_iter_loop (iter, "(siiii)", &entry_id, &x, &y,
+ &width, &height))
+ {
+ panel_service_sync_geometry (service, panel_id, entry_id, x, y,
+ width, height);
+ }
+
+ g_variant_iter_free (iter);
+ }
+
+ g_free (panel_id);
}
- if (iter) g_variant_iter_free (iter);
-
g_dbus_method_invocation_return_value (invocation, NULL);
}
else if (g_strcmp0 (method_name, "ShowEntry") == 0)
@@ -189,10 +175,9 @@ handle_method_call (GDBusConnection *connection,
gint32 x;
gint32 y;
guint32 button;
- guint32 timestamp;
- g_variant_get (parameters, "(suiiuu)", &entry_id, &xid, &x, &y, &button, &timestamp, NULL);
+ g_variant_get (parameters, "(suiiu)", &entry_id, &xid, &x, &y, &button);
- panel_service_show_entry (service, entry_id, xid, x, y, button, timestamp);
+ panel_service_show_entry (service, entry_id, xid, x, y, button);
g_dbus_method_invocation_return_value (invocation, NULL);
g_free (entry_id);
@@ -202,20 +187,18 @@ handle_method_call (GDBusConnection *connection,
guint32 xid;
gint32 x;
gint32 y;
- guint32 timestamp;
- g_variant_get (parameters, "(uiiu)", &xid, &x, &y, &timestamp, NULL);
+ g_variant_get (parameters, "(uii)", &xid, &x, &y);
- panel_service_show_app_menu (service, xid, x, y, timestamp);
+ panel_service_show_app_menu (service, xid, x, y);
g_dbus_method_invocation_return_value (invocation, NULL);
}
else if (g_strcmp0 (method_name, "SecondaryActivateEntry") == 0)
{
- gchar *entry_id;
- guint32 timestamp;
- g_variant_get (parameters, "(su)", &entry_id, &timestamp, NULL);
+ gchar *entry_id;
+ g_variant_get (parameters, "(s)", &entry_id);
- panel_service_secondary_activate_entry (service, entry_id, timestamp);
+ panel_service_secondary_activate_entry (service, entry_id);
g_dbus_method_invocation_return_value (invocation, NULL);
g_free (entry_id);
@@ -277,7 +260,8 @@ on_service_entry_activate_request (PanelService *service,
GDBusConnection *connection)
{
GError *error = NULL;
- g_warning ("%s, entry_id:%s", G_STRFUNC, entry_id);
+ g_debug ("%s, entry_id: %s", G_STRFUNC, entry_id);
+
g_dbus_connection_emit_signal (connection,
NULL,
S_PATH,
@@ -357,7 +341,7 @@ on_name_lost (GDBusConnection *connection,
gpointer user_data)
{
PanelService *service = PANEL_SERVICE (user_data);
-
+
g_debug ("%s", G_STRFUNC);
if (service != NULL)
{
diff --git a/services/panel-service.c b/services/panel-service.c
index cd557382c..0127bc045 100644
--- a/services/panel-service.c
+++ b/services/panel-service.c
@@ -460,7 +460,7 @@ event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self)
}
else if (entry == priv->pressed_entry)
{
- panel_service_secondary_activate_entry (self, entry_id, time(NULL));
+ panel_service_secondary_activate_entry (self, entry_id);
}
ret = GDK_FILTER_REMOVE;
@@ -1645,8 +1645,7 @@ panel_service_show_entry_common (PanelService *self,
guint32 xid,
gint32 x,
gint32 y,
- guint32 button,
- guint32 timestamp)
+ guint32 button)
{
PanelServicePrivate *priv;
GtkWidget *last_menu;
@@ -1767,8 +1766,7 @@ panel_service_show_entry (PanelService *self,
guint32 xid,
gint32 x,
gint32 y,
- guint32 button,
- guint32 timestamp)
+ guint32 button)
{
IndicatorObject *object;
IndicatorObjectEntry *entry;
@@ -1778,15 +1776,11 @@ panel_service_show_entry (PanelService *self,
entry = get_indicator_entry_by_id (self, entry_id);
object = get_entry_parent_indicator (entry);
- panel_service_show_entry_common (self, object, entry, xid, x, y, button, timestamp);
+ panel_service_show_entry_common (self, object, entry, xid, x, y, button);
}
void
-panel_service_show_app_menu (PanelService *self,
- guint32 xid,
- gint32 x,
- gint32 y,
- guint32 timestamp)
+panel_service_show_app_menu (PanelService *self, guint32 xid, gint32 x, gint32 y)
{
IndicatorObject *object;
IndicatorObjectEntry *entry;
@@ -1804,14 +1798,12 @@ panel_service_show_app_menu (PanelService *self,
entry = entries->data;
g_list_free (entries);
- panel_service_show_entry_common (self, object, entry, xid, x, y, 1, timestamp);
+ panel_service_show_entry_common (self, object, entry, xid, x, y, 1);
}
}
void
-panel_service_secondary_activate_entry (PanelService *self,
- const gchar *entry_id,
- guint32 timestamp)
+panel_service_secondary_activate_entry (PanelService *self, const gchar *entry_id)
{
IndicatorObject *object;
IndicatorObjectEntry *entry;
@@ -1821,7 +1813,7 @@ panel_service_secondary_activate_entry (PanelService *self,
object = get_entry_parent_indicator (entry);
g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, entry,
- timestamp);
+ CurrentTime);
}
void
diff --git a/services/panel-service.h b/services/panel-service.h
index b7514f04b..ad0c6fc28 100644
--- a/services/panel-service.h
+++ b/services/panel-service.h
@@ -28,19 +28,19 @@ G_BEGIN_DECLS
#define PANEL_TYPE_SERVICE (panel_service_get_type ())
#define PANEL_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
- PANEL_TYPE_SERVICE, PanelService))
+ PANEL_TYPE_SERVICE, PanelService))
#define PANEL_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
- PANEL_TYPE_SERVICE, PanelServiceClass))
+ PANEL_TYPE_SERVICE, PanelServiceClass))
#define PANEL_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
- PANEL_TYPE_SERVICE))
+ PANEL_TYPE_SERVICE))
#define PANEL_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
- PANEL_TYPE_SERVICE))
+ PANEL_TYPE_SERVICE))
#define PANEL_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
- PANEL_TYPE_SERVICE, PanelServiceClass))
+ PANEL_TYPE_SERVICE, PanelServiceClass))
typedef struct _PanelService PanelService;
typedef struct _PanelServiceClass PanelServiceClass;
@@ -84,36 +84,33 @@ void panel_service_clear_indicators (PanelService *self);
GVariant * panel_service_sync (PanelService *self);
GVariant * panel_service_sync_one (PanelService *self,
- const gchar *indicator_id);
+ const gchar *indicator_id);
void panel_service_sync_geometry (PanelService *self,
- const gchar *indicator_id,
- const gchar *entry_id,
- gint x,
- gint y,
- gint width,
- gint height);
+ const gchar *indicator_id,
+ const gchar *entry_id,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
void panel_service_show_entry (PanelService *self,
- const gchar *entry_id,
- guint32 xid,
- gint32 x,
- gint32 y,
- guint32 button,
- guint32 timestamp);
+ const gchar *entry_id,
+ guint32 xid,
+ gint32 x,
+ gint32 y,
+ guint32 button);
void panel_service_show_app_menu (PanelService *self,
- guint32 xid,
- gint32 x,
- gint32 y,
- guint32 timestamp);
+ guint32 xid,
+ gint32 x,
+ gint32 y);
void panel_service_secondary_activate_entry (PanelService *self,
- const gchar *entry_id,
- guint32 timestamp);
+ const gchar *entry_id);
void panel_service_scroll_entry (PanelService *self,
- const gchar *entry_id,
- gint32 delta);
+ const gchar *entry_id,
+ gint32 delta);
G_END_DECLS
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a8e22b73a..6ea0c60a1 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -95,6 +95,7 @@ if (GTEST_SRC_DIR AND
# The service that provides DBus services to test against
add_executable(test-gtest-service
+ mock-application.cpp
test_service_gdbus_wrapper.c
test_service_gdbus_wrapper.h
test_service_hud.c
@@ -113,7 +114,7 @@ if (GTEST_SRC_DIR AND
# The actual test executable (xless) - do not put anything that requires X in here
set (GTEST_XLESS_SOURCES
test_main_xless.cpp
- test_animator.cpp
+ #test_animator.cpp # XXX: disabled, to be removed completely soon
test_launcher_model.cpp
test_glib_object.cpp
test_glib_object_utils.cpp
@@ -138,6 +139,7 @@ if (GTEST_SRC_DIR AND
test_layout_system.cpp
test_model_iterator.cpp
test_previews.cpp
+ test_time_util.cpp
test_ubus.cpp
test_unityshell_private.cpp
${CMAKE_CURRENT_BINARY_DIR}/test_glib_signals_utils_marshal.cpp
@@ -204,7 +206,10 @@ if (GTEST_SRC_DIR AND
if (ENABLE_X_SUPPORT)
# Tests that require X
add_executable(test-gtest
+ mock-application.cpp
+ logger_helper.cpp
test_main.cpp
+ test_action_link.cpp
test_application_launcher_icon.cpp
test_bfb_launcher_icon.cpp
test_dashview_impl.cpp
@@ -240,6 +245,7 @@ if (ENABLE_X_SUPPORT)
test_single_monitor_launcher_icon.cpp
test_expo_launcher_icon.cpp
test_showdesktop_handler.cpp
+ test_static_cairo_text.cpp
test_switcher_controller.cpp
test_switcher_model.cpp
test_texture_cache.cpp
diff --git a/tests/autopilot/unity/emulators/dash.py b/tests/autopilot/unity/emulators/dash.py
index 7954b14af..902d680f3 100644
--- a/tests/autopilot/unity/emulators/dash.py
+++ b/tests/autopilot/unity/emulators/dash.py
@@ -9,14 +9,12 @@
from __future__ import absolute_import
-from autopilot.emulators.dbus_handler import session_bus
from autopilot.emulators.X11 import Keyboard, Mouse
from autopilot.keybindings import KeybindingsHelper
from testtools.matchers import GreaterThan
from unity.emulators import UnityIntrospectionObject
import logging
-from time import sleep
import dbus
logger = logging.getLogger(__name__)
@@ -32,7 +30,6 @@ class Dash(KeybindingsHelper):
controllers = DashController.get_all_instances()
assert(len(controllers) == 1)
self.controller = controllers[0]
- self._keyboard = Keyboard()
@property
def view(self):
@@ -169,7 +166,7 @@ class DashController(UnityIntrospectionObject):
def hide_dash_via_dbus(self):
""" Emulate a DBus call for dash hiding """
- dash_object = session_bus.get_object('com.canonical.Unity',
+ dash_object = dbus.SessionBus().get_object('com.canonical.Unity',
'/com/canonical/Unity/Dash')
dash_iface = dbus.Interface(dash_object, 'com.canonical.Unity.Dash')
dash_iface.HideDash()
diff --git a/tests/autopilot/unity/emulators/launcher.py b/tests/autopilot/unity/emulators/launcher.py
index 5bff403b9..c7f00f571 100644
--- a/tests/autopilot/unity/emulators/launcher.py
+++ b/tests/autopilot/unity/emulators/launcher.py
@@ -9,11 +9,9 @@
from __future__ import absolute_import
-from autopilot.emulators.dbus_handler import session_bus
from autopilot.emulators.X11 import Mouse, ScreenGeometry
from autopilot.keybindings import KeybindingsHelper
from autopilot.utilities import get_compiz_option
-import dbus
import logging
from testtools.matchers import NotEquals
from time import sleep
@@ -57,19 +55,6 @@ class LauncherController(UnityIntrospectionObject):
assert(len(models) == 1)
return models[0]
- def add_launcher_item_from_position(self,name,icon,icon_x,icon_y,icon_size,desktop_file,aptdaemon_task):
- """ Emulate a DBus call from Software Center to pin an icon to the launcher """
- launcher_object = session_bus.get_object('com.canonical.Unity.Launcher',
- '/com/canonical/Unity/Launcher')
- launcher_iface = dbus.Interface(launcher_object, 'com.canonical.Unity.Launcher')
- launcher_iface.AddLauncherItemFromPosition(name,
- icon,
- icon_x,
- icon_y,
- icon_size,
- desktop_file,
- aptdaemon_task)
-
class Launcher(UnityIntrospectionObject, KeybindingsHelper):
"""An individual launcher for a monitor."""
diff --git a/tests/autopilot/unity/emulators/unity.py b/tests/autopilot/unity/emulators/unity.py
index 97b1840a0..6f0a31be9 100644
--- a/tests/autopilot/unity/emulators/unity.py
+++ b/tests/autopilot/unity/emulators/unity.py
@@ -9,8 +9,7 @@
from __future__ import absolute_import
-from autopilot.emulators.dbus_handler import session_bus
-from dbus import Interface
+from dbus import Interface, SessionBus
# acquire the debugging dbus object
UNITY_BUS_NAME = 'com.canonical.Unity'
@@ -19,7 +18,7 @@ LOGGING_IFACE = 'com.canonical.Unity.Debug.Logging'
def get_dbus_proxy_object():
- return session_bus.get_object(UNITY_BUS_NAME, DEBUG_PATH)
+ return SessionBus().get_object(UNITY_BUS_NAME, DEBUG_PATH)
def get_dbus_logging_interface():
diff --git a/tests/autopilot/unity/tests/launcher/test_keynav.py b/tests/autopilot/unity/tests/launcher/test_keynav.py
index 474463a30..6cd538112 100644
--- a/tests/autopilot/unity/tests/launcher/test_keynav.py
+++ b/tests/autopilot/unity/tests/launcher/test_keynav.py
@@ -234,3 +234,8 @@ class LauncherKeyNavTests(LauncherTestCase):
self.assertThat(self.dash.visible, Eventually(Equals(True)))
self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
+ def test_launcher_keynav_changes_panel(self):
+ """The panel title must change when in key nav mode."""
+
+ self.start_keynav_with_cleanup_cancel()
+ self.assertThat(self.panels.get_active_panel().title, Eventually(Equals("Dash Home")))
diff --git a/tests/autopilot/unity/tests/test_hud.py b/tests/autopilot/unity/tests/test_hud.py
index 61cfa4748..d1f6d7a11 100644
--- a/tests/autopilot/unity/tests/test_hud.py
+++ b/tests/autopilot/unity/tests/test_hud.py
@@ -57,6 +57,14 @@ class HudTestsBase(UnityTestCase):
num_active += 1
return num_active
+ # Unable to exit SDM without any active apps, need a placeholder.
+ # See bug LP:1079460
+ def start_placeholder_app(self):
+ window_spec = {
+ "Title": "Placeholder application",
+ }
+ self.launch_test_window(window_spec)
+
class HudBehaviorTests(HudTestsBase):
@@ -142,6 +150,7 @@ class HudBehaviorTests(HudTestsBase):
This used to cause unity to crash (hence the lack of assertion in this test).
"""
+ self.start_placeholder_app()
self.window_manager.enter_show_desktop()
self.addCleanup(self.window_manager.leave_show_desktop)
@@ -346,6 +355,7 @@ class HudBehaviorTests(HudTestsBase):
"""Activating a HUD item with the 'Enter' key MUST close the HUD."""
# starting on a clean desktop because this way we are sure that our search
# string won't match any menu item from a focused application
+ self.start_placeholder_app()
self.window_manager.enter_show_desktop()
self.addCleanup(self.window_manager.leave_show_desktop)
@@ -635,6 +645,7 @@ class HudVisualTests(HudTestsBase):
def test_hud_icon_shows_the_ubuntu_emblem_on_empty_desktop(self):
"""When in 'show desktop' mode the hud icon must be the BFB icon."""
+ self.start_placeholder_app()
self.window_manager.enter_show_desktop()
self.addCleanup(self.window_manager.leave_show_desktop)
self.hud.ensure_visible()
@@ -669,6 +680,7 @@ class HudVisualTests(HudTestsBase):
from the current desktop. As the Hud must go through the entire window
stack to find the top most window.
"""
+ self.start_placeholder_app()
initial_workspace = self.workspace.current_workspace
self.addCleanup(self.workspace.switch_to, initial_workspace)
self.window_manager.enter_show_desktop()
diff --git a/tests/logger_helper.cpp b/tests/logger_helper.cpp
new file mode 100644
index 000000000..cc9e54364
--- /dev/null
+++ b/tests/logger_helper.cpp
@@ -0,0 +1,100 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "logger_helper.h"
+
+#include <glib.h>
+#include <iostream>
+
+#include "NuxCore/Logger.h"
+#include "NuxCore/LoggingWriter.h"
+
+namespace unity
+{
+namespace helper
+{
+namespace
+{
+
+nux::logging::Level glog_level_to_nux(GLogLevelFlags log_level)
+{
+ // For some weird reason, ERROR is more critical than CRITICAL in gnome.
+ if (log_level & G_LOG_LEVEL_ERROR)
+ return nux::logging::Critical;
+ if (log_level & G_LOG_LEVEL_CRITICAL)
+ return nux::logging::Error;
+ if (log_level & G_LOG_LEVEL_WARNING)
+ return nux::logging::Warning;
+ if (log_level & G_LOG_LEVEL_MESSAGE ||
+ log_level & G_LOG_LEVEL_INFO)
+ return nux::logging::Info;
+ // default to debug.
+ return nux::logging::Debug;
+}
+
+void capture_g_log_calls(const gchar* log_domain,
+ GLogLevelFlags log_level,
+ const gchar* message,
+ gpointer user_data)
+{
+ // If nothing else, all log messages from unity should be identified as such
+ std::string module("unity");
+ if (log_domain)
+ {
+ module += std::string(".") + log_domain;
+ }
+ nux::logging::Logger logger(module);
+ nux::logging::Level level = glog_level_to_nux(log_level);
+ if (level >= logger.GetEffectiveLogLevel())
+ {
+ nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
+ << message;
+ }
+}
+
+}
+
+
+CaptureLogOutput::CaptureLogOutput()
+{
+ nux::logging::Writer::Instance().SetOutputStream(sout_);
+}
+
+CaptureLogOutput::~CaptureLogOutput()
+{
+ nux::logging::Writer::Instance().SetOutputStream(std::cout);
+}
+
+std::string CaptureLogOutput::GetOutput()
+{
+ std::string result = sout_.str();
+ sout_.str("");
+ return result;
+}
+
+void configure_logging(std::string const& env_var)
+{
+ const char* env = (env_var.empty() ? "UNITY_LOG_SEVERITY" : env_var.c_str());
+ nux::logging::configure_logging(::getenv(env));
+ g_log_set_default_handler(capture_g_log_calls, NULL);
+}
+
+
+}
+}
diff --git a/tests/logger_helper.h b/tests/logger_helper.h
new file mode 100644
index 000000000..812cf85de
--- /dev/null
+++ b/tests/logger_helper.h
@@ -0,0 +1,50 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#ifndef TEST_LOGGER_HELPER_H
+#define TEST_LOGGER_HELPER_H
+
+#include <string>
+#include <sstream>
+
+
+namespace unity
+{
+namespace helper
+{
+
+class CaptureLogOutput
+{
+public:
+ CaptureLogOutput();
+ ~CaptureLogOutput();
+ std::string GetOutput();
+private:
+ std::ostringstream sout_;
+};
+
+
+void configure_logging(std::string const& env_var = "");
+
+}
+}
+
+
+
+#endif
diff --git a/tests/mock-application.cpp b/tests/mock-application.cpp
new file mode 100644
index 000000000..cb42243c4
--- /dev/null
+++ b/tests/mock-application.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 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: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "mock-application.h"
+
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager()
+{
+ return std::shared_ptr<ApplicationManager>(new testmocks::MockApplicationManager());
+}
+
+}
diff --git a/tests/mock-application.h b/tests/mock-application.h
new file mode 100644
index 000000000..728942cd8
--- /dev/null
+++ b/tests/mock-application.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2012 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: Tim Penhey <tim.penhey@canonical.com>
+ */
+#ifndef TESTS_MOCK_APPLICATION_H
+#define TESTS_MOCK_APPLICATION_H
+
+#include <map>
+#include "unity-shared/ApplicationManager.h"
+
+
+namespace testmocks
+{
+class MockApplication : public unity::Application
+{
+public:
+ MockApplication(std::string const& desktop_file,
+ std::string const& icon = "",
+ std::string const& title = "")
+ : desktop_file_(desktop_file)
+ , icon_(icon)
+ , title_(title)
+ , seen_(false)
+ , sticky_(false)
+ , visible_(false)
+ , active_(false)
+ , running_(false)
+ , urgent_(false)
+ {
+ seen.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetSeen));
+ seen.SetSetterFunction(sigc::mem_fun(this, &MockApplication::SetSeen));
+ sticky.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetSticky));
+ sticky.SetSetterFunction(sigc::mem_fun(this, &MockApplication::SetSticky));
+ visible.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetVisible));
+ active.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetActive));
+ running.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetRunning));
+ urgent.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetUrgent));
+ }
+
+ std::string desktop_file_;
+ std::string icon_;
+ std::string title_;
+ bool seen_;
+ bool sticky_;
+ bool visible_;
+ bool active_;
+ bool running_;
+ bool urgent_;
+
+ virtual std::string icon() const { return icon_; }
+ virtual std::string title() const { return title_; }
+ virtual std::string desktop_file() const { return desktop_file_; }
+ virtual std::string type() const { return "mock"; }
+ virtual std::string repr() const { return "MockApplication"; }
+
+ virtual unity::WindowList GetWindows() const { return unity::WindowList(); }
+ virtual bool OwnsWindow(Window window_id) const { return false; }
+
+ virtual std::vector<std::string> GetSupportedMimeTypes() const { return {}; }
+ virtual std::vector<unity::ApplicationMenu> GetRemoteMenus() const { return {}; }
+
+ virtual unity::ApplicationWindowPtr GetFocusableWindow() const { return unity::ApplicationWindowPtr(); }
+ virtual void Focus(bool show_on_visible, int monitor) const {}
+ virtual void Quit() const {}
+ void SetRunState(bool state) {
+ running_ = state;
+ running.changed.emit(state);
+ }
+
+ bool GetSeen() const { return seen_; }
+ bool SetSeen(bool const& param) {
+ if (param != seen_) {
+ seen_ = param;
+ return true;
+ }
+ return false;
+ }
+
+ bool GetSticky() const { return sticky_; }
+ bool SetSticky(bool const& param) {
+ if (param != sticky_) {
+ sticky_ = param;
+ return true;
+ }
+ return false;
+ }
+
+ bool GetVisible() const { return visible_; }
+ bool GetActive() const { return active_; }
+ bool GetRunning() const { return running_; }
+ bool GetUrgent() const { return urgent_; }
+};
+
+class MockApplicationManager : public unity::ApplicationManager
+{
+public:
+ static void StartApp(std::string const& desktop_file)
+ {
+ // We know the application manager is a mock one so we can cast it.
+ auto self = dynamic_cast<MockApplicationManager&>(unity::ApplicationManager::Default());
+ auto app = self.GetApplicationForDesktopFile(desktop_file);
+ self.application_started.emit(app);
+ }
+
+ virtual unity::ApplicationWindowPtr GetActiveWindow()
+ {
+ return unity::ApplicationWindowPtr();
+ }
+
+ unity::ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file)
+ {
+ AppMap::iterator iter = app_map_.find(desktop_file);
+ if (iter == app_map_.end())
+ {
+ unity::ApplicationPtr app(new MockApplication(desktop_file));
+ app_map_.insert(AppMap::value_type(desktop_file, app));
+ return app;
+ }
+ else
+ {
+ return iter->second;
+ }
+ }
+
+ unity::ApplicationList GetRunningApplications()
+ {
+ return unity::ApplicationList();
+ }
+private:
+ typedef std::map<std::string, unity::ApplicationPtr> AppMap;
+ AppMap app_map_;
+};
+
+}
+
+#endif
diff --git a/tests/test_action_link.cpp b/tests/test_action_link.cpp
new file mode 100644
index 000000000..ce0573359
--- /dev/null
+++ b/tests/test_action_link.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser 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 applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser General Public
+ * License version 3 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authored by: Manuel de la Pena <manuel.delapena@canonical.com>
+ *
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <unity-shared/StaticCairoText.h>
+
+#include "dash/previews/ActionLink.cpp"
+#include "test_utils.h"
+
+using namespace nux;
+using namespace unity;
+using namespace unity::dash;
+
+namespace unity
+{
+
+namespace dash
+{
+
+class ActionLinkMock : public ActionLink
+{
+ public:
+ MOCK_METHOD0(QueueDraw, void());
+ MOCK_METHOD0(ComputeContentSize, long());
+ MOCK_METHOD2(CalculateBar, void(nux::GraphicsEngine&, bool));
+
+ ActionLinkMock(std::string const& action_hint, std::string const& label, NUX_FILE_LINE_PROTO)
+ : ActionLink(action_hint, label){}
+ ~ActionLinkMock(){}
+
+ nux::ObjectPtr<nux::StaticCairoText> GetText() { return static_text_; }
+
+ using ActionLink::GetLinkAlpha;
+ using ActionLink::Draw;
+ using ActionLink::DrawContent;
+ using ActionLink::RecvClick;
+ using ActionLink::GetName;
+ using ActionLink::AddProperties;
+ using ActionLink::set_aligment;
+ using ActionLink::get_aligment;
+ using ActionLink::set_underline;
+ using ActionLink::get_underline;
+ using ActionLink::set_font_hint;
+ using ActionLink::get_font_hint;
+ using ActionLink::action_hint_;
+ using ActionLink::font_hint_;
+ using ActionLink::aligment_;
+ using ActionLink::underline_;
+};
+
+class TestActionLink : public ::testing::Test
+{
+ protected:
+ TestActionLink() : Test()
+ {
+ action_link = new ActionLinkMock("action_id", "display_name");
+ }
+ nux::ObjectPtr<ActionLinkMock> action_link;
+};
+
+TEST_F(TestActionLink, AligmentCorrectlySetDifferent)
+{
+ ActionLinkMock link("test", "test");
+
+ EXPECT_CALL(link, ComputeContentSize()).Times(1);
+ EXPECT_CALL(link, QueueDraw()).Times(1);
+
+ link.text_aligment.Set(nux::StaticCairoText::NUX_ALIGN_RIGHT);
+}
+
+TEST_F(TestActionLink, AligmentCorrectlySetSame)
+{
+ ActionLinkMock link("test", "test");
+
+ EXPECT_CALL(link, ComputeContentSize()).Times(0);
+ EXPECT_CALL(link, QueueDraw()).Times(0);
+
+ link.text_aligment.Set(link.text_aligment.Get());
+}
+
+TEST_F(TestActionLink, AligmentCorrectlyRetrieved)
+{
+ nux::StaticCairoText::AlignState aligment =
+ nux::StaticCairoText::NUX_ALIGN_RIGHT;
+ action_link->aligment_ = aligment;
+ EXPECT_EQ(aligment, action_link->text_aligment.Get());
+}
+
+TEST_F(TestActionLink, UnderlineCorrectlySetDifferent)
+{
+ ActionLinkMock link("test", "test");
+
+ EXPECT_CALL(link, ComputeContentSize()).Times(1);
+ EXPECT_CALL(link, QueueDraw()).Times(1);
+ link.underline_state.Set(nux::StaticCairoText::NUX_UNDERLINE_NONE);
+}
+
+TEST_F(TestActionLink, UnderlineCorrectlySetSame)
+{
+ ActionLinkMock link("test", "test");
+
+ EXPECT_CALL(link, ComputeContentSize()).Times(0);
+ EXPECT_CALL(link, QueueDraw()).Times(0);
+ link.underline_state.Set(link.underline_state.Get());
+}
+
+TEST_F(TestActionLink, UnderlineCorrectlyRetrieved)
+{
+ nux::StaticCairoText::UnderlineState underline =
+ nux::StaticCairoText::NUX_UNDERLINE_DOUBLE;
+ action_link->underline_ = underline;
+ EXPECT_EQ(underline, action_link->underline_state.Get());
+}
+
+TEST_F(TestActionLink, FontCorrectlySetDifferent)
+{
+ ActionLinkMock link("test", "test");
+ link.font_hint_ = "Ubuntu 10";
+
+ EXPECT_CALL(link, ComputeContentSize()).Times(1);
+ EXPECT_CALL(link, QueueDraw()).Times(1);
+ link.font_hint.Set("Ubuntu 11");
+}
+
+TEST_F(TestActionLink, FontCorrectlySetSame)
+{
+ ActionLinkMock link("test", "test");
+ link.font_hint_ = "Ubuntu 10";
+
+ EXPECT_CALL(link, ComputeContentSize()).Times(0);
+ EXPECT_CALL(link, QueueDraw()).Times(0);
+ link.font_hint.Set(link.font_hint.Get());
+}
+
+TEST_F(TestActionLink, FontCorrectlyRetrieved)
+{
+ std::string font_hint = "Ubuntu 11";
+ action_link->font_hint_ = font_hint;
+ EXPECT_EQ(font_hint, action_link->font_hint.Get());
+}
+
+TEST_F(TestActionLink, LinkAlphaOnPressed)
+{
+ ButtonVisualState state = ButtonVisualState::VISUAL_STATE_PRESSED;
+ EXPECT_EQ(4, action_link->GetLinkAlpha(state));
+}
+
+TEST_F(TestActionLink, LinkAlphaOnNormal)
+{
+ ButtonVisualState state = ButtonVisualState::VISUAL_STATE_NORMAL;
+ EXPECT_EQ(4, action_link->GetLinkAlpha(state));
+}
+
+TEST_F(TestActionLink, LinkAlphaOnPrelight)
+{
+ ButtonVisualState state = ButtonVisualState::VISUAL_STATE_PRELIGHT;
+ EXPECT_EQ(1, action_link->GetLinkAlpha(state));
+}
+
+TEST_F(TestActionLink, LinkAlphaOnDisabled)
+{
+ ButtonVisualState state = ButtonVisualState::VISUAL_STATE_DISABLED;
+ EXPECT_EQ(4, action_link->GetLinkAlpha(state));
+}
+
+}
+
+}
diff --git a/tests/test_animator.cpp b/tests/test_animator.cpp
index 5d2c7f6d9..b0ec0adde 100644
--- a/tests/test_animator.cpp
+++ b/tests/test_animator.cpp
@@ -91,10 +91,10 @@ TEST_F(TestAnimator, ConstructDestroy)
double progress = 0.0f;
{
- Animator tmp_animator(200, 25);
+ Animator tmp_animator(400, 20);
- EXPECT_EQ(tmp_animator.GetDuration(), 200);
- EXPECT_EQ(tmp_animator.GetRate(), 25);
+ EXPECT_EQ(tmp_animator.GetDuration(), 400);
+ EXPECT_EQ(tmp_animator.GetRate(), 20);
bool got_update = false;
tmp_animator.animation_updated.connect([&progress, &got_update](double p) {
@@ -142,8 +142,7 @@ TEST_F(TestAnimator, SimulateStep)
TEST_F(TestAnimator, SimulateAnimation)
{
test_animator_.SetRate(20);
- test_animator_.SetDuration(200);
- long long start_time = g_get_monotonic_time() / 1000;
+ test_animator_.SetDuration(400);
test_animator_.Start();
EXPECT_EQ(started_, true);
@@ -152,27 +151,19 @@ TEST_F(TestAnimator, SimulateAnimation)
Utils::WaitUntil(got_update_);
EXPECT_GT(test_animator_.GetProgress(), 0.0f);
EXPECT_EQ(test_animator_.GetProgress(), current_progress_);
- EXPECT_EQ(n_steps_, 1);
+ EXPECT_GE(n_steps_, 1);
Utils::WaitUntil(ended_);
EXPECT_EQ(stopped_, false);
EXPECT_EQ(ended_, true);
- unsigned int expected_steps = (test_animator_.GetDuration() / 1000.0f) * test_animator_.GetRate();
- EXPECT_EQ(n_steps_, ceil(expected_steps));
-
- long long actual_time = g_get_monotonic_time() / 1000;
- long long expected_end = start_time+test_animator_.GetDuration();
- EXPECT_GE(actual_time, expected_end);
- EXPECT_LE(actual_time-expected_end, test_animator_.GetRate()*2);
-
ResetValues();
}
TEST_F(TestAnimator, SimulateStoppedAnimation)
{
- test_animator_.SetRate(30);
- test_animator_.SetDuration(100);
+ test_animator_.SetRate(20);
+ test_animator_.SetDuration(400);
test_animator_.Start();
EXPECT_EQ(started_, true);
EXPECT_EQ(test_animator_.IsRunning(), true);
@@ -193,8 +184,8 @@ TEST_F(TestAnimator, SimulateStoppedAnimation)
TEST_F(TestAnimator, SimulateStoppedAndContinueAnimation)
{
- test_animator_.SetRate(30);
- test_animator_.SetDuration(100);
+ test_animator_.SetRate(20);
+ test_animator_.SetDuration(400);
test_animator_.Start();
EXPECT_EQ(started_, true);
EXPECT_EQ(test_animator_.IsRunning(), true);
@@ -208,16 +199,11 @@ TEST_F(TestAnimator, SimulateStoppedAndContinueAnimation)
stopped_ = false;
ended_ = false;
- long long start_time = g_get_monotonic_time() / 1000;
- long long expected_end = start_time + (test_animator_.GetDuration() / current_progress_);
test_animator_.Start(test_animator_.GetProgress());
Utils::WaitUntil(ended_);
EXPECT_EQ(stopped_, false);
EXPECT_EQ(ended_, true);
- long long actual_time = g_get_monotonic_time() / 1000;
- EXPECT_LT(expected_end-actual_time, test_animator_.GetDuration());
-
ResetValues();
}
@@ -225,10 +211,10 @@ TEST_F(TestAnimator, SimulateOneTimeDurationStart)
{
unsigned int default_duration = 100;
- test_animator_.SetRate(30);
+ test_animator_.SetRate(20);
test_animator_.SetDuration(default_duration);
- unsigned int one_time_duration = 75;
+ unsigned int one_time_duration = 200;
test_animator_.Start(one_time_duration);
EXPECT_EQ(started_, true);
EXPECT_EQ(test_animator_.IsRunning(), true);
@@ -251,10 +237,10 @@ TEST_F(TestAnimator, SimulateOneTimeDurationStartStop)
{
unsigned int default_duration = 100;
- test_animator_.SetRate(30);
+ test_animator_.SetRate(20);
test_animator_.SetDuration(default_duration);
- unsigned int one_time_duration = 75;
+ unsigned int one_time_duration = 200;
test_animator_.Start(one_time_duration);
EXPECT_EQ(started_, true);
EXPECT_EQ(test_animator_.IsRunning(), true);
@@ -273,22 +259,18 @@ TEST_F(TestAnimator, SimulateOneTimeDurationStartStop)
TEST_F(TestAnimator, SimulateZeroDuration)
{
- test_animator_.SetRate(30);
+ test_animator_.SetRate(20);
test_animator_.SetDuration(0);
EXPECT_EQ(started_, false);
EXPECT_EQ(ended_, false);
EXPECT_EQ(test_animator_.IsRunning(), false);
- long long start_time = g_get_monotonic_time() / 1000;
test_animator_.Start();
EXPECT_EQ(started_, true);
Utils::WaitUntil(ended_);
EXPECT_EQ(ended_, true);
-
- long long end_time = g_get_monotonic_time() / 1000;
- EXPECT_LT(end_time - start_time, test_animator_.GetRate()*2);
}
diff --git a/tests/test_application_launcher_icon.cpp b/tests/test_application_launcher_icon.cpp
index 0ae91e76f..f409473d9 100644
--- a/tests/test_application_launcher_icon.cpp
+++ b/tests/test_application_launcher_icon.cpp
@@ -27,14 +27,15 @@
#include "ApplicationLauncherIcon.h"
#include "FavoriteStore.h"
-#include "bamf-mock-application.h"
+#include "mock-application.h"
+
using namespace unity;
+using namespace testmocks;
using namespace unity::launcher;
namespace
{
-
const std::string DEFAULT_EMPTY_ICON = "application-default-icon";
const std::string USC_DESKTOP = BUILDDIR"/tests/data/applications/ubuntu-software-center.desktop";
const std::string NO_ICON_DESKTOP = BUILDDIR"/tests/data/applications/no-icon.desktop";
@@ -44,24 +45,22 @@ class TestApplicationLauncherIcon : public testing::Test
public:
virtual void SetUp()
{
- BamfApplication* bamf_app;
- bamf_matcher = bamf_matcher_get_default();
-
- bamf_app = bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), TRUE);
- usc_icon = new launcher::ApplicationLauncherIcon(bamf_app);
+ usc_app.reset(new MockApplication(USC_DESKTOP, "softwarecenter"));
+ usc_icon = new launcher::ApplicationLauncherIcon(usc_app);
ASSERT_EQ(usc_icon->DesktopFile(), USC_DESKTOP);
- bamf_app = bamf_matcher_get_application_for_desktop_file(bamf_matcher, NO_ICON_DESKTOP.c_str(), TRUE);
- empty_icon = new launcher::ApplicationLauncherIcon(bamf_app);
+ empty_app.reset(new MockApplication(NO_ICON_DESKTOP));
+ empty_icon = new launcher::ApplicationLauncherIcon(empty_app);
ASSERT_EQ(empty_icon->DesktopFile(), NO_ICON_DESKTOP);
- mock_app = bamf_mock_application_new();
- mock_icon = new launcher::ApplicationLauncherIcon(glib::object_cast<BamfApplication>(mock_app));
+ mock_app.reset(new MockApplication(""));
+ mock_icon = new launcher::ApplicationLauncherIcon(mock_app);
ASSERT_TRUE(mock_icon->DesktopFile().empty());
}
- glib::Object<BamfMatcher> bamf_matcher;
- glib::Object<BamfMockApplication> mock_app;
+ std::shared_ptr<MockApplication> usc_app;
+ std::shared_ptr<MockApplication> empty_app;
+ std::shared_ptr<MockApplication> mock_app;
nux::ObjectPtr<launcher::ApplicationLauncherIcon> usc_icon;
nux::ObjectPtr<launcher::ApplicationLauncherIcon> empty_icon;
nux::ObjectPtr<launcher::ApplicationLauncherIcon> mock_icon;
@@ -91,53 +90,39 @@ TEST_F(TestApplicationLauncherIcon, TestDefaultIcon)
TEST_F(TestApplicationLauncherIcon, Stick)
{
- BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
- ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
-
bool saved = false;
usc_icon->position_saved.connect([&saved] {saved = true;});
usc_icon->Stick(false);
- EXPECT_TRUE(bamf_view_is_sticky(bamf_app));
+ EXPECT_TRUE(usc_app->sticky());
EXPECT_TRUE(usc_icon->IsSticky());
EXPECT_TRUE(usc_icon->IsVisible());
EXPECT_FALSE(saved);
usc_icon->Stick(true);
EXPECT_FALSE(saved);
- bamf_view_set_sticky(bamf_app, FALSE);
}
TEST_F(TestApplicationLauncherIcon, StickAndSave)
{
- BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
- ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
-
bool saved = false;
usc_icon->position_saved.connect([&saved] {saved = true;});
usc_icon->Stick(true);
- EXPECT_TRUE(bamf_view_is_sticky(bamf_app));
+ EXPECT_TRUE(usc_app->sticky());
EXPECT_TRUE(usc_icon->IsSticky());
EXPECT_TRUE(usc_icon->IsVisible());
EXPECT_TRUE(saved);
- bamf_view_set_sticky(bamf_app, FALSE);
}
TEST_F(TestApplicationLauncherIcon, Unstick)
{
- BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
- ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
-
bool forgot = false;
usc_icon->position_forgot.connect([&forgot] {forgot = true;});
usc_icon->Stick(false);
- ASSERT_TRUE(bamf_view_is_sticky(bamf_app));
- ASSERT_TRUE(usc_icon->IsSticky());
-
usc_icon->UnStick();
- EXPECT_FALSE(bamf_view_is_sticky(bamf_app));
+ EXPECT_FALSE(usc_app->sticky());
EXPECT_FALSE(usc_icon->IsSticky());
EXPECT_FALSE(usc_icon->IsVisible());
EXPECT_TRUE(forgot);
@@ -152,32 +137,31 @@ TEST_F(TestApplicationLauncherIcon, RemoteUri)
TEST_F(TestApplicationLauncherIcon, EmptyTooltipUpdatesOnRunning)
{
ASSERT_TRUE(mock_icon->tooltip_text().empty());
- bamf_mock_application_set_name (mock_app, "Got Name");
-
+ mock_app->title_ = "Got Name";
ASSERT_TRUE(mock_icon->tooltip_text().empty());
- bamf_mock_application_set_running(mock_app, TRUE);
+ mock_app->SetRunState(true);
EXPECT_EQ(mock_icon->tooltip_text(), "Got Name");
- bamf_mock_application_set_running(mock_app, FALSE);
- bamf_mock_application_set_name (mock_app, "New Name");
- bamf_mock_application_set_running(mock_app, TRUE);
+ mock_app->SetRunState(false);
+ mock_app->title_ = "New Name";
+ mock_app->SetRunState(true);
EXPECT_EQ(mock_icon->tooltip_text(), "Got Name");
}
TEST_F(TestApplicationLauncherIcon, InvalidIconUpdatesOnRunning)
{
ASSERT_EQ(mock_icon->icon_name(), DEFAULT_EMPTY_ICON);
- bamf_mock_application_set_icon (mock_app, "icon-name");
+ mock_app->icon_ = "icon-name";
ASSERT_EQ(mock_icon->icon_name(), DEFAULT_EMPTY_ICON);
- bamf_mock_application_set_running(mock_app, TRUE);
+ mock_app->SetRunState(true);
EXPECT_EQ(mock_icon->icon_name(), "icon-name");
- bamf_mock_application_set_running(mock_app, FALSE);
- bamf_mock_application_set_icon (mock_app, "new-icon-name");
- bamf_mock_application_set_running(mock_app, TRUE);
+ mock_app->SetRunState(false);
+ mock_app->icon_ = "new-icon-name";
+ mock_app->SetRunState(true);
EXPECT_EQ(mock_icon->icon_name(), "icon-name");
}
diff --git a/tests/test_expo_launcher_icon.cpp b/tests/test_expo_launcher_icon.cpp
index 8d04d8619..81a3dd31c 100644
--- a/tests/test_expo_launcher_icon.cpp
+++ b/tests/test_expo_launcher_icon.cpp
@@ -15,34 +15,39 @@
* <http://www.gnu.org/licenses/>
*
* Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
+ * Andrea Azzarone <andrea.azzarone@canonical.com>
*/
#include <gmock/gmock.h>
#include "launcher/ExpoLauncherIcon.h"
-#include "unity-shared/WindowManager.h"
+#include "unity-shared/StandaloneWindowManager.h"
using namespace unity;
using namespace unity::launcher;
namespace
{
+
struct TestExpoLauncherIcon : testing::Test
{
+ TestExpoLauncherIcon()
+ : wm(dynamic_cast<StandaloneWindowManager*>(&WindowManager::Default()))
+ {}
+
ExpoLauncherIcon icon;
+ StandaloneWindowManager* wm;
};
TEST_F(TestExpoLauncherIcon, ActivateToggleExpo)
{
- WindowManager& wm = WindowManager::Default();
-
- ASSERT_FALSE(wm.IsExpoActive());
+ ASSERT_FALSE(wm->IsExpoActive());
icon.Activate(ActionArg());
- ASSERT_TRUE(wm.IsExpoActive());
+ ASSERT_TRUE(wm->IsExpoActive());
icon.Activate(ActionArg());
- EXPECT_FALSE(wm.IsExpoActive());
+ EXPECT_FALSE(wm->IsExpoActive());
}
TEST_F(TestExpoLauncherIcon, Position)
@@ -55,4 +60,60 @@ TEST_F(TestExpoLauncherIcon, RemoteUri)
EXPECT_EQ(icon.RemoteUri(), "unity://expo-icon");
}
+TEST_F(TestExpoLauncherIcon, Icon2x2Layout)
+{
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-top-left");
+
+ wm->SetCurrentViewport(nux::Point(1, 0));
+ wm->screen_viewport_switch_ended.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-right-top");
+
+ wm->SetCurrentViewport(nux::Point(0, 1));
+ wm->screen_viewport_switch_ended.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-left-bottom");
+
+ wm->SetCurrentViewport(nux::Point(1, 1));
+ wm->screen_viewport_switch_ended.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-right-bottom");
+
+ wm->SetCurrentViewport(nux::Point(0, 0));
+ wm->screen_viewport_switch_ended.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-top-left");
+}
+
+TEST_F(TestExpoLauncherIcon, Icon2x2Layout_Expo)
+{
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-top-left");
+
+ wm->SetCurrentViewport(nux::Point(1, 0));
+ wm->terminate_expo.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-right-top");
+
+ wm->SetCurrentViewport(nux::Point(0, 1));
+ wm->terminate_expo.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-left-bottom");
+
+ wm->SetCurrentViewport(nux::Point(1, 1));
+ wm->terminate_expo.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-right-bottom");
+
+ wm->SetCurrentViewport(nux::Point(0, 0));
+ wm->terminate_expo.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-top-left");
+}
+
+TEST_F(TestExpoLauncherIcon, IconNot2x2Layout)
+{
+ wm->SetCurrentViewport(nux::Point(1, 0));
+ wm->screen_viewport_switch_ended.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-right-top");
+
+ wm->viewport_layout_changed.emit(5, 2);
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-top-left");
+
+ wm->SetCurrentViewport(nux::Point(1, 1));
+ wm->screen_viewport_switch_ended.emit();
+ EXPECT_EQ(icon.icon_name, "workspace-switcher-top-left");
+}
+
}
diff --git a/tests/test_glib_source.cpp b/tests/test_glib_source.cpp
index 7d3641d0b..7f2d2c51a 100644
--- a/tests/test_glib_source.cpp
+++ b/tests/test_glib_source.cpp
@@ -131,55 +131,46 @@ TEST(TestGLibTimeout, OneShotRun)
{
callback_called = false;
callback_call_count = 0;
- struct timespec pre, post;
+ bool removed_called = false;
Timeout timeout(100, &OnSourceCallbackStop);
- clock_gettime(CLOCK_MONOTONIC, &pre);
- timeout.removed.connect([&] (unsigned int id) { clock_gettime(CLOCK_MONOTONIC, &post); });
+ timeout.removed.connect([&] (unsigned int id) { removed_called = true; });
Utils::WaitForTimeoutMSec(500);
EXPECT_FALSE(timeout.IsRunning());
EXPECT_TRUE(callback_called);
EXPECT_EQ(callback_call_count, 1);
- int time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
- EXPECT_GE(time_delta, 100);
- EXPECT_LT(time_delta, 110);
+ EXPECT_TRUE(removed_called);
}
TEST(TestGLibTimeout, MultipleShotsRun)
{
callback_called = false;
callback_call_count = 0;
- struct timespec pre, post;
+ bool removed_called = false;
{
+ auto check_function = []() { return (callback_call_count > 1) ? true : false; };
Timeout timeout(100, &OnSourceCallbackContinue);
- clock_gettime(CLOCK_MONOTONIC, &pre);
- timeout.removed.connect([&] (unsigned int id) { clock_gettime(CLOCK_MONOTONIC, &post); });
-
- Utils::WaitForTimeoutMSec(650);
+ timeout.removed.connect([&] (unsigned int id) { removed_called = true; });
+ Utils::WaitUntil(check_function, true, 1);
EXPECT_TRUE(timeout.IsRunning());
}
EXPECT_TRUE(callback_called);
- EXPECT_EQ(callback_call_count, 6);
- int time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
- EXPECT_GE(time_delta, 600);
- EXPECT_LT(time_delta, 700);
+ EXPECT_GT(callback_call_count, 1);
+ EXPECT_TRUE(removed_called);
}
TEST(TestGLibTimeout, OneShotRunWithEmptyCallback)
{
- struct timespec pre, post;
+ bool removed_called = false;
Timeout timeout(100, Source::Callback());
- clock_gettime(CLOCK_MONOTONIC, &pre);
- timeout.removed.connect([&] (unsigned int id) { clock_gettime(CLOCK_MONOTONIC, &post); });
+ timeout.removed.connect([&] (unsigned int id) { removed_called = true; });
Utils::WaitForTimeoutMSec(500);
EXPECT_FALSE(timeout.IsRunning());
- int time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
- EXPECT_GE(time_delta, 100);
- EXPECT_LT(time_delta, 110);
+ EXPECT_TRUE(removed_called);
}
TEST(TestGLibTimeout, Removal)
@@ -337,7 +328,7 @@ TEST(TestGLibTimeoutSeconds, OneShotRun)
EXPECT_FALSE(timeout.IsRunning());
EXPECT_TRUE(callback_called);
EXPECT_EQ(callback_call_count, 1);
- int time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
+ DeltaTime time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
EXPECT_GE(time_delta, 500);
EXPECT_LT(time_delta, 2000);
}
@@ -360,7 +351,7 @@ TEST(TestGLibTimeoutSeconds, MultipleShotsRun)
EXPECT_TRUE(callback_called);
EXPECT_GE(callback_call_count, 3);
EXPECT_LE(callback_call_count, 4);
- int time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
+ DeltaTime time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
EXPECT_GE(time_delta, 3500);
EXPECT_LT(time_delta, 5000);
}
@@ -424,7 +415,7 @@ TEST(TestGLibIdle, MultipleShotsRun)
EXPECT_TRUE(callback_called);
EXPECT_GT(callback_call_count, 1);
- int time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
+ DeltaTime time_delta = unity::TimeUtil::TimeDelta(&post, &pre);
EXPECT_GE(time_delta, 100);
EXPECT_LT(time_delta, 200);
}
diff --git a/tests/test_indicator.cpp b/tests/test_indicator.cpp
index 5d3ac5aa6..c65f03fa3 100644
--- a/tests/test_indicator.cpp
+++ b/tests/test_indicator.cpp
@@ -145,34 +145,31 @@ TEST(TestIndicator, ChildrenSignals)
std::string show_entry;
int show_x, show_y;
- unsigned int show_xid, show_button, show_timestamp;
+ unsigned int show_xid, show_button;
// Connecting to signals
indicator.on_show_menu.connect([&] (std::string const& eid, unsigned int xid,
- int x, int y, unsigned int button,
- unsigned int timestamp) {
+ int x, int y, unsigned int button) {
show_entry = eid;
show_xid = xid;
show_x = x;
show_y = y;
show_button = button;
- show_timestamp = timestamp;
});
- entry1->ShowMenu(123456789, 50, 100, 2, 1328058770);
+ entry1->ShowMenu(123456789, 50, 100, 2);
EXPECT_EQ(show_entry, "test-entry-1");
EXPECT_EQ(show_xid, 123456789);
EXPECT_EQ(show_x, 50);
EXPECT_EQ(show_y, 100);
EXPECT_EQ(show_button, 2);
- EXPECT_EQ(show_timestamp, 1328058770);
// Check if a removed entry still emits a signal to the old indicator
show_entry = "invalid-entry";
sync_data.remove(entry1);
indicator.Sync(sync_data);
- entry1->ShowMenu(123456789, 50, 100, 2, 1328058770);
+ entry1->ShowMenu(123456789, 50, 100, 2);
EXPECT_EQ(show_entry, "invalid-entry");
// Checking secondary activate signal
@@ -182,16 +179,12 @@ TEST(TestIndicator, ChildrenSignals)
indicator.Sync(sync_data);
std::string secondary_activated;
- unsigned int secondary_timestamp;
- indicator.on_secondary_activate.connect([&] (std::string const& eid,
- unsigned int timestamp) {
+ indicator.on_secondary_activate.connect([&] (std::string const& eid) {
secondary_activated = eid;
- secondary_timestamp = timestamp;
});
- entry->SecondaryActivate(1328060717);
+ entry->SecondaryActivate();
EXPECT_EQ(secondary_activated, "test-entry-2");
- EXPECT_EQ(secondary_timestamp, 1328060717);
// Checking scroll signal
std::string scrolled_entry;
diff --git a/tests/test_indicator_appmenu.cpp b/tests/test_indicator_appmenu.cpp
index 30cac8372..00e791b86 100644
--- a/tests/test_indicator_appmenu.cpp
+++ b/tests/test_indicator_appmenu.cpp
@@ -42,25 +42,22 @@ TEST(TestAppmenuIndicator, ShowAppmenu)
bool signal_emitted = false;
int show_x, show_y;
- unsigned int show_xid, show_timestamp;
+ unsigned show_xid;
// Connecting to signals
- indicator.on_show_appmenu.connect([&] (unsigned int xid, int x, int y,
- unsigned int timestamp) {
+ indicator.on_show_appmenu.connect([&] (unsigned int xid, int x, int y) {
signal_emitted = true;
show_xid = xid;
show_x = x;
show_y = y;
- show_timestamp = timestamp;
});
- indicator.ShowAppmenu(123456789, 50, 100, 1328308554);
+ indicator.ShowAppmenu(123456789, 50, 100);
EXPECT_TRUE(signal_emitted);
EXPECT_EQ(show_xid, 123456789);
EXPECT_EQ(show_x, 50);
EXPECT_EQ(show_y, 100);
- EXPECT_EQ(show_timestamp, 1328308554);
}
}
diff --git a/tests/test_indicator_entry.cpp b/tests/test_indicator_entry.cpp
index 6a426811e..ce3231e94 100644
--- a/tests/test_indicator_entry.cpp
+++ b/tests/test_indicator_entry.cpp
@@ -159,17 +159,16 @@ TEST(TestIndicatorEntry, TestOnScroll)
struct ShowMenuRecorder
{
- void OnShowMenu(std::string const& a, unsigned int b, int c, int d, unsigned int e, unsigned int f)
+ void OnShowMenu(std::string const& a, unsigned b, int c, int d, unsigned e)
{
name = a;
xid = b;
x = c;
y = d;
button = e;
- timestamp = f;
}
std::string name;
- unsigned int xid, timestamp, button;
+ unsigned xid, button;
int x, y;
};
@@ -182,12 +181,11 @@ TEST(TestIndicatorEntry, TestOnShowMenu)
ShowMenuRecorder recorder;
entry.on_show_menu.connect(sigc::mem_fun(recorder, &ShowMenuRecorder::OnShowMenu));
- entry.ShowMenu(10, 20, 1, 12345);
+ entry.ShowMenu(10, 20, 1);
EXPECT_EQ(recorder.name, "id");
EXPECT_EQ(recorder.xid, 0);
EXPECT_EQ(recorder.x, 10);
EXPECT_EQ(recorder.y, 20);
- EXPECT_EQ(recorder.timestamp, 12345);
EXPECT_EQ(recorder.button, 1);
}
@@ -200,12 +198,11 @@ TEST(TestIndicatorEntry, TestOnShowMenuXid)
ShowMenuRecorder recorder;
entry.on_show_menu.connect(sigc::mem_fun(recorder, &ShowMenuRecorder::OnShowMenu));
- entry.ShowMenu(88492615, 15, 25, 2, 123456);
+ entry.ShowMenu(88492615, 15, 25, 2);
EXPECT_EQ(recorder.name, "xid");
EXPECT_EQ(recorder.xid, 88492615);
EXPECT_EQ(recorder.x, 15);
EXPECT_EQ(recorder.y, 25);
- EXPECT_EQ(recorder.timestamp, 123456);
EXPECT_EQ(recorder.button, 2);
}
diff --git a/tests/test_indicators.cpp b/tests/test_indicators.cpp
index e0a1d3618..e2ced7266 100644
--- a/tests/test_indicators.cpp
+++ b/tests/test_indicators.cpp
@@ -45,7 +45,6 @@ struct TargetData
y = 0;
xid = 0;
button = 0;
- timestamp = 0;
}
std::string entry;
@@ -55,7 +54,6 @@ struct TargetData
int y;
unsigned int xid;
unsigned int button;
- unsigned int timestamp;
};
class MockIndicators : public Indicators
@@ -72,35 +70,29 @@ public:
}
virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
- int x, int y, unsigned int button,
- unsigned int timestamp)
+ int x, int y, unsigned int button)
{
- on_entry_show_menu.emit(entry_id, xid, x, y, button, timestamp);
+ on_entry_show_menu.emit(entry_id, xid, x, y, button);
target.entry = entry_id;
target.xid = xid;
target.x = x;
target.y = y;
target.button = button;
- target.timestamp = timestamp;
}
- virtual void OnEntrySecondaryActivate(std::string const& entry_id,
- unsigned int timestamp)
+ virtual void OnEntrySecondaryActivate(std::string const& entry_id)
{
target.entry = entry_id;
- target.timestamp = timestamp;
}
- virtual void OnShowAppMenu(unsigned int xid, int x, int y,
- unsigned int timestamp)
+ virtual void OnShowAppMenu(unsigned int xid, int x, int y)
{
- on_show_appmenu.emit(xid, x, y, timestamp);
+ on_show_appmenu.emit(xid, x, y);
target.xid = xid;
target.x = x;
target.y = y;
- target.timestamp = timestamp;
}
// Redirecting protected methods
@@ -470,49 +462,44 @@ TEST(TestIndicators, EntryShowMenu)
TargetData show_menu_data;
sigc::connection on_entry_show_menu_conn =
indicators.on_entry_show_menu.connect([&] (std::string const& e, unsigned int w,
- int x, int y, unsigned int b, unsigned int t) {
+ int x, int y, unsigned int b) {
show_menu_data.entry = e;
show_menu_data.xid = w;
show_menu_data.x = x;
show_menu_data.y = y;
show_menu_data.button = b;
- show_menu_data.timestamp = t;
});
- entry13->ShowMenu(465789, 35, 53, 2, 1331773412);
+ entry13->ShowMenu(465789, 35, 53, 2);
EXPECT_EQ(indicators.target.entry, entry13->id());
EXPECT_EQ(indicators.target.xid, 465789);
EXPECT_EQ(indicators.target.x, 35);
EXPECT_EQ(indicators.target.y, 53);
EXPECT_EQ(indicators.target.button, 2);
- EXPECT_EQ(indicators.target.timestamp, 1331773412);
EXPECT_EQ(show_menu_data.entry, entry13->id());
EXPECT_EQ(show_menu_data.xid, 465789);
EXPECT_EQ(show_menu_data.x, 35);
EXPECT_EQ(show_menu_data.y, 53);
EXPECT_EQ(show_menu_data.button, 2);
- EXPECT_EQ(show_menu_data.timestamp, 1331773412);
show_menu_data.Reset();
indicators.target.Reset();
- entry13->ShowMenu(55, 68, 3, 1331773883);
+ entry13->ShowMenu(55, 68, 3);
EXPECT_EQ(indicators.target.entry, entry13->id());
EXPECT_EQ(indicators.target.xid, 0);
EXPECT_EQ(indicators.target.x, 55);
EXPECT_EQ(indicators.target.y, 68);
EXPECT_EQ(indicators.target.button, 3);
- EXPECT_EQ(indicators.target.timestamp, 1331773883);
EXPECT_EQ(show_menu_data.entry, entry13->id());
EXPECT_EQ(show_menu_data.xid, 0);
EXPECT_EQ(show_menu_data.x, 55);
EXPECT_EQ(show_menu_data.y, 68);
EXPECT_EQ(show_menu_data.button, 3);
- EXPECT_EQ(show_menu_data.timestamp, 1331773883);
on_entry_show_menu_conn.disconnect();
}
@@ -532,9 +519,8 @@ TEST(TestIndicators, EntryScroll)
EXPECT_EQ(indicators.target.entry, entry11->id());
EXPECT_EQ(indicators.target.delta, 80);
- entry11->SecondaryActivate(1331774167);
+ entry11->SecondaryActivate();
EXPECT_EQ(indicators.target.entry, entry11->id());
- EXPECT_EQ(indicators.target.timestamp, 1331774167);
}
TEST(TestIndicators, EntrySecondaryActivate)
@@ -548,9 +534,8 @@ TEST(TestIndicators, EntrySecondaryActivate)
Entry::Ptr entry22(indicators.GetIndicator("indicator-test-2")->GetEntry("indicator-test-2|entry-1"));
ASSERT_THAT(entry22, NotNull());
- entry22->SecondaryActivate(1331774167);
+ entry22->SecondaryActivate();
EXPECT_EQ(indicators.target.entry, entry22->id());
- EXPECT_EQ(indicators.target.timestamp, 1331774167);
}
TEST(TestIndicators, ShowAppMenu)
@@ -572,14 +557,13 @@ TEST(TestIndicators, ShowAppMenu)
indicators.target.Reset();
- appmenu_indicator->ShowAppmenu(4356789, 54, 13, 1331774961);
+ appmenu_indicator->ShowAppmenu(4356789, 54, 13);
EXPECT_TRUE(indicators.target.entry.empty());
EXPECT_EQ(indicators.target.xid, 4356789);
EXPECT_EQ(indicators.target.x, 54);
EXPECT_EQ(indicators.target.y, 13);
EXPECT_EQ(indicators.target.button, 0);
- EXPECT_EQ(indicators.target.timestamp, 1331774961);
}
}
diff --git a/tests/test_launcher_controller.cpp b/tests/test_launcher_controller.cpp
index 516125484..ebdb0f66f 100644
--- a/tests/test_launcher_controller.cpp
+++ b/tests/test_launcher_controller.cpp
@@ -33,11 +33,14 @@
#include "PanelStyle.h"
#include "UnitySettings.h"
#include "UBusMessages.h"
+#include "logger_helper.h"
#include "test_utils.h"
#include "test_uscreen_mock.h"
#include "test_mock_devices.h"
-#include "bamf-mock-application.h"
+#include "mock-application.h"
+
+using namespace testmocks;
using namespace unity::launcher;
using namespace testing;
@@ -133,21 +136,21 @@ struct MockApplicationLauncherIcon : public ApplicationLauncherIcon
typedef bool Fake;
MockApplicationLauncherIcon(Fake = true, std::string const& remote_uri = "")
- : ApplicationLauncherIcon(BAMF_APPLICATION(bamf_mock_application_new()))
+ : ApplicationLauncherIcon(std::make_shared<MockApplication>(""))
, remote_uri_(remote_uri)
{
InitMock();
SetQuirk(Quirk::VISIBLE, true);
}
- explicit MockApplicationLauncherIcon(BamfApplication* app)
+ explicit MockApplicationLauncherIcon(ApplicationPtr const& app)
: ApplicationLauncherIcon(app)
{
InitMock();
}
MockApplicationLauncherIcon(std::string const& desktop_file)
- : ApplicationLauncherIcon(bamf_matcher_get_application_for_desktop_file(bamf_matcher_get_default(), desktop_file.c_str(), TRUE))
+ : ApplicationLauncherIcon(std::make_shared<MockApplication>(desktop_file))
{
InitMock();
}
@@ -179,8 +182,8 @@ struct MockVolumeLauncherIcon : public VolumeLauncherIcon
typedef nux::ObjectPtr<MockVolumeLauncherIcon> Ptr;
MockVolumeLauncherIcon()
- : VolumeLauncherIcon(Volume::Ptr(volume_ = new MockVolume()),
- std::make_shared<MockDevicesSettings>())
+ : VolumeLauncherIcon(Volume::Ptr(volume_ = new NiceMock<MockVolume>()),
+ std::make_shared<NiceMock<MockDevicesSettings>>())
, uuid_(std::to_string(g_random_int()))
{
ON_CALL(*volume_, GetIdentifier()).WillByDefault(Return(uuid_));
@@ -201,12 +204,14 @@ namespace launcher
struct TestLauncherController : public testing::Test
{
TestLauncherController()
- : xdnd_manager_(std::make_shared<XdndManager>())
+ : logger_output_(std::make_shared<helper::CaptureLogOutput>())
+ , xdnd_manager_(std::make_shared<XdndManager>())
, lc(xdnd_manager_)
{}
virtual void SetUp()
{
+ logger_output_->GetOutput(); // discard old output.
lc.multiple_launchers = true;
}
@@ -255,7 +260,7 @@ protected:
void DisconnectSignals()
{
- Impl()->view_opened_signal_.Disconnect();
+ // Impl()->view_opened_signal_.Disconnect();
Impl()->device_section_.icon_added.clear();
Impl()->model_->icon_removed.clear();
Impl()->model_->saved.clear();
@@ -263,6 +268,7 @@ protected:
}
};
+ std::shared_ptr<helper::CaptureLogOutput> logger_output_;
MockUScreen uscreen;
Settings settings;
panel::Style panel_style;
@@ -279,7 +285,6 @@ TEST_F(TestLauncherController, Construction)
ASSERT_EQ(lc.launchers().size(), 1);
EXPECT_EQ(lc.launcher().monitor(), 0);
ASSERT_EQ(lc.Impl()->parent_, &lc);
- ASSERT_TRUE(lc.Impl()->matcher_.IsType(BAMF_TYPE_MATCHER));
ASSERT_NE(lc.Impl()->model_, nullptr);
EXPECT_EQ(lc.Impl()->expo_icon_->GetIconType(), AbstractLauncherIcon::IconType::EXPO);
EXPECT_EQ(lc.Impl()->desktop_icon_->GetIconType(), AbstractLauncherIcon::IconType::DESKTOP);
@@ -526,7 +531,7 @@ TEST_F(TestLauncherController, CreateFavoriteDesktopFile)
TEST_F(TestLauncherController, CreateFavoriteInvalidDesktopFile)
{
// This desktop file has already been added as favorite, so it is invalid
- std::string desktop_file = *(favorite_store.GetFavorites().begin());
+ std::string desktop_file = app::UBUNTU_ONE;
std::string icon_uri = FavoriteStore::URI_PREFIX_APP + desktop_file;
auto const& fav = lc.Impl()->CreateFavoriteIcon(icon_uri);
@@ -655,7 +660,7 @@ TEST_F(TestLauncherController, RegisterIconDevice)
TEST_F(TestLauncherController, RegisteredIconSavesPosition)
{
- MockApplicationLauncherIcon::Ptr app_icon(new MockApplicationLauncherIcon(true, "normal-icon.desktop"));
+ MockApplicationLauncherIcon::Ptr app_icon(new NiceMock<MockApplicationLauncherIcon>(true, "normal-icon.desktop"));
lc.Impl()->RegisterIcon(app_icon);
ASSERT_FALSE(favorite_store.IsFavorite(app_icon->RemoteUri()));
@@ -719,22 +724,15 @@ TEST_F(TestLauncherController, AddRunningApps)
lc.DisconnectSignals();
lc.Impl()->AddRunningApps();
- std::shared_ptr<GList> apps(bamf_matcher_get_applications(lc.Impl()->matcher_), g_list_free);
-
- for (GList *l = apps.get(); l; l = l->next)
+ // This test should be rewritten to not use the default application manager.
+ for (auto& app : ApplicationManager::Default().GetRunningApplications())
{
- if (!BAMF_IS_APPLICATION(l->data))
- continue;
-
- if (bamf_view_is_sticky(BAMF_VIEW(l->data)))
+ if (app->sticky())
continue;
- BamfApplication* app = BAMF_APPLICATION(l->data);
- ASSERT_NE(g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")), nullptr);
-
- auto desktop = bamf_application_get_desktop_file(app);
- std::string path(desktop ? desktop : "");
+ ASSERT_TRUE(app->seen());
+ auto path = app->desktop_file();
if (path.empty())
continue;
@@ -774,7 +772,6 @@ TEST_F(TestLauncherController, SetupIcons)
FavoriteStore::URI_PREFIX_APP + app::UPDATE_MANAGER });
lc.Impl()->SetupIcons();
lc.DisconnectSignals();
- std::shared_ptr<GList> apps(bamf_matcher_get_applications(lc.Impl()->matcher_), g_list_free);
auto fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::UBUNTU_ONE);
EXPECT_EQ(model->IconIndex(fav), icon_index);
@@ -788,23 +785,19 @@ TEST_F(TestLauncherController, SetupIcons)
fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::UPDATE_MANAGER);
EXPECT_EQ(model->IconIndex(fav), ++icon_index);
- for (GList *l = apps.get(); l; l = l->next)
+ for (auto& app : ApplicationManager::Default().GetRunningApplications())
{
- if (!BAMF_IS_APPLICATION(l->data))
- continue;
-
- if (bamf_view_is_sticky(BAMF_VIEW(l->data)))
+ if (app->sticky())
continue;
- auto desktop = bamf_application_get_desktop_file(BAMF_APPLICATION(l->data));
- std::string path(desktop ? desktop : "");
- ++icon_index;
+ ASSERT_TRUE(app->seen());
+ auto path = app->desktop_file();
if (path.empty())
continue;
auto icon = lc.GetIconByDesktop(path);
- ASSERT_EQ(model->IconIndex(icon), icon_index);
+ ASSERT_EQ(model->IconIndex(icon), ++icon_index);
}
ASSERT_EQ(model->IconIndex(lc.Impl()->expo_icon_), ++icon_index);
@@ -820,7 +813,6 @@ TEST_F(TestLauncherController, ResetIconPriorities)
favorite_store.AddFavorite(places::DEVICES_URI, -1);
lc.Impl()->SetupIcons();
lc.DisconnectSignals();
- std::shared_ptr<GList> apps(bamf_matcher_get_applications(lc.Impl()->matcher_), g_list_free);
favorite_store.SetFavorites({ places::DEVICES_URI,
FavoriteStore::URI_PREFIX_APP + app::SW_CENTER,
@@ -837,25 +829,19 @@ TEST_F(TestLauncherController, ResetIconPriorities)
auto fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::SW_CENTER);
EXPECT_EQ(model->IconIndex(fav), ++icon_index);
- for (GList *l = apps.get(); l; l = l->next)
+ for (auto& app : ApplicationManager::Default().GetRunningApplications())
{
- if (!BAMF_IS_APPLICATION(l->data))
+ if (app->sticky())
continue;
- if (bamf_view_is_sticky(BAMF_VIEW(l->data)))
- continue;
-
- auto desktop = bamf_application_get_desktop_file(BAMF_APPLICATION(l->data));
- std::string path(desktop ? desktop : "");
- ++icon_index;
+ ASSERT_TRUE(app->seen());
+ auto path = app->desktop_file();
if (path.empty())
continue;
- auto const& icon = lc.GetIconByDesktop(path);
-
- ASSERT_TRUE(icon.IsValid());
- ASSERT_EQ(model->IconIndex(icon), icon_index);
+ auto icon = lc.GetIconByDesktop(path);
+ ASSERT_EQ(model->IconIndex(icon), ++icon_index);
}
fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::UBUNTU_ONE);
@@ -1081,7 +1067,7 @@ TEST_F(TestLauncherController, LauncherAddRequestDeviceAdd)
TEST_F(TestLauncherController, LauncherAddRequestDeviceStick)
{
auto const& model = lc.Impl()->model_;
- MockVolumeLauncherIcon::Ptr device_icon(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr device_icon(new NiceMock<MockVolumeLauncherIcon>());
lc.Impl()->RegisterIcon(device_icon, std::numeric_limits<int>::max());
auto app_icons = model->GetSublist<ApplicationLauncherIcon>();
@@ -1105,7 +1091,7 @@ TEST_F(TestLauncherController, LauncherRemoveRequestApplicationUnStickAndQuit)
TEST_F(TestLauncherController, LauncherRemoveRequestDeviceEjects)
{
- MockVolumeLauncherIcon::Ptr device_icon(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr device_icon(new NiceMock<MockVolumeLauncherIcon>());
EXPECT_CALL(*(device_icon->volume_), CanBeEjected())
.WillRepeatedly(Return(true));
@@ -1120,7 +1106,7 @@ TEST_F(TestLauncherController, LauncherRemoveRequestDeviceEjects)
TEST_F(TestLauncherController, LauncherRemoveRequestDeviceStops)
{
- MockVolumeLauncherIcon::Ptr device_icon(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr device_icon(new NiceMock<MockVolumeLauncherIcon>());
EXPECT_CALL(*(device_icon->volume_), CanBeEjected())
.WillRepeatedly(Return(false));
@@ -1170,15 +1156,15 @@ TEST_F(TestLauncherController, SaveIconsOrder)
lc.DisconnectSignals();
int priority = 0;
- MockApplicationLauncherIcon::Ptr sticky_app(new MockApplicationLauncherIcon(true, "sticky-app"));
+ MockApplicationLauncherIcon::Ptr sticky_app(new NiceMock<MockApplicationLauncherIcon>(true, "sticky-app"));
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockApplicationLauncherIcon::Ptr invisible_app(new MockApplicationLauncherIcon(true, "invisible-app"));
+ MockApplicationLauncherIcon::Ptr invisible_app(new NiceMock<MockApplicationLauncherIcon>(true, "invisible-app"));
invisible_app->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
lc.Impl()->RegisterIcon(invisible_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1205,11 +1191,11 @@ TEST_F(TestLauncherController, SaveIconsOrderWithOnlyStickyIcons)
lc.ClearModel();
int priority = 0;
- MockApplicationLauncherIcon::Ptr sticky_app(new MockApplicationLauncherIcon(true, "sticky-app"));
+ MockApplicationLauncherIcon::Ptr sticky_app(new NiceMock<MockApplicationLauncherIcon>(true, "sticky-app"));
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1234,11 +1220,11 @@ TEST_F(TestLauncherController, SaveIconsOrderTriesToKeepIconProvidersOrder)
FavoriteStore::URI_PREFIX_APP + "bar.desktop", places::APPS_URI,
FavoriteStore::URI_PREFIX_APP + "foobar.desktop"});
- MockApplicationLauncherIcon::Ptr sticky_app(new MockApplicationLauncherIcon(true, "sticky-app"));
+ MockApplicationLauncherIcon::Ptr sticky_app(new NiceMock<MockApplicationLauncherIcon>(true, "sticky-app"));
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1259,11 +1245,11 @@ TEST_F(TestLauncherController, SaveIconsOrderTriesToKeepIconProvidersOrder2)
lc.ClearModel();
int priority = 0;
- MockApplicationLauncherIcon::Ptr sticky_app(new MockApplicationLauncherIcon(true, "sticky-app"));
+ MockApplicationLauncherIcon::Ptr sticky_app(new NiceMock<MockApplicationLauncherIcon>(true, "sticky-app"));
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon());
+ MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1434,7 +1420,7 @@ TEST_F(TestLauncherController, OnFavoriteStoreFavoriteAddedDeviceSection)
TEST_F(TestLauncherController, OnFavoriteStoreFavoriteRemovedApplication)
{
- MockApplicationLauncherIcon::Ptr app_icon(new MockApplicationLauncherIcon(true, "sticky-icon"));
+ MockApplicationLauncherIcon::Ptr app_icon(new NiceMock<MockApplicationLauncherIcon>(true, "sticky-icon"));
lc.Impl()->RegisterIcon(app_icon);
app_icon->Stick(false);
@@ -1500,10 +1486,7 @@ TEST_F(TestLauncherController, OnViewOpened)
auto const& app_icons = lc.Impl()->model_->GetSublist<ApplicationLauncherIcon>();
auto const& last_app = *(app_icons.rbegin());
- auto app = bamf_matcher_get_application_for_desktop_file(lc.Impl()->matcher_, app::BZR_HANDLE_PATCH.c_str(), TRUE);
- g_signal_emit_by_name(lc.Impl()->matcher_, "view-opened", app);
- lc.DisconnectSignals();
-
+ testmocks::MockApplicationManager::StartApp(app::BZR_HANDLE_PATCH);
auto const& icon = lc.GetIconByDesktop(app::BZR_HANDLE_PATCH);
ASSERT_TRUE(icon.IsValid());
@@ -1554,7 +1537,10 @@ TEST_F(TestLauncherController, UpdateSelectionChanged)
ASSERT_EQ(lc.Impl()->model_->Selection()->tooltip_text(), last_selection_change);
}
-TEST_F(TestLauncherController, DragAndDrop_MultipleLaunchers)
+// thumper: 2012-11-28 disabling the drag and drop tests as they are taking over 20s
+// each, and that is not acceptable for unit tests. These sound more like functional
+// tests.
+TEST_F(TestLauncherController, DISABLED_DragAndDrop_MultipleLaunchers)
{
lc.multiple_launchers = true;
uscreen.SetupFakeMultiMonitor();
@@ -1580,7 +1566,7 @@ TEST_F(TestLauncherController, DragAndDrop_MultipleLaunchers)
Utils::WaitUntil(std::bind(check_fn, i), true);
}
-TEST_F(TestLauncherController, DragAndDrop_SingleLauncher)
+TEST_F(TestLauncherController, DISABLED_DragAndDrop_SingleLauncher)
{
lc.multiple_launchers = false;
uscreen.SetupFakeMultiMonitor(2);
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index c0af3dbd5..9e1289d37 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -4,6 +4,8 @@
#include <NuxCore/Logger.h>
#include <Nux/Nux.h>
+#include "logger_helper.h"
+
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
@@ -18,8 +20,7 @@ int main(int argc, char** argv)
// Slightly higher as we're more likely to test things we know will fail
nux::logging::configure_logging("<root>=error");
- // but you can still change it if you're debugging ;)
- nux::logging::configure_logging(::getenv("UNITY_LOG_SEVERITY"));
+ unity::helper::configure_logging("UNITY_TEST_LOG_SEVERITY");
// StandaloneWindowManager brought in at link time.
int ret = RUN_ALL_TESTS();
diff --git a/tests/test_mock_devices.h b/tests/test_mock_devices.h
index 427608bbc..e8497a18c 100644
--- a/tests/test_mock_devices.h
+++ b/tests/test_mock_devices.h
@@ -23,6 +23,8 @@
#ifndef TEST_MOCK_DEVICES_H
#define TEST_MOCK_DEVICES_H
+#include <gmock/gmock.h>
+
#include "DeviceLauncherSection.h"
#include "AbstractVolumeMonitorWrapper.h"
#include "Volume.h"
@@ -63,8 +65,8 @@ struct MockDevicesSettings : DevicesSettings
struct MockDeviceLauncherSection : DeviceLauncherSection
{
MockDeviceLauncherSection(unsigned size = 2)
- : DeviceLauncherSection(MockVolumeMonitorWrapper::Ptr(new MockVolumeMonitorWrapper(size)),
- DevicesSettings::Ptr(new MockDevicesSettings))
+ : DeviceLauncherSection(MockVolumeMonitorWrapper::Ptr(new testing::NiceMock<MockVolumeMonitorWrapper>(size)),
+ DevicesSettings::Ptr(new testing::NiceMock<MockDevicesSettings>))
{}
};
diff --git a/tests/test_previews_application.cpp b/tests/test_previews_application.cpp
index 4ce33ed7d..7b11af568 100644
--- a/tests/test_previews_application.cpp
+++ b/tests/test_previews_application.cpp
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ * Authored by: Nick Dedekind <nick.dedekinc@canonical.com>
*/
#include <list>
diff --git a/tests/test_previews_generic.cpp b/tests/test_previews_generic.cpp
index 19f34f071..fb8b79f33 100644
--- a/tests/test_previews_generic.cpp
+++ b/tests/test_previews_generic.cpp
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ * Authored by: Nick Dedekind <nick.dedekinc@canonical.com>
*/
#include <list>
diff --git a/tests/test_previews_movie.cpp b/tests/test_previews_movie.cpp
index aead90d58..0ece56249 100644
--- a/tests/test_previews_movie.cpp
+++ b/tests/test_previews_movie.cpp
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ * Authored by: Nick Dedekind <nick.dedekinc@canonical.com>
*/
#include <list>
diff --git a/tests/test_previews_music.cpp b/tests/test_previews_music.cpp
index a8437feef..afa6ed13a 100644
--- a/tests/test_previews_music.cpp
+++ b/tests/test_previews_music.cpp
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ * Authored by: Nick Dedekind <nick.dedekinc@canonical.com>
*/
#include <list>
diff --git a/tests/test_previews_social.cpp b/tests/test_previews_social.cpp
index 998e453d6..30bd33bff 100644
--- a/tests/test_previews_social.cpp
+++ b/tests/test_previews_social.cpp
@@ -14,8 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
- * Ken VanDine <ken.vandine@canonical.com>
+ * Authored by: Ken VanDine <ken.vandine@canonical.com>
*/
#include <list>
diff --git a/tests/test_static_cairo_text.cpp b/tests/test_static_cairo_text.cpp
new file mode 100644
index 000000000..2553349ac
--- /dev/null
+++ b/tests/test_static_cairo_text.cpp
@@ -0,0 +1,73 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
+ */
+
+#include <list>
+#include <gmock/gmock.h>
+using namespace testing;
+
+#include <Nux/Nux.h>
+#include <unity-shared/StaticCairoText.h>
+#include "test_utils.h"
+
+using namespace unity;
+
+namespace
+{
+
+class MockStaticCairoText : public nux::StaticCairoText
+{
+public:
+ MockStaticCairoText():StaticCairoText("") {}
+
+ using StaticCairoText::GetTextureStartIndices;
+ using StaticCairoText::GetTextureEndIndices;
+};
+
+TEST(TestStaticCairoText, TextTextureSize)
+{
+ // Test multi-texture stitching support.
+
+ nux::ObjectPtr<MockStaticCairoText> text(new MockStaticCairoText());
+ text->SetLines(-2000);
+ text->SetMaximumWidth(100);
+
+ std::stringstream ss;
+ std::vector<unsigned> starts;
+ std::vector<unsigned> ends;
+ while(starts.size() < 3)
+ {
+ for (int i = 0; i < 100; i++)
+ ss << "Test string\n";
+ text->SetText(ss.str());
+
+ starts = text->GetTextureStartIndices();
+ ends = text->GetTextureEndIndices();
+ ASSERT_TRUE(starts.size() == ends.size());
+
+ for (unsigned int start_index = 0; start_index < starts.size(); start_index++)
+ {
+ if (start_index > 0)
+ {
+ ASSERT_EQ(starts[start_index], ends[start_index-1]+1);
+ }
+ }
+ }
+}
+
+}
diff --git a/tests/test_time_util.cpp b/tests/test_time_util.cpp
new file mode 100644
index 000000000..50aa82864
--- /dev/null
+++ b/tests/test_time_util.cpp
@@ -0,0 +1,36 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+* Copyright (C) 2012 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 warranty of
+* MERCHANTABILITY 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
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
+*
+*/
+
+#include <cinttypes>
+#include <gtest/gtest.h>
+#include <unity-shared/TimeUtil.h>
+
+using namespace testing;
+
+TEST(TestTimeUtil, Testin32BufferOverflow)
+{
+ struct timespec start, end;
+ unity::TimeUtil::SetTimeStruct(&start, &end);
+
+ end.tv_sec = start.tv_sec + INT32_MAX;
+
+ EXPECT_GT(unity::TimeUtil::TimeDelta(&end, &start), 0);
+}
+
diff --git a/unity-shared/ApplicationManager.cpp b/unity-shared/ApplicationManager.cpp
new file mode 100644
index 000000000..b510901f0
--- /dev/null
+++ b/unity-shared/ApplicationManager.cpp
@@ -0,0 +1,47 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "unity-shared/ApplicationManager.h"
+
+#include "unity-shared/WindowManager.h"
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager();
+
+ApplicationManager& ApplicationManager::Default()
+{
+ static std::shared_ptr<ApplicationManager> instance(create_application_manager());
+ return *instance;
+}
+
+
+// This method is needed to create an unresolved external for the
+// WindowManager::Default method. This is because it is highly likely that
+// the application manager implementations need the window manager for some
+// things, and in fact the bamf one does. In order to make the linker happy,
+// we need to make sure that we have this here.
+void dummy()
+{
+ WindowManager::Default();
+}
+
+} // namespace unity
diff --git a/unity-shared/ApplicationManager.h b/unity-shared/ApplicationManager.h
new file mode 100644
index 000000000..7ff8b0ba1
--- /dev/null
+++ b/unity-shared/ApplicationManager.h
@@ -0,0 +1,142 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#ifndef UNITYSHARED_APPLICATION_MANAGER_H
+#define UNITYSHARED_APPLICATION_MANAGER_H
+
+#include <memory>
+#include <vector>
+
+#include <sigc++/signal.h>
+#include <NuxCore/Property.h>
+#include <unity-shared/WindowManager.h>
+
+
+namespace unity
+{
+
+class Application;
+class ApplicationManager;
+class ApplicationWindow;
+typedef std::shared_ptr<Application> ApplicationPtr;
+typedef std::shared_ptr<ApplicationWindow> ApplicationWindowPtr;
+
+typedef std::vector<ApplicationPtr> ApplicationList;
+typedef std::vector<ApplicationWindowPtr> WindowList;
+
+
+class ApplicationWindow
+{
+public:
+ virtual ~ApplicationWindow() {}
+
+ virtual std::string title() const = 0;
+ virtual std::string icon() const = 0;
+ virtual std::string type() const = 0; // 'window' or 'tab'
+
+ virtual Window window_id() const = 0;
+ virtual int monitor() const = 0;
+
+ // It is possible for this to be null, especially in situations where
+ // the application is starting up or shutting down.
+ virtual ApplicationPtr application() const = 0;
+ // Returns true if we made a best effort at focusing the window, or
+ // false if this was not possible for some reason (like a missing window_id).
+ virtual bool Focus() const = 0;
+ // Closes the window, or the browser tab if a webapp.
+ virtual void Quit() const = 0;
+
+ nux::ROProperty<bool> visible;
+ nux::ROProperty<bool> active;
+ nux::ROProperty<bool> urgent;
+};
+
+// Used for dbus menus, and nicer than a std::pair of strings.
+struct ApplicationMenu
+{
+ ApplicationMenu(std::string const& path, std::string const& address)
+ : path(path), remote_address(address) {}
+ std::string path;
+ std::string remote_address;
+};
+
+
+class Application
+{
+public:
+ virtual ~Application() {}
+
+ virtual std::string icon() const = 0;
+ virtual std::string title() const = 0;
+ virtual std::string desktop_file() const = 0;
+ virtual std::string type() const = 0;
+
+ // A string representation of the object.
+ virtual std::string repr() const = 0;
+
+ virtual WindowList GetWindows() const = 0;
+ virtual bool OwnsWindow(Window window_id) const = 0;
+
+ virtual std::vector<std::string> GetSupportedMimeTypes() const = 0;
+ virtual std::vector<ApplicationMenu> GetRemoteMenus() const = 0;
+
+ virtual ApplicationWindowPtr GetFocusableWindow() const = 0;
+ virtual void Focus(bool show_on_visible, int monitor) const = 0;
+ // Calls quit on all the Windows for this application.
+ virtual void Quit() const = 0;
+
+ // Considering using a property for the "unity-seen" quark
+ nux::RWProperty<bool> seen;
+ nux::RWProperty<bool> sticky;
+
+ nux::ROProperty<bool> visible;
+ nux::ROProperty<bool> active;
+ nux::ROProperty<bool> running;
+ nux::ROProperty<bool> urgent;
+
+ sigc::signal<void> closed;
+
+ sigc::signal<void, ApplicationWindow const&> window_opened;
+ sigc::signal<void, ApplicationWindow const&> window_moved;
+ sigc::signal<void> window_closed;
+};
+
+
+class ApplicationManager
+{
+public:
+ virtual ~ApplicationManager() {}
+
+ static ApplicationManager& Default();
+
+ virtual ApplicationWindowPtr GetActiveWindow() = 0;
+
+ virtual ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) = 0;
+
+ virtual ApplicationList GetRunningApplications() = 0;
+
+ sigc::signal<void, ApplicationPtr const&> application_started;
+
+ sigc::signal<void, ApplicationPtr const&> active_application_changed;
+ sigc::signal<void, ApplicationWindowPtr const&> active_window_changed;
+};
+
+}
+
+#endif // UNITYSHARED_APPLICATION_MANAGER_H
diff --git a/unity-shared/BamfApplicationManager.cpp b/unity-shared/BamfApplicationManager.cpp
new file mode 100644
index 000000000..5fcccd8da
--- /dev/null
+++ b/unity-shared/BamfApplicationManager.cpp
@@ -0,0 +1,662 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "unity-shared/BamfApplicationManager.h"
+#include "unity-shared/WindowManager.h"
+
+#include <NuxCore/Logger.h>
+
+
+DECLARE_LOGGER(logger, "unity.appmanager.bamf");
+
+namespace unity
+{
+namespace bamf
+{
+namespace
+{
+const char* UNSEEN_QUARK = "unity-unseen";
+}
+
+
+// Due to the way glib handles object inheritance, we need to cast between pointer types.
+// In order to make the up-call for the base class easy, we pass through a void* for the view.
+View::View(Manager const& manager, glib::Object<BamfView> const& view)
+ : manager_(manager)
+ , bamf_view_(view)
+{
+}
+
+std::string View::title() const
+{
+ return glib::String(bamf_view_get_name(bamf_view_)).Str();
+}
+
+std::string View::icon() const
+{
+ return glib::String(bamf_view_get_icon(bamf_view_)).Str();
+}
+
+std::string View::type() const
+{
+ const gchar* t = bamf_view_get_view_type(bamf_view_);
+ return (t ? t : "");
+}
+
+bool View::GetVisible() const
+{
+ return bamf_view_is_user_visible(bamf_view_);
+}
+
+bool View::GetActive() const
+{
+ return bamf_view_is_active(bamf_view_);
+
+}
+
+bool View::GetRunning() const
+{
+ return bamf_view_is_running(bamf_view_);
+}
+
+bool View::GetUrgent() const
+{
+ return bamf_view_is_urgent(bamf_view_);
+}
+
+
+WindowBase::WindowBase(Manager const& manager,
+ glib::Object<BamfView> const& window)
+ : View(manager, window)
+{
+ visible.SetGetterFunction(sigc::mem_fun(this, &View::GetVisible));
+ active.SetGetterFunction(sigc::mem_fun(this, &View::GetActive));
+ urgent.SetGetterFunction(sigc::mem_fun(this, &View::GetUrgent));
+
+ glib::SignalBase* sig;
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "user-visible-changed",
+ [this] (BamfView*, gboolean visible) {
+ this->visible.changed.emit(visible);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "active-changed",
+ [this] (BamfView*, gboolean active) {
+ this->active.changed.emit(active);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "urgent-changed",
+ [this] (BamfView*, gboolean urgent) {
+ this->urgent.changed.emit(urgent);
+ });
+ signals_.Add(sig);
+}
+
+std::string WindowBase::title() const
+{
+ return View::title();
+}
+
+std::string WindowBase::icon() const
+{
+ return View::icon();
+}
+
+std::string WindowBase::type() const
+{
+ return View::type();
+}
+
+bool WindowBase::Focus() const
+{
+ Window xid = window_id();
+ if (xid)
+ {
+ std::vector<Window> windows = { xid };
+ // TODO: we should simplify the use case of focusing one window.
+ // Somewhat outside the scope of these changes however.
+ WindowManager::Default().FocusWindowGroup(
+ windows,
+ WindowManager::FocusVisibility::ForceUnminimizeInvisible,
+ monitor(),true);
+ return true;
+ }
+ return false;
+}
+
+
+AppWindow::AppWindow(Manager const& manager, glib::Object<BamfView> const& window)
+ : WindowBase(manager, window)
+ , bamf_window_(glib::object_cast<BamfWindow>(window))
+{
+}
+
+
+Window AppWindow::window_id() const
+{
+ return bamf_window_get_xid(bamf_window_);
+}
+
+int AppWindow::monitor() const
+{
+ return bamf_window_get_monitor(bamf_window_);
+}
+
+ApplicationPtr AppWindow::application() const
+{
+ // Moderately evil, but better than changing the method to non-const.
+ // We know that the manager will always be able to be non-const.
+ Manager& m = const_cast<Manager&>(manager_);
+ return m.GetApplicationForWindow(bamf_window_);
+}
+
+void AppWindow::Quit() const
+{
+ WindowManager::Default().Close(window_id());
+}
+
+Tab::Tab(Manager const& manager, glib::Object<BamfView> const& tab)
+ : WindowBase(manager, tab)
+ , bamf_tab_(glib::object_cast<BamfTab>(tab))
+{}
+
+Window Tab::window_id() const
+{
+ return bamf_tab_get_xid(bamf_tab_);
+}
+
+int Tab::monitor() const
+{
+ // TODO, we could find the real window for the window_id, and get the monitor for that.
+ return -1;
+}
+
+ApplicationPtr Tab::application() const
+{
+ // TODO, we could find the real window for the window_id, and return the application for that.
+ return ApplicationPtr();
+}
+
+bool Tab::Focus() const
+{
+ // Raise the tab in the browser.
+ bamf_tab_raise(bamf_tab_);
+ // Then raise the browser window.
+ return WindowBase::Focus();
+}
+
+void Tab::Quit() const
+{
+ bamf_tab_close(bamf_tab_);
+}
+
+// Being brutal with this function.
+ApplicationWindowPtr create_window(Manager const& manager, glib::Object<BamfView> const& view)
+{
+ ApplicationWindowPtr result;
+ if (view.IsType(BAMF_TYPE_TAB))
+ {
+ result.reset(new Tab(manager, view));
+ }
+ else if (view.IsType(BAMF_TYPE_WINDOW))
+ {
+ result.reset(new AppWindow(manager, view));
+ }
+ // We don't handle applications nor indicators here.
+ return result;
+}
+
+Application::Application(Manager const& manager, glib::Object<BamfView> const& app)
+ : View(manager, app)
+ , bamf_app_(glib::object_cast<BamfApplication>(app))
+{
+ HookUpEvents();
+}
+
+Application::Application(Manager const& manager, glib::Object<BamfApplication> const& app)
+ : View(manager, glib::object_cast<BamfView>(app))
+ , bamf_app_(app)
+{
+ HookUpEvents();
+}
+
+void Application::HookUpEvents()
+{
+ // Hook up the property set/get functions
+ seen.SetGetterFunction(sigc::mem_fun(this, &Application::GetSeen));
+ seen.SetSetterFunction(sigc::mem_fun(this, &Application::SetSeen));
+ sticky.SetGetterFunction(sigc::mem_fun(this, &Application::GetSticky));
+ sticky.SetSetterFunction(sigc::mem_fun(this, &Application::SetSticky));
+ visible.SetGetterFunction(sigc::mem_fun(this, &View::GetVisible));
+ active.SetGetterFunction(sigc::mem_fun(this, &View::GetActive));
+ running.SetGetterFunction(sigc::mem_fun(this, &View::GetRunning));
+ urgent.SetGetterFunction(sigc::mem_fun(this, &View::GetUrgent));
+
+ glib::SignalBase* sig;
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "user-visible-changed",
+ [this] (BamfView*, gboolean visible) {
+ LOG_TRACE(logger) << "user-visible-changed " << visible;
+ this->visible.changed.emit(visible);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "active-changed",
+ [this] (BamfView*, gboolean active) {
+ LOG_TRACE(logger) << "active-changed " << visible;
+ this->active.changed.emit(active);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "running-changed",
+ [this] (BamfView*, gboolean running) {
+ LOG_TRACE(logger) << "running " << visible;
+ this->running.changed.emit(running);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "urgent-changed",
+ [this] (BamfView*, gboolean urgent) {
+ this->urgent.changed.emit(urgent);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*>(bamf_view_, "closed",
+ [this] (BamfView*) {
+ this->closed.emit();
+ });
+ signals_.Add(sig);
+
+
+ sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view_, "child-added",
+ [this] (BamfView*, BamfView* child) {
+ // Ownership is not passed on signals
+ glib::Object<BamfView> view(child, glib::AddRef());
+ ApplicationWindowPtr win = create_window(this->manager_, view);
+ if (win)
+ this->window_opened.emit(*win);
+ });
+ signals_.Add(sig);
+
+ sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view_, "child-removed",
+ [this] (BamfView*, BamfView* child) {
+ this->window_closed.emit();
+ });
+ signals_.Add(sig);
+
+ sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view_, "child-moved",
+ [this] (BamfView*, BamfView* child) {
+ // Ownership is not passed on signals
+ glib::Object<BamfView> view(child, glib::AddRef());
+ ApplicationWindowPtr win = create_window(this->manager_, view);
+ if (win)
+ this->window_moved.emit(*win);
+ });
+ signals_.Add(sig);
+}
+
+std::string Application::title() const
+{
+ return View::title();
+}
+
+std::string Application::icon() const
+{
+ return View::icon();
+}
+
+std::string Application::desktop_file() const
+{
+ const gchar* file = bamf_application_get_desktop_file(bamf_app_);
+ return file ? file : "";
+}
+
+std::string Application::type() const
+{
+ // Can't determine the type of a non-running app.
+ std::string result = "unknown";
+ if (running())
+ {
+ const gchar* type = bamf_application_get_application_type(bamf_app_);
+ if (type) result = type;
+ }
+ return result;
+}
+
+std::string Application::repr() const
+{
+ std::ostringstream sout;
+ sout << "<bamf::Application " << bamf_app_.RawPtr() << " >";
+ return sout.str();
+}
+
+WindowList Application::GetWindows() const
+{
+ WindowList result;
+
+ if (!bamf_app_)
+ return result;
+
+ WindowManager& wm = WindowManager::Default();
+ std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free);
+ for (GList* l = children.get(); l; l = l->next)
+ {
+ glib::Object<BamfView> view(BAMF_VIEW(l->data), glib::AddRef());
+ ApplicationWindowPtr window(create_window(manager_, view));
+ if (!window)
+ continue;
+
+ Window window_id = window->window_id();
+
+ if (wm.IsWindowMapped(window_id))
+ {
+ result.push_back(window);
+ }
+ }
+ return result;
+}
+
+bool Application::OwnsWindow(Window window_id) const
+{
+ if (!window_id)
+ return false;
+
+ bool owns = false;
+ std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free);
+ for (GList* l = children.get(); l && !owns; l = l->next)
+ {
+ owns = BAMF_IS_WINDOW(l->data) &&
+ bamf_window_get_xid(static_cast<BamfWindow*>(l->data)) == window_id;
+ }
+
+ return owns;
+}
+
+std::vector<std::string> Application::GetSupportedMimeTypes() const
+{
+ std::vector<std::string> result;
+ std::unique_ptr<gchar*[], void(*)(gchar**)> mimes(
+ bamf_application_get_supported_mime_types(bamf_app_), g_strfreev);
+
+ if (mimes)
+ {
+ for (int i = 0; mimes[i]; i++)
+ {
+ result.push_back(mimes[i]);
+ }
+ }
+ return result;
+}
+
+std::vector<ApplicationMenu> Application::GetRemoteMenus() const
+{
+ std::vector<ApplicationMenu> result;
+ std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free);
+ for (GList* l = children.get(); l; l = l->next)
+ {
+ if (!BAMF_IS_INDICATOR(l->data))
+ continue;
+
+ auto indicator = static_cast<BamfIndicator*>(l->data);
+ const gchar* path = bamf_indicator_get_dbus_menu_path(indicator);
+ const gchar* address = bamf_indicator_get_remote_address(indicator);
+
+ // It is possible for path or address to be null on error condintions, or if
+ // the remote is not ready.
+ if (path && address)
+ result.push_back(ApplicationMenu(path, address));
+ }
+ return result;
+}
+
+ApplicationWindowPtr Application::GetFocusableWindow() const
+{
+ glib::Object<BamfView> view(bamf_application_get_focusable_child(bamf_app_),
+ glib::AddRef());
+ return create_window(manager_, view);
+}
+
+void Application::Focus(bool show_only_visible, int monitor) const
+{
+ WindowManager& wm = WindowManager::Default();
+ std::vector<Window> urgent_windows;
+ std::vector<Window> visible_windows;
+ std::vector<Window> non_visible_windows;
+ bool any_visible = false;
+
+ for (auto& window : GetWindows())
+ {
+ Window window_id = window->window_id();
+ if (window->urgent())
+ urgent_windows.push_back(window_id);
+ else if (window->visible())
+ visible_windows.push_back(window_id);
+ else
+ non_visible_windows.push_back(window_id);
+
+ if (wm.IsWindowOnCurrentDesktop(window_id) &&
+ wm.IsWindowVisible(window_id))
+ {
+ any_visible = true;
+ }
+ }
+
+ // This logic seems overly convoluted, but copying the behaviour from
+ // the launcher icon for now.
+ auto visibility = WindowManager::FocusVisibility::OnlyVisible;
+ if (!show_only_visible)
+ {
+ visibility = any_visible
+ ? WindowManager::FocusVisibility::ForceUnminimizeInvisible
+ : WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop;
+ }
+ if (!urgent_windows.empty())
+ {
+ // Last param is whether to show only the top most window. In the situation
+ // where we have urgent windows, we want to raise all the urgent windows on
+ // the current workspace, or the workspace of the top most urgent window.
+ wm.FocusWindowGroup(urgent_windows, visibility, monitor, false);
+ }
+ else if (!visible_windows.empty())
+ {
+ wm.FocusWindowGroup(visible_windows, visibility, monitor, true);
+ }
+ else
+ {
+ // Not sure what the use case is for this behaviour, but at this stage,
+ // copying behaviour from ApplicationLauncherIcon.
+ wm.FocusWindowGroup(non_visible_windows, visibility, monitor, true);
+ }
+}
+
+void Application::Quit() const
+{
+ for (auto& window : GetWindows())
+ {
+ window->Quit();
+ }
+}
+
+bool Application::GetSeen() const
+{
+ return g_object_get_qdata(G_OBJECT(bamf_app_.RawPtr()),
+ g_quark_from_string(UNSEEN_QUARK));
+}
+
+bool Application::SetSeen(bool const& param)
+{
+ bool is_seen = GetSeen();
+ if (param == is_seen)
+ return false; // unchanged
+
+ void* data = param ? reinterpret_cast<void*>(1) : nullptr;
+ g_object_set_qdata(G_OBJECT(bamf_app_.RawPtr()),
+ g_quark_from_string(UNSEEN_QUARK),
+ data);
+ return true; // value updated
+}
+
+bool Application::GetSticky() const
+{
+ return bamf_view_is_sticky(bamf_view_);
+}
+
+bool Application::SetSticky(bool const& param)
+{
+ bool is_sticky = GetSticky();
+ if (param == is_sticky)
+ return false; // unchanged
+
+ bamf_view_set_sticky(bamf_view_, param);
+ return true; // value updated
+}
+
+
+Manager::Manager()
+ : matcher_(bamf_matcher_get_default())
+{
+ LOG_TRACE(logger) << "Create BAMF Application Manager";
+ glib::SignalBase* sig;
+ sig = new glib::Signal<void, BamfMatcher*, BamfView*>
+ (matcher_, "view-opened",
+ sigc::mem_fun(this, &Manager::OnViewOpened));
+ signals_.Add(sig);
+
+ sig = new glib::Signal<void, BamfMatcher*, BamfView*, BamfView*>
+ (matcher_, "active-window-changed",
+ [this](BamfMatcher*, BamfView* /* from */, BamfView* to) {
+ // Ownership is not passed on signals
+ glib::Object<BamfView> view(to, glib::AddRef());
+ ApplicationWindowPtr win = create_window(*this, view);
+ if (win)
+ this->active_window_changed.emit(win);
+ });
+ signals_.Add(sig);
+
+ sig = new glib::Signal<void, BamfMatcher*, BamfApplication*, BamfApplication*>
+ (matcher_, "active-application-changed",
+ [this](BamfMatcher*, BamfApplication* /* from */, BamfApplication* to) {
+ // Ownership is not passed on signals
+ glib::Object<BamfApplication> app(to, glib::AddRef());
+ ApplicationPtr active_app;
+ if (app) active_app.reset(new Application(*this, app));
+ this->active_application_changed.emit(active_app);
+ });
+ signals_.Add(sig);
+}
+
+Manager::~Manager()
+{
+ LOG_TRACE(logger) << "Manager::~Manager";
+}
+
+ApplicationWindowPtr Manager::GetActiveWindow()
+{
+ ApplicationWindowPtr result;
+ // No transfer of ownership for bamf_matcher_get_active_window.
+ BamfWindow* active_win = bamf_matcher_get_active_window(matcher_);
+
+ // If the active window is a dock type, then we want the first visible, non-dock type.
+ if (active_win &&
+ bamf_window_get_window_type(active_win) == BAMF_WINDOW_DOCK)
+ {
+ LOG_DEBUG(logger) << "Is a dock, looking at the window stack.";
+ std::shared_ptr<GList> windows(bamf_matcher_get_window_stack_for_monitor(matcher_, -1), g_list_free);
+ WindowManager& wm = WindowManager::Default();
+ for (GList *l = windows.get(); l; l = l->next)
+ {
+ if (!BAMF_IS_WINDOW(l->data))
+ {
+ LOG_DEBUG(logger) << "Window stack returned something not a window, WTF?";
+ continue;
+ }
+
+ auto win = static_cast<BamfWindow*>(l->data);
+ auto view = static_cast<BamfView*>(l->data);
+ Window xid = bamf_window_get_xid(win);
+
+ if (bamf_view_is_user_visible(view) &&
+ bamf_window_get_window_type(win) != BAMF_WINDOW_DOCK &&
+ wm.IsWindowOnCurrentDesktop(xid) &&
+ wm.IsWindowVisible(xid))
+ {
+ active_win = win;
+ }
+ }
+ }
+
+ auto view = reinterpret_cast<BamfView*>(active_win);
+ if (active_win)
+ result.reset(new AppWindow(*this, glib::Object<BamfView>(view, glib::AddRef())));
+ return result;
+}
+
+ApplicationPtr Manager::GetApplicationForDesktopFile(std::string const& desktop_file)
+{
+ ApplicationPtr result;
+ glib::Object<BamfApplication> app(bamf_matcher_get_application_for_desktop_file(
+ matcher_, desktop_file.c_str(), true), glib::AddRef());
+
+ if (app)
+ result.reset(new Application(*this, app));
+
+ return result;
+}
+
+ApplicationPtr Manager::GetApplicationForWindow(glib::Object<BamfWindow> const& window)
+{
+ ApplicationPtr result;
+ glib::Object<BamfApplication> app(bamf_matcher_get_application_for_window(matcher_, window),
+ glib::AddRef());
+ if (app)
+ result.reset(new Application(*this, app));
+ return result;
+}
+
+ApplicationList Manager::GetRunningApplications()
+{
+ ApplicationList result;
+ std::shared_ptr<GList> apps(bamf_matcher_get_applications(matcher_), g_list_free);
+
+ for (GList *l = apps.get(); l; l = l->next)
+ {
+ if (!BAMF_IS_APPLICATION(l->data))
+ {
+ LOG_INFO(logger) << "Running apps given something not an app.";
+ continue;
+ }
+
+ glib::Object<BamfApplication> bamf_app(static_cast<BamfApplication*>(l->data));
+ ApplicationPtr app(new Application(*this, bamf_app));
+ result.push_back(app);
+ LOG_DEBUG(logger) << "Running app: " << app->title();
+ }
+ return result;
+}
+
+
+void Manager::OnViewOpened(BamfMatcher* matcher, BamfView* view)
+{
+ LOG_TRACE_BLOCK(logger);
+ if (!BAMF_IS_APPLICATION(view))
+ {
+ LOG_DEBUG(logger) << "view is not an app";
+ return;
+ }
+
+ glib::Object<BamfApplication> app(reinterpret_cast<BamfApplication*>(view), glib::AddRef());
+ application_started.emit(ApplicationPtr(new Application(*this, app)));
+}
+
+} // namespace bamf
+} // namespace unity
diff --git a/unity-shared/BamfApplicationManager.h b/unity-shared/BamfApplicationManager.h
new file mode 100644
index 000000000..9823c8e2e
--- /dev/null
+++ b/unity-shared/BamfApplicationManager.h
@@ -0,0 +1,173 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#ifndef UNITYSHARED_BAMF_APPLICATION_MANAGER_H
+#define UNITYSHARED_BAMF_APPLICATION_MANAGER_H
+
+#include <libbamf/libbamf.h>
+#include <UnityCore/GLibWrapper.h>
+#include <UnityCore/GLibSignal.h>
+
+#include "unity-shared/ApplicationManager.h"
+
+
+namespace unity
+{
+namespace bamf
+{
+class Manager;
+class View
+{
+public:
+ View(Manager const& manager,
+ glib::Object<BamfView> const& view);
+
+ std::string title() const;
+ std::string icon() const;
+ std::string type() const;
+
+ bool GetVisible() const;
+ bool GetActive() const;
+ bool GetRunning() const;
+ bool GetUrgent() const;
+
+protected:
+ Manager const& manager_;
+ glib::Object<BamfView> bamf_view_;
+};
+
+
+class WindowBase: public ::unity::ApplicationWindow, public View
+{
+protected:
+ WindowBase(Manager const& manager,
+ glib::Object<BamfView> const& window);
+
+public:
+ virtual std::string title() const;
+ virtual std::string icon() const;
+ virtual std::string type() const; // 'window' or 'tab'
+
+ virtual bool Focus() const;
+
+private:
+ glib::SignalManager signals_;
+};
+
+// NOTE: Can't use Window as a type as there is a #define for Window to some integer value.
+class AppWindow: public WindowBase
+{
+public:
+ AppWindow(Manager const& manager,
+ glib::Object<BamfView> const& window);
+
+ virtual Window window_id() const;
+ virtual int monitor() const;
+ virtual ApplicationPtr application() const;
+ virtual void Quit() const;
+
+private:
+ glib::Object<BamfWindow> bamf_window_;
+};
+
+class Tab: public WindowBase
+{
+public:
+ Tab(Manager const& manager,
+ glib::Object<BamfView> const& tab);
+
+ virtual Window window_id() const;
+ virtual int monitor() const;
+ virtual ApplicationPtr application() const;
+ virtual bool Focus() const;
+ virtual void Quit() const;
+
+private:
+ glib::Object<BamfTab> bamf_tab_;
+};
+
+
+class Application : public ::unity::Application, public View
+{
+public:
+ Application(Manager const& manager,
+ glib::Object<BamfView> const& app);
+ Application(Manager const& manager,
+ glib::Object<BamfApplication> const& app);
+
+ virtual std::string title() const;
+ virtual std::string icon() const;
+ virtual std::string desktop_file() const;
+ virtual std::string type() const;
+
+ virtual WindowList GetWindows() const;
+ virtual bool OwnsWindow(Window window_id) const;
+
+ virtual std::vector<std::string> GetSupportedMimeTypes() const;
+ virtual std::vector<ApplicationMenu> GetRemoteMenus() const;
+
+ virtual ApplicationWindowPtr GetFocusableWindow() const;
+ virtual void Focus(bool show_on_visible, int monitor) const;
+
+ virtual void Quit() const;
+
+ virtual std::string repr() const;
+
+private: // Property getters and setters
+ void HookUpEvents();
+
+ bool GetSeen() const;
+ bool SetSeen(bool const& param);
+
+ bool GetSticky() const;
+ bool SetSticky(bool const& param);
+
+private:
+ glib::Object< ::BamfApplication> bamf_app_;
+ glib::SignalManager signals_;
+ std::string type_;
+};
+
+class Manager : public ::unity::ApplicationManager
+{
+public:
+ Manager();
+ ~Manager();
+
+ virtual ApplicationWindowPtr GetActiveWindow();
+
+ virtual ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file);
+
+ virtual ApplicationList GetRunningApplications();
+
+
+ virtual ApplicationPtr GetApplicationForWindow(glib::Object<BamfWindow> const& window);
+
+private:
+ void OnViewOpened(BamfMatcher* matcher, BamfView* view);
+
+private:
+ glib::Object<BamfMatcher> matcher_;
+ glib::SignalManager signals_;
+};
+
+} // namespace bamf
+} // namespace unity
+
+#endif // UNITYSHARED_APPLICATION_MANAGER_H
diff --git a/unity-shared/BamfApplicationManagerFactory.cpp b/unity-shared/BamfApplicationManagerFactory.cpp
new file mode 100644
index 000000000..fb2c9d9ad
--- /dev/null
+++ b/unity-shared/BamfApplicationManagerFactory.cpp
@@ -0,0 +1,31 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "unity-shared/BamfApplicationManager.h"
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager()
+{
+ return std::shared_ptr<ApplicationManager>(new bamf::Manager());
+}
+
+}
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index dabe26ee9..64ccae47e 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -23,6 +23,7 @@ include_directories (.. ../services ../UnityCore ${UNITY_SRC} ${CMAKE_BINARY_DIR
#
set (UNITY_SHARED_SOURCES
AbstractSeparator.cpp
+ ApplicationManager.cpp
Animator.cpp
BGHash.cpp
CoverArt.cpp
@@ -98,6 +99,15 @@ if (ENABLE_X_SUPPORT)
target_link_libraries (unity-shared-compiz ${LIBS})
add_dependencies (unity-shared-compiz unity-shared)
+
+ # bamf application manager
+ set (UNITY_SHARED_BAMF_SOURCES
+ BamfApplicationManager.cpp
+ BamfApplicationManagerFactory.cpp
+ )
+ add_library (unity-shared-bamf STATIC ${UNITY_SHARED_BAMF_SOURCES})
+ target_link_libraries (unity-shared-bamf ${LIBS})
+ add_dependencies (unity-shared-bamf unity-shared)
endif()
# standalone
@@ -108,4 +118,7 @@ add_library (unity-shared-standalone STATIC ${UNITY_SHARED_STANDALONE_SOURCES})
target_link_libraries (unity-shared-standalone ${LIBS})
add_dependencies (unity-shared-standalone unity-shared)
+add_executable (app-manager StandaloneAppManager.cpp)
+add_dependencies (app-manager unity-shared unity-shared-bamf unity-shared-standalone)
+target_link_libraries (app-manager unity-shared unity-shared-bamf unity-shared-standalone)
diff --git a/unity-shared/PluginAdapter.cpp b/unity-shared/PluginAdapter.cpp
index 5e83ddf45..ed408b7f8 100644
--- a/unity-shared/PluginAdapter.cpp
+++ b/unity-shared/PluginAdapter.cpp
@@ -1084,6 +1084,22 @@ int PluginAdapter::WorkspaceCount() const
return m_Screen->vpSize().width() * m_Screen->vpSize().height();
}
+nux::Point PluginAdapter::GetCurrentViewport() const
+{
+ CompPoint const& vp = m_Screen->vp();
+ return nux::Point(vp.x(), vp.y());
+}
+
+int PluginAdapter::GetViewportHSize() const
+{
+ return m_Screen->vpSize().width();
+}
+
+int PluginAdapter::GetViewportVSize() const
+{
+ return m_Screen->vpSize().height();
+}
+
void PluginAdapter::SetMwmWindowHints(Window xid, MotifWmHints* new_hints) const
{
Display* display = m_Screen->dpy();
diff --git a/unity-shared/PluginAdapter.h b/unity-shared/PluginAdapter.h
index 12d3aaca4..55ead3770 100644
--- a/unity-shared/PluginAdapter.h
+++ b/unity-shared/PluginAdapter.h
@@ -177,6 +177,10 @@ public:
int WorkspaceCount() const;
+ nux::Point GetCurrentViewport() const override;
+ int GetViewportHSize() const override;
+ int GetViewportVSize() const override;
+
void SetCoverageAreaBeforeAutomaximize(float area);
bool SaveInputFocus();
diff --git a/unity-shared/StandaloneAppManager.cpp b/unity-shared/StandaloneAppManager.cpp
new file mode 100644
index 000000000..589b40b4f
--- /dev/null
+++ b/unity-shared/StandaloneAppManager.cpp
@@ -0,0 +1,245 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 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 warranty of
+ * MERCHANTABILITY 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <NuxCore/Logger.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <signal.h>
+
+#include "unity-shared/ApplicationManager.h"
+#include "UnityCore/GLibSource.h"
+
+using namespace std;
+using namespace unity;
+
+DECLARE_LOGGER(logger, "unity.appmanager.test");
+
+GMainLoop *loop;
+
+void dump_app(ApplicationPtr const& app, std::string const& prefix = "")
+{
+ if (app)
+ {
+ cout << prefix << "Application: " << app->title()
+ << ", seen: " << (app->seen() ? "yes" : "no")
+ << ", sticky: " << (app->sticky() ? "yes" : "no")
+ << ", visible: " << (app->visible() ? "yes" : "no")
+ << ", active: " << (app->active() ? "yes" : "no")
+ << ", running: " << (app->running() ? "yes" : "no")
+ << ", urgent: " << (app->urgent() ? "yes" : "no")
+ << ", repr: " << app->repr()
+ << "\n icon: \"" << app->icon() << "\""
+ << "\n desktop file: \"" << app->desktop_file() << "\""
+ << "\n type: \"" << app->type() << "\""
+ << endl;
+
+ for (auto win : app->GetWindows())
+ {
+ std::cout << " Window: " << win->title()
+ << ", window_id: " << win->window_id()
+ << ", monitor: " << win->monitor()
+ << ", type: " << win->type()
+ << endl;
+ }
+ }
+ else
+ {
+ cout << "App ptr is null" << endl;
+ }
+}
+
+void connect_events(ApplicationPtr const& app)
+{
+ if (app->seen())
+ {
+ cout << "Already seen " << app->title() << ", skipping event connection.\n";
+ return;
+ }
+ std::string app_name = app->title();
+ app->visible.changed.connect([app_name](bool const& value) {
+ cout << app_name << " visibility changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->running.changed.connect([app_name](bool const& value) {
+ cout << app_name << " running changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->active.changed.connect([app_name](bool const& value) {
+ cout << app_name << " active changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->urgent.changed.connect([app_name](bool const& value) {
+ cout << app_name << " urgent changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->closed.connect([app_name]() {
+ cout << app_name << " closed." << endl;
+ });
+ app->window_opened.connect([app_name](ApplicationWindow const& window) {
+ cout << "** " << app_name << " window opened: " << window.title() << endl;
+ });
+ app->window_closed.connect([app_name]() {
+ cout << "** " << app_name << " window closed" << endl;
+ });
+ app->window_moved.connect([app_name](ApplicationWindow const& window) {
+ cout << "** " << app_name << " window moved: " << window.title() << endl;
+ });
+ app->seen = true;
+}
+
+
+
+nux::logging::Level glog_level_to_nux(GLogLevelFlags log_level)
+{
+ // For some weird reason, ERROR is more critical than CRITICAL in gnome.
+ if (log_level & G_LOG_LEVEL_ERROR)
+ return nux::logging::Critical;
+ if (log_level & G_LOG_LEVEL_CRITICAL)
+ return nux::logging::Error;
+ if (log_level & G_LOG_LEVEL_WARNING)
+ return nux::logging::Warning;
+ if (log_level & G_LOG_LEVEL_MESSAGE ||
+ log_level & G_LOG_LEVEL_INFO)
+ return nux::logging::Info;
+ // default to debug.
+ return nux::logging::Debug;
+}
+
+void capture_g_log_calls(const gchar* log_domain,
+ GLogLevelFlags log_level,
+ const gchar* message,
+ gpointer user_data)
+{
+ // If the environment variable is set, we capture the backtrace.
+ static bool glog_backtrace = ::getenv("UNITY_LOG_GLOG_BACKTRACE");
+ // If nothing else, all log messages from unity should be identified as such
+ std::string module("unity");
+ if (log_domain)
+ {
+ module += std::string(".") + log_domain;
+ }
+ nux::logging::Logger logger(module);
+ nux::logging::Level level = glog_level_to_nux(log_level);
+ if (level >= logger.GetEffectiveLogLevel())
+ {
+ std::string backtrace;
+ if (glog_backtrace && level >= nux::logging::Warning)
+ {
+ backtrace = "\n" + nux::logging::Backtrace();
+ }
+ nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
+ << message << backtrace;
+ }
+}
+
+void print_active_window(ApplicationManager& manager)
+{
+ ApplicationWindowPtr win = manager.GetActiveWindow();
+ if (win)
+ {
+ ApplicationPtr app = win->application();
+ if (app)
+ cout << "\n\nActive App: " << app->title();
+ else
+ cout << "\n\nNo app for window:";
+ cout << "\nActive Window: " << win->title() << endl;
+ }
+ else
+ cout << "\n\nNo active window: " << endl;
+}
+
+void clean_exit(int sig)
+{
+ if (loop && g_main_loop_is_running(loop))
+ g_main_loop_quit(loop);
+}
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager();
+}
+
+int main(int argc, char* argv[])
+{
+ g_type_init();
+ gtk_init(&argc, &argv);
+ nux::logging::configure_logging(::getenv("UNITY_APP_LOG_SEVERITY"));
+ g_log_set_default_handler(capture_g_log_calls, NULL);
+
+ bool show_active = (argc > 1 && std::string(argv[1]) == "show-active");
+ //std::shared_ptr<ApplicationManager> manager_ptr = create_application_manager();
+ //ApplicationManager& manager = *manager_ptr;
+ ApplicationManager& manager = ApplicationManager::Default();
+
+ ApplicationPtr terminal = manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/gnome-terminal.desktop");
+ terminal->sticky = true; // this is needed to get the notifications...
+ dump_app(terminal);
+ connect_events(terminal);
+
+ ApplicationList apps = manager.GetRunningApplications();
+
+ for (auto app : apps)
+ {
+ dump_app(app);
+ connect_events(app);
+ }
+
+ dump_app(manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/gnome-terminal.desktop"));
+
+ // Get some desktop files for checking
+ ApplicationPtr pgadmin = manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/pgadmin3.desktop");
+ dump_app(pgadmin);
+ ApplicationPtr gedit = manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/gedit.desktop");
+ dump_app(gedit);
+ // dump new apps
+ manager.application_started.connect([&apps](ApplicationPtr const& app) {
+ apps.push_back(app);
+ dump_app(app, "\nApp started: ");
+ connect_events(app);
+ });
+ manager.active_application_changed.connect([](ApplicationPtr const& app) {
+ if (app)
+ cout << "Manager::active_application_changed: " << app->title() << endl;
+ else
+ cout << "Manager::active_application_changed to nothing\n";
+ });
+ manager.active_window_changed.connect([](ApplicationWindowPtr const& win) {
+ cout << "Manager::active_window_changed: " << win->title() << endl;
+ });
+
+ shared_ptr<GMainLoop> main_loop(g_main_loop_new(nullptr, FALSE),
+ g_main_loop_unref);
+ loop = main_loop.get();
+ signal(SIGINT, clean_exit);
+ {
+ glib::SourceManager source_manager;
+ if (show_active)
+ source_manager.AddTimeoutSeconds(5, [&manager]() {
+ print_active_window(manager);
+ return true;
+ });
+ g_main_loop_run(loop);
+ }
+ cout << "After main loop.\n";
+}
diff --git a/unity-shared/StandaloneWindowManager.cpp b/unity-shared/StandaloneWindowManager.cpp
index 91b96a421..1dad77534 100644
--- a/unity-shared/StandaloneWindowManager.cpp
+++ b/unity-shared/StandaloneWindowManager.cpp
@@ -98,7 +98,7 @@ bool StandaloneWindowManager::IsWindowOnCurrentDesktop(Window window_id) const
if (it != standalone_windows_.end())
return (it->second->current_desktop == current_desktop_);
- return false;
+ return true;
}
bool StandaloneWindowManager::IsWindowObscured(Window window_id) const
@@ -112,7 +112,7 @@ bool StandaloneWindowManager::IsWindowMapped(Window window_id) const
if (it != standalone_windows_.end())
return it->second->mapped;
- return false;
+ return true;
}
bool StandaloneWindowManager::IsWindowVisible(Window window_id) const
@@ -121,7 +121,7 @@ bool StandaloneWindowManager::IsWindowVisible(Window window_id) const
if (it != standalone_windows_.end())
return it->second->visible;
- return false;
+ return true;
}
bool StandaloneWindowManager::IsWindowOnTop(Window window_id) const
@@ -438,6 +438,21 @@ int StandaloneWindowManager::WorkspaceCount() const
return 4;
}
+nux::Point StandaloneWindowManager::GetCurrentViewport() const
+{
+ return current_vp_;
+}
+
+ int StandaloneWindowManager::GetViewportHSize() const
+{
+ return 2;
+}
+
+int StandaloneWindowManager::GetViewportVSize() const
+{
+ return 2;
+}
+
bool StandaloneWindowManager::SaveInputFocus()
{
return false;
@@ -480,6 +495,10 @@ std::map<Window, StandaloneWindow::Ptr> StandaloneWindowManager::GetStandaloneWi
return standalone_windows_;
}
+void StandaloneWindowManager::SetCurrentViewport(nux::Point const& vp)
+{
+ current_vp_ = vp;
+}
void StandaloneWindowManager::AddProperties(GVariantBuilder* builder)
{
diff --git a/unity-shared/StandaloneWindowManager.h b/unity-shared/StandaloneWindowManager.h
index 674f9c336..15b737bcd 100644
--- a/unity-shared/StandaloneWindowManager.h
+++ b/unity-shared/StandaloneWindowManager.h
@@ -129,6 +129,10 @@ public:
virtual int WorkspaceCount() const;
+ nux::Point GetCurrentViewport() const override;
+ int GetViewportHSize() const override;
+ int GetViewportVSize() const override;
+
virtual bool SaveInputFocus();
virtual bool RestoreInputFocus();
@@ -142,6 +146,8 @@ public:
void AddStandaloneWindow(StandaloneWindow::Ptr const& window);
std::map<Window, StandaloneWindow::Ptr> GetStandaloneWindows() const;
+ void SetCurrentViewport(nux::Point const& vp);
+
protected:
virtual void AddProperties(GVariantBuilder* builder);
@@ -152,6 +158,7 @@ private:
bool scale_active_for_group_;
unsigned current_desktop_;
std::map<Window, StandaloneWindow::Ptr> standalone_windows_;
+ nux::Point current_vp_;
};
}
diff --git a/unity-shared/StaticCairoText.cpp b/unity-shared/StaticCairoText.cpp
index f3ed86a1e..85cda4d83 100644
--- a/unity-shared/StaticCairoText.cpp
+++ b/unity-shared/StaticCairoText.cpp
@@ -17,6 +17,7 @@
* Authored by: Jay Taoko <jay.taoko@canonical.com>
* Mirco Müller <mirco.mueller@canonical.com>
* Tim Penhey <tim.penhey@canonical.com>
+ * Nick Dedekind <nick.dedekind@canonical.com>
*/
#include "StaticCairoText.h"
@@ -52,9 +53,26 @@ struct StaticCairoText::Impl
PangoAlignment GetPangoAlignment() const;
std::string GetEffectiveFont() const;
+
+ struct CacheTexture
+ {
+ typedef std::shared_ptr<CacheTexture> Ptr;
+ CacheTexture()
+ : start_index(0)
+ , length((unsigned)std::string::npos)
+ , height(0)
+ {}
+
+ unsigned start_index;
+ unsigned length;
+ unsigned height;
+
+ std::shared_ptr<CairoGraphics> cr;
+ };
Size GetTextExtents() const;
- void DrawText(cairo_t* cr, int width, int height, int line_spacing, Color const& color);
+ void SetAttributes(PangoLayout* layout);
+ void DrawText(CacheTexture::Ptr cached_texture, int width, int height, int line_spacing, Color const& color);
void UpdateTexture();
void OnFontChanged();
@@ -68,6 +86,7 @@ struct StaticCairoText::Impl
mutable Size cached_extent_;
mutable Size cached_base_;
mutable int baseline_;
+ mutable std::list<CacheTexture::Ptr> cache_textures_;
std::string text_;
Color text_color_;
@@ -75,10 +94,11 @@ struct StaticCairoText::Impl
EllipsizeState ellipsize_;
AlignState align_;
AlignState valign_;
+ UnderlineState underline_;
std::string font_;
- BaseTexturePtr texture2D_;
+ std::list<BaseTexturePtr> textures2D_;
Size pre_layout_size_;
@@ -97,6 +117,7 @@ StaticCairoText::Impl::Impl(StaticCairoText* parent, std::string const& text)
, ellipsize_(NUX_ELLIPSIZE_END)
, align_(NUX_ALIGN_LEFT)
, valign_(NUX_ALIGN_TOP)
+ , underline_(NUX_UNDERLINE_NONE)
, lines_(-2) // should find out why -2...
// the desired height of the layout in Pango units if positive, or desired
// number of lines if negative.
@@ -214,7 +235,7 @@ void StaticCairoText::PreLayoutManagement()
SetBaseSize(pimpl->cached_extent_.width,
pimpl->cached_extent_.height);
- if (pimpl->texture2D_.IsNull())
+ if (pimpl->textures2D_.empty())
{
pimpl->UpdateTexture();
}
@@ -251,7 +272,7 @@ void StaticCairoText::Draw(GraphicsEngine& gfxContext, bool forceDraw)
{
Geometry const& base = GetGeometry();
- if (pimpl->texture2D_.IsNull() ||
+ if (pimpl->textures2D_.empty() ||
pimpl->cached_base_.width != base.width ||
pimpl->cached_base_.height != base.height)
{
@@ -281,13 +302,24 @@ void StaticCairoText::Draw(GraphicsEngine& gfxContext, bool forceDraw)
base.height,
col);
- gfxContext.QRP_1Tex(base.x,
- base.y + ((base.height - pimpl->cached_extent_.height) / 2),
- base.width,
- base.height,
- pimpl->texture2D_->GetDeviceTexture(),
- texxform,
- pimpl->text_color_);
+ int current_y = base.y + ((base.height - pimpl->cached_extent_.height) / 2);
+
+ for (BaseTexturePtr tex : pimpl->textures2D_)
+ {
+ nux::ObjectPtr<nux::IOpenGLBaseTexture> text_tex = tex->GetDeviceTexture();
+ if (!text_tex)
+ break;
+
+ gfxContext.QRP_1Tex(base.x,
+ current_y,
+ text_tex->GetWidth(),
+ text_tex->GetHeight(),
+ text_tex,
+ texxform,
+ pimpl->text_color_);
+
+ current_y += text_tex->GetHeight();
+ }
gfxContext.GetRenderStates().SetBlend(alpha, src, dest);
@@ -312,6 +344,16 @@ void StaticCairoText::SetText(std::string const& text, bool escape_text)
}
}
+void StaticCairoText::SetTextAlpha(unsigned int alpha)
+{
+ if (pimpl->text_color_.alpha != alpha)
+ {
+ pimpl->text_color_.alpha = alpha;
+ pimpl->UpdateTexture();
+ QueueDraw();
+ }
+}
+
void StaticCairoText::SetMaximumSize(int w, int h)
{
if (w != GetMaximumWidth())
@@ -320,7 +362,7 @@ void StaticCairoText::SetMaximumSize(int w, int h)
View::SetMaximumSize(w, h);
pimpl->UpdateTexture();
return;
- }
+ }
View::SetMaximumSize(w, h);
}
@@ -380,6 +422,18 @@ std::string StaticCairoText::GetFont()
return pimpl->font_;
}
+void StaticCairoText::SetUnderline(UnderlineState underline)
+{
+ if (pimpl->underline_ != underline)
+ {
+ pimpl->underline_ = underline;
+ pimpl->need_new_extent_cache_ = true;
+ Size s = GetTextExtents();
+ SetMinimumHeight(s.height);
+ NeedRedraw();
+ }
+}
+
int StaticCairoText::GetLineCount() const
{
return pimpl->actual_lines_;
@@ -402,6 +456,44 @@ void StaticCairoText::GetTextExtents(int& width, int& height) const
height = s.height;
}
+std::vector<unsigned> StaticCairoText::GetTextureStartIndices()
+{
+ pimpl->GetTextExtents();
+
+ std::vector<unsigned> list;
+ auto iter = pimpl->cache_textures_.begin();
+ for (; iter != pimpl->cache_textures_.end(); ++iter)
+ {
+ Impl::CacheTexture::Ptr const& cached_texture = *iter;
+ list.push_back(cached_texture->start_index);
+ }
+ return list;
+}
+
+std::vector<unsigned> StaticCairoText::GetTextureEndIndices()
+{
+ pimpl->GetTextExtents();
+
+ std::vector<unsigned> list;
+ auto iter = pimpl->cache_textures_.begin();
+ for (; iter != pimpl->cache_textures_.end(); ++iter)
+ {
+ Impl::CacheTexture::Ptr const& cached_texture = *iter;
+ if (cached_texture->length == (unsigned)std::string::npos)
+ {
+ list.push_back((unsigned)std::string::npos);
+ }
+ else
+ {
+ if (cached_texture->start_index > 0 || cached_texture->length > 0)
+ list.push_back((unsigned)(cached_texture->start_index + cached_texture->length - 1));
+ else
+ list.push_back(0);
+ }
+ }
+ return list;
+}
+
std::string StaticCairoText::Impl::GetEffectiveFont() const
{
if (font_.empty())
@@ -481,6 +573,50 @@ Size StaticCairoText::Impl::GetTextExtents() const
baseline_ = pango_layout_get_baseline(layout) / PANGO_SCALE;
need_new_extent_cache_ = false;
+ cache_textures_.clear();
+ PangoLayoutIter* iter = pango_layout_get_iter(layout);
+ CacheTexture::Ptr current_tex(new CacheTexture());
+ const int max_height = GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxTextureSize();
+ if (max_height < 0)
+ return nux::Size(0, 0);
+
+ do
+ {
+ PangoLayoutLine* line = pango_layout_iter_get_line_readonly(iter);
+ int y0 = 0, y1 = 0;
+ pango_layout_iter_get_line_yrange(iter, &y0, &y1);
+ y0 /= PANGO_SCALE;
+ y1 /= PANGO_SCALE;
+
+ if (line->start_index < 0 || y1 < y0)
+ {
+ current_tex.reset();
+ break;
+ }
+ unsigned line_start_index = line->start_index;
+ unsigned height = y1-y0;
+
+ if (current_tex->height + height > (unsigned)max_height)
+ {
+ if (line_start_index > current_tex->start_index)
+ current_tex->length = line_start_index - current_tex->start_index;
+ else
+ current_tex->length = 0;
+ cache_textures_.push_back(current_tex);
+
+ // new texture.
+ current_tex.reset(new CacheTexture());
+ current_tex->start_index = line_start_index;
+ current_tex->height = 0;
+ }
+ current_tex->height += height;
+ }
+ while(pango_layout_iter_next_line(iter));
+
+ if (current_tex) { cache_textures_.push_back(current_tex); }
+
+ pango_layout_iter_free(iter);
+
// clean up
pango_font_description_free(desc);
g_object_unref(layout);
@@ -489,12 +625,48 @@ Size StaticCairoText::Impl::GetTextExtents() const
return result;
}
-void StaticCairoText::Impl::DrawText(cairo_t* cr,
+void StaticCairoText::Impl::SetAttributes(PangoLayout *layout)
+{
+ PangoAttrList* attr_list = NULL;
+ PangoAttribute* underline_attr = NULL;
+
+ attr_list = pango_layout_get_attributes(layout);
+ if(!attr_list)
+ {
+ attr_list = pango_attr_list_new();
+ }
+
+ PangoUnderline underline_type;
+
+ switch(underline_){
+ case(NUX_UNDERLINE_SINGLE):
+ underline_type = PANGO_UNDERLINE_SINGLE;
+ break;
+ case(NUX_UNDERLINE_DOUBLE):
+ underline_type = PANGO_UNDERLINE_DOUBLE;
+ break;
+ case(NUX_UNDERLINE_LOW):
+ underline_type = PANGO_UNDERLINE_LOW;
+ break;
+ default:
+ underline_type = PANGO_UNDERLINE_NONE;
+ }
+ underline_attr = pango_attr_underline_new(underline_type);
+ pango_attr_list_insert(attr_list, underline_attr);
+ pango_layout_set_attributes(layout, attr_list);
+}
+
+void StaticCairoText::Impl::DrawText(CacheTexture::Ptr cached_texture,
int width,
int height,
int line_spacing,
Color const& color)
{
+ if (!cached_texture)
+ return;
+ cached_texture->cr.reset(new CairoGraphics(CAIRO_FORMAT_ARGB32, width, height));
+ cairo_t* cr = cached_texture->cr->GetInternalContext();
+
PangoLayout* layout = NULL;
PangoFontDescription* desc = NULL;
PangoContext* pangoCtx = NULL;
@@ -502,9 +674,11 @@ void StaticCairoText::Impl::DrawText(cairo_t* cr,
GdkScreen* screen = gdk_screen_get_default(); // not ref'ed
GtkSettings* settings = gtk_settings_get_default(); // not ref'ed
- std::string font(GetEffectiveFont());
+ std::string text = text_.substr(cached_texture->start_index, cached_texture->length);
+ std::string font(GetEffectiveFont());
cairo_set_font_options(cr, gdk_screen_get_font_options(screen));
+
layout = pango_cairo_create_layout(cr);
desc = pango_font_description_from_string(font.c_str());
@@ -512,12 +686,15 @@ void StaticCairoText::Impl::DrawText(cairo_t* cr,
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
pango_layout_set_ellipsize(layout, GetPangoEllipsizeMode());
pango_layout_set_alignment(layout, GetPangoAlignment());
- pango_layout_set_markup(layout, text_.c_str(), -1);
+ pango_layout_set_markup(layout, text.c_str(), -1);
pango_layout_set_width(layout, width * PANGO_SCALE);
pango_layout_set_height(layout, height * PANGO_SCALE);
pango_layout_set_spacing(layout, line_spacing * PANGO_SCALE);
pango_layout_set_height(layout, lines_);
+
+ SetAttributes(layout);
+
pangoCtx = pango_layout_get_context(layout); // is not ref'ed
pango_cairo_context_set_font_options(pangoCtx,
gdk_screen_get_font_options(screen));
@@ -555,16 +732,18 @@ void StaticCairoText::Impl::UpdateTexture()
{
Size size = GetTextExtents();
parent_->SetBaseSize(size.width, size.height);
- // Now reget the internal geometry as it is clipped by the max size.
- Geometry const& geo = parent_->GetGeometry();
+ nux::Geometry const& geo = parent_->GetGeometry();
- CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32,
- geo.width, geo.height);
-
- DrawText(cairo_graphics.GetInternalContext(),
- geo.width, geo.height, line_spacing_, text_color_);
+ textures2D_.clear();
+ auto iter = cache_textures_.begin();
+ for (; iter != cache_textures_.end(); ++iter)
+ {
+ CacheTexture::Ptr const& cached_texture = *iter;
+ DrawText(cached_texture,
+ geo.width, cached_texture->height, line_spacing_, text_color_);
- texture2D_ = texture_ptr_from_cairo_graphics(cairo_graphics);
+ textures2D_.push_back(texture_ptr_from_cairo_graphics(*cached_texture->cr));
+ }
}
void StaticCairoText::Impl::FontChanged(GObject* gobject,
diff --git a/unity-shared/StaticCairoText.h b/unity-shared/StaticCairoText.h
index 0d9503a89..91549e7f6 100644
--- a/unity-shared/StaticCairoText.h
+++ b/unity-shared/StaticCairoText.h
@@ -51,6 +51,14 @@ public:
NUX_ALIGN_BOTTOM = NUX_ALIGN_RIGHT
};
+ enum UnderlineState
+ {
+ NUX_UNDERLINE_NONE,
+ NUX_UNDERLINE_SINGLE,
+ NUX_UNDERLINE_DOUBLE,
+ NUX_UNDERLINE_LOW
+ };
+
StaticCairoText(std::string const& text, NUX_FILE_LINE_PROTO);
StaticCairoText(std::string const& text, bool escape_text, NUX_FILE_LINE_PROTO);
~StaticCairoText();
@@ -67,12 +75,14 @@ public:
// public API
void SetText(std::string const& text, bool escape_text = false);
+ void SetTextAlpha(unsigned int alpha);
void SetTextColor(Color const& textColor);
void SetTextEllipsize(EllipsizeState state);
void SetTextAlignment(AlignState state);
void SetTextVerticalAlignment(AlignState state);
void SetFont(std::string const& font);
std::string GetFont();
+ void SetUnderline(UnderlineState underline);
void SetLines(int maximum_lines);
void SetLineSpacing(float line_spacing);
@@ -100,6 +110,9 @@ protected:
// Key navigation
virtual bool AcceptKeyNavFocus();
+ std::vector<unsigned> GetTextureStartIndices();
+ std::vector<unsigned> GetTextureEndIndices();
+
private:
struct Impl;
Impl* pimpl;
diff --git a/unity-shared/TimeUtil.h b/unity-shared/TimeUtil.h
index ab4d109db..4e326e984 100644
--- a/unity-shared/TimeUtil.h
+++ b/unity-shared/TimeUtil.h
@@ -19,29 +19,34 @@
*/
#include <time.h>
+#include <cstdint>
+
+typedef int64_t DeltaTime;
namespace unity {
class TimeUtil
{
public:
- static int TimeDelta (struct timespec const* x, struct timespec const* y)
+ static DeltaTime TimeDelta (struct timespec const* x, struct timespec const* y)
{
- return ((x->tv_sec - y->tv_sec) * 1000) + ((x->tv_nsec - y->tv_nsec) / 1000000);
+ DeltaTime d_sec = ((x->tv_sec - y->tv_sec));
+ DeltaTime d_nsec = ((x->tv_nsec - y->tv_nsec));
+ return (d_sec * 1000) + (d_nsec / 1000000);
}
- static void SetTimeStruct(struct timespec* timer, struct timespec* sister = 0, int sister_relation = 0)
+ static void SetTimeStruct(struct timespec* timer, struct timespec* sister = 0, DeltaTime sister_relation = 0)
{
struct timespec current;
clock_gettime(CLOCK_MONOTONIC, &current);
if (sister)
{
- int diff = TimeDelta(&current, sister);
+ DeltaTime diff = TimeDelta(&current, sister);
if (diff < sister_relation)
{
- int remove = sister_relation - diff;
+ DeltaTime remove = sister_relation - diff;
SetTimeBack(&current, remove);
}
}
@@ -50,7 +55,7 @@ public:
timer->tv_nsec = current.tv_nsec;
}
- static void SetTimeBack(struct timespec* timeref, int remove)
+ static void SetTimeBack(struct timespec* timeref, DeltaTime remove)
{
timeref->tv_sec -= remove / 1000;
remove = remove % 1000;
diff --git a/unity-shared/WindowManager.h b/unity-shared/WindowManager.h
index 28d474805..73c593910 100644
--- a/unity-shared/WindowManager.h
+++ b/unity-shared/WindowManager.h
@@ -141,6 +141,10 @@ public:
virtual int WorkspaceCount() const = 0;
+ virtual nux::Point GetCurrentViewport() const = 0;
+ virtual int GetViewportHSize() const = 0;
+ virtual int GetViewportVSize() const = 0;
+
virtual bool SaveInputFocus() = 0;
virtual bool RestoreInputFocus() = 0;
@@ -173,6 +177,7 @@ public:
sigc::signal<void> screen_ungrabbed;
sigc::signal<void> screen_viewport_switch_started;
sigc::signal<void> screen_viewport_switch_ended;
+ sigc::signal<void, int, int> viewport_layout_changed;
protected:
std::string GetName() const;
diff --git a/unity-standalone/CMakeLists.txt b/unity-standalone/CMakeLists.txt
index 60e5a55d5..6dd4b70dc 100644
--- a/unity-standalone/CMakeLists.txt
+++ b/unity-standalone/CMakeLists.txt
@@ -31,4 +31,5 @@ target_link_libraries (unity-standalone
launcher-lib
panel-lib
unity-shared
+ unity-shared-bamf
unity-shared-standalone)