diff options
| author | Brandon Schaefer <brandon.schaefer@canonical.com> | 2013-03-19 14:32:30 -0700 |
|---|---|---|
| committer | Brandon Schaefer <brandon.schaefer@canonical.com> | 2013-03-19 14:32:30 -0700 |
| commit | 71f2c3351ab18f17d6cadbf3fa24d8c20c02ba4d (patch) | |
| tree | ef090883077d816465243a421177dd53fd163463 | |
| parent | dc24cb119220c5fbd63bc05446b440ea5c0df176 (diff) | |
| parent | 14973632a9b01cae21e5bdf9453729431beef766 (diff) | |
* Merge Trunk, Fix Conflict
(bzr r3215.3.3)
54 files changed, 985 insertions, 699 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1839bde69..70b66c195 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,7 +153,7 @@ find_package (Gettext REQUIRED) set (COMPIZ_I18N_DIR ${CMAKE_SOURCE_DIR}/po) add_custom_command (OUTPUT ${CMAKE_SOURCE_DIR}/po/unity.pot - COMMAND xgettext -c --files-from ${CMAKE_SOURCE_DIR}/po/POTFILES.in --keyword=_ -o ${CMAKE_SOURCE_DIR}/po/unity.pot --copyright-holder="Canonical Ltd" --msgid-bugs-address="ayatana-dev@lists.launchpad.net" --no-wrap --no-location + COMMAND xgettext -c --from-code=UTF-8 --files-from ${CMAKE_SOURCE_DIR}/po/POTFILES.in --keyword=_ -o ${CMAKE_SOURCE_DIR}/po/unity.pot --copyright-holder="Canonical Ltd" --msgid-bugs-address="ayatana-dev@lists.launchpad.net" --no-wrap --no-location WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) diff --git a/dash/ApplicationStarter.h b/dash/ApplicationStarter.h index 817a5466d..d74f302fe 100644 --- a/dash/ApplicationStarter.h +++ b/dash/ApplicationStarter.h @@ -32,6 +32,8 @@ class ApplicationStarter : boost::noncopyable public: typedef std::shared_ptr<ApplicationStarter> Ptr; + virtual ~ApplicationStarter() {} + virtual bool Launch(std::string const& application_name, Time timestamp) = 0; }; diff --git a/dash/ApplicationStarterImp.cpp b/dash/ApplicationStarterImp.cpp index bdc75aab4..021649109 100644 --- a/dash/ApplicationStarterImp.cpp +++ b/dash/ApplicationStarterImp.cpp @@ -37,7 +37,7 @@ bool ApplicationStarterImp::Launch(std::string const& application_name, Time tim GdkDisplay* display = gdk_display_get_default(); glib::Object<GdkAppLaunchContext> app_launch_context(gdk_display_get_app_launch_context(display)); - if (timestamp >= 0) + if (timestamp > 0) gdk_app_launch_context_set_timestamp(app_launch_context, timestamp); while (true) diff --git a/dash/DashView.cpp b/dash/DashView.cpp index 17af8d43e..d0d30ae85 100644 --- a/dash/DashView.cpp +++ b/dash/DashView.cpp @@ -200,7 +200,7 @@ void DashView::OnUriActivated(ResultView::ActivateType type, std::string const& int row_height = 0; int results_to_the_left = 0; int results_to_the_right = 0; - g_variant_get(data, "(iiiiiii)", &last_activated_timestamp_, &column_x, &row_y, &column_width, &row_height, &results_to_the_left, &results_to_the_right); + g_variant_get(data, "(tiiiiii)", &last_activated_timestamp_, &column_x, &row_y, &column_width, &row_height, &results_to_the_left, &results_to_the_right); preview_state_machine_.SetSplitPosition(SplitPosition::CONTENT_AREA, row_y); preview_state_machine_.left_results = results_to_the_left; @@ -703,7 +703,11 @@ void DashView::DrawContent(nux::GraphicsEngine& graphics_engine, bool force_draw renderer_.DrawInner(graphics_engine, content_geo_, renderer_geo_abs, renderer_geo); nux::Geometry const& geo_layout(layout_->GetGeometry()); - graphics_engine.PushClippingRectangle(geo_layout); + + // See lp bug: 1125346 (The sharp white line between dash and launcher is missing) + nux::Geometry clip_geo = geo_layout; + clip_geo.x += 1; + graphics_engine.PushClippingRectangle(clip_geo); if (IsFullRedraw()) { diff --git a/dash/DashView.h b/dash/DashView.h index 37c06bfed..eb929f706 100644 --- a/dash/DashView.h +++ b/dash/DashView.h @@ -162,7 +162,7 @@ private: OverlayRenderer renderer_; std::string last_activated_uri_; - Time last_activated_timestamp_; + guint64 last_activated_timestamp_; bool search_in_progress_; bool activate_on_finish_; diff --git a/dash/ResultViewGrid.cpp b/dash/ResultViewGrid.cpp index 4f52952d5..d81341474 100644 --- a/dash/ResultViewGrid.cpp +++ b/dash/ResultViewGrid.cpp @@ -208,8 +208,8 @@ void ResultViewGrid::Activate(std::string const& uri, int index, ResultView::Act } active_index_ = index; - auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; - glib::Variant data(g_variant_new("(iiiiiii)", timestamp, column_x, row_y, column_width, row_height, left_results, right_results)); + guint64 timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; + glib::Variant data(g_variant_new("(tiiiiii)", timestamp, column_x, row_y, column_width, row_height, left_results, right_results)); UriActivated.emit(uri, type, data); } diff --git a/hud/HudController.cpp b/hud/HudController.cpp index 2c57aea12..71895a679 100644 --- a/hud/HudController.cpp +++ b/hud/HudController.cpp @@ -484,7 +484,7 @@ void Controller::OnSearchChanged(std::string search_string) void Controller::OnSearchActivated(std::string search_string) { - unsigned int timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; + unsigned int timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; hud_service_.ExecuteQueryBySearch(search_string, timestamp); ubus.SendMessage(UBUS_HUD_CLOSE_REQUEST); } @@ -492,7 +492,7 @@ void Controller::OnSearchActivated(std::string search_string) void Controller::OnQueryActivated(Query::Ptr query) { LOG_DEBUG(logger) << "Activating query, " << query->formatted_text; - unsigned int timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; + unsigned int timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; hud_service_.ExecuteQuery(query, timestamp); ubus.SendMessage(UBUS_HUD_CLOSE_REQUEST); } diff --git a/hud/HudView.cpp b/hud/HudView.cpp index ebea81ae4..e32190218 100644 --- a/hud/HudView.cpp +++ b/hud/HudView.cpp @@ -114,6 +114,11 @@ View::View() } }); + mouse_move.connect([this] (int x, int y, int dx, int dy, unsigned long mouse_button, unsigned long special_key) { + for (auto button : buttons_) + button->SetInputEventSensitivity(true); + }); + mouse_down.connect(sigc::mem_fun(this, &View::OnMouseButtonDown)); QueueDraw(); @@ -133,7 +138,6 @@ void View::ProcessGrowShrink() { float diff = g_get_monotonic_time() - start_time_; int target_height = content_layout_->GetGeometry().height; - // only animate if we are after our defined pause time if (diff > pause_before_grow_length) { @@ -151,12 +155,18 @@ void View::ProcessGrowShrink() //shrink new_height = last_height - ((last_height - target_height) * progress); } + LOG_DEBUG(logger) << "resizing to " << target_height << " (" << new_height << ")" << "View height: " << GetGeometry().height; current_height_ = new_height; } + for (auto button : buttons_) + { + button->SetSkipDraw((button->GetAbsoluteY() + button->GetBaseHeight()) > (GetAbsoluteY() + current_height_)); + } + if (diff > grow_anim_length + pause_before_grow_length) { // ensure we are at our final location and update last known height @@ -175,13 +185,8 @@ void View::ProcessGrowShrink() return false; })); } - - // Do this after we check if we are finished, it will skip drawing buttons otherwise - for (auto button : buttons_) - button->SetSkipDraw((button->GetAbsoluteY() + button->GetBaseHeight()) > (GetAbsoluteY() + current_height_)); } - void View::ResetToDefault() { SetQueries(Hud::Queries()); @@ -227,6 +232,7 @@ void View::SetQueries(Hud::Queries queries) HudButton::Ptr button(new HudButton()); buttons_.push_front(button); + button->SetInputEventSensitivity(false); button->SetMinimumWidth(content_width); button->SetMaximumWidth(content_width); button->SetQuery(query); @@ -237,7 +243,7 @@ void View::SetQueries(Hud::Queries queries) query_activated.emit(dynamic_cast<HudButton*>(view)->GetQuery()); }); - button->mouse_move.connect([&](int x, int y, int dx, int dy, unsigned long mouse_button, unsigned long special_key) { + button->mouse_move.connect([this](int x, int y, int dx, int dy, unsigned long mouse_button, unsigned long special_key) { if (keyboard_stole_focus_) { MouseStealsHudButtonFocus(); @@ -245,19 +251,19 @@ void View::SetQueries(Hud::Queries queries) } }); - button->mouse_enter.connect([&](int x, int y, unsigned long mouse_button, unsigned long special_key) { + button->mouse_enter.connect([this](int x, int y, unsigned long mouse_button, unsigned long special_key) { MouseStealsHudButtonFocus(); }); - button->mouse_leave.connect([&](int x, int y, unsigned long mouse_button, unsigned long special_key) { + button->mouse_leave.connect([this](int x, int y, unsigned long mouse_button, unsigned long special_key) { SelectLastFocusedButton(); }); - button->key_nav_focus_activate.connect([&](nux::Area* area) { + button->key_nav_focus_activate.connect([this](nux::Area* area) { query_activated.emit(dynamic_cast<HudButton*>(area)->GetQuery()); }); - button->key_nav_focus_change.connect([&](nux::Area* area, bool recieving, nux::KeyNavDirection direction){ + button->key_nav_focus_change.connect([this](nux::Area* area, bool recieving, nux::KeyNavDirection direction){ if (recieving) query_selected.emit(dynamic_cast<HudButton*>(area)->GetQuery()); }); @@ -346,7 +352,6 @@ void View::AboutToHide() visible_ = false; overlay_window_buttons_->Hide(); renderer_.AboutToHide(); - ResetToDefault(); } void View::SetupViews() @@ -419,9 +424,7 @@ void View::OnSearchChanged(std::string const& search_string) search_changed.emit(search_string); for(auto button : buttons_) - { button->fake_focused = false; - } if (!buttons_.empty()) buttons_.back()->fake_focused = true; diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h index 7bf6e1ee5..859ab56ba 100644 --- a/launcher/AbstractLauncherIcon.h +++ b/launcher/AbstractLauncherIcon.h @@ -41,10 +41,9 @@ namespace unity namespace launcher { -class ActionArg +struct ActionArg { -public: - enum Source + enum class Source { LAUNCHER, SWITCHER, @@ -52,25 +51,24 @@ public: }; ActionArg() - : source(OTHER) + : source(Source::OTHER) , button(0) + , timestamp(0) , target(0) , monitor(-1) - { - } + {} - ActionArg(Source source, int button, Time timestamp = -1, Window target = 0, int monitor = -1) + ActionArg(Source source, int button, unsigned long timestamp = 0, Window target = 0, int monitor = -1) : source(source) , button(button) , timestamp(timestamp) , target(target) , monitor(monitor) - { - } + {} Source source; int button; - Time timestamp; + unsigned long timestamp; Window target; int monitor; }; diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp index cf1697613..2e0e70691 100644 --- a/launcher/ApplicationLauncherIcon.cpp +++ b/launcher/ApplicationLauncherIcon.cpp @@ -90,68 +90,68 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app) // 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(); }); + EnsureWindowState(); + UpdateMenus(); + UpdateIconGeometries(GetCenters()); + }); + app->window_closed.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState)); + app->window_moved.connect(sigc::hide(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState))); app->urgent.changed.connect([this](bool const& urgent) { - LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false"); - SetQuirk(Quirk::URGENT, urgent); - }); + LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false"); + SetQuirk(Quirk::URGENT, urgent); + }); app->active.changed.connect([this](bool const& active) { - LOG_DEBUG(logger) << tooltip_text() << " active now " << (active ? "true" : "false"); - SetQuirk(Quirk::ACTIVE, active); - }); + LOG_DEBUG(logger) << tooltip_text() << " active now " << (active ? "true" : "false"); + SetQuirk(Quirk::ACTIVE, active); + }); app->running.changed.connect([this](bool const& running) { - LOG_DEBUG(logger) << tooltip_text() << " running now " << (running ? "true" : "false"); - SetQuirk(Quirk::RUNNING, running); - - if (running) - { - _source_manager.Remove(ICON_REMOVE_TIMEOUT); - - /* It can happen that these values are not set - * during initialization if the view is closed - * 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 = app_->title(); - - if (icon_name == DEFAULT_ICON) - { - std::string icon = app_->icon(); - icon_name = (icon.empty() ? DEFAULT_ICON : icon); - } - - EnsureWindowState(); - UpdateIconGeometries(GetCenters()); - } - }); + LOG_DEBUG(logger) << tooltip_text() << " running now " << (running ? "true" : "false"); + SetQuirk(Quirk::RUNNING, running); + + if (running) + { + _source_manager.Remove(ICON_REMOVE_TIMEOUT); + + /* It can happen that these values are not set + * during initialization if the view is closed + * 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 = app_->title(); + + if (icon_name == DEFAULT_ICON) + { + std::string icon = app_->icon(); + icon_name = (icon.empty() ? DEFAULT_ICON : icon); + } + + EnsureWindowState(); + UpdateIconGeometries(GetCenters()); + } + }); app->visible.changed.connect([this](bool const& visible) { - if (!IsSticky()) - SetQuirk(Quirk::VISIBLE, visible); - }); + if (!IsSticky()) + SetQuirk(Quirk::VISIBLE, visible); + }); app->closed.connect([this]() { - if (!IsSticky()) - { - SetQuirk(Quirk::VISIBLE, false); - - /* Use a timeout to remove the icon, this avoids - * that we remove an application that is going - * to be reopened soon. So applications that - * have a splash screen won't be removed from - * the launcher while the splash is closed and - * a new window is opened. */ - _source_manager.AddTimeoutSeconds(1, [&] { - Remove(); - return false; - }, ICON_REMOVE_TIMEOUT); - } - }); + if (!IsSticky()) + { + SetQuirk(Quirk::VISIBLE, false); + + /* Use a timeout to remove the icon, this avoids + * that we remove an application that is going + * to be reopened soon. So applications that + * have a splash screen won't be removed from + * the launcher while the splash is closed and + * a new window is opened. */ + _source_manager.AddTimeoutSeconds(1, [this] { + Remove(); + return false; + }, ICON_REMOVE_TIMEOUT); + } + }); WindowManager& wm = WindowManager::Default(); wm.window_minimized.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::OnWindowMinimized)); @@ -262,7 +262,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg) * an unmapped (!= minimized) window around and * if so force "Focus" behaviour */ - if (arg.source != ActionArg::SWITCHER) + if (arg.source != ActionArg::Source::SWITCHER) { user_visible = app_->visible(); @@ -339,7 +339,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg) } else // #2 above { - if (arg.source != ActionArg::SWITCHER) + if (arg.source != ActionArg::Source::SWITCHER) { Spread(true, 0, false); } @@ -350,7 +350,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg) if (scaleWasActive) // #4 above { Focus(arg); - if (arg.source != ActionArg::SWITCHER) + if (arg.source != ActionArg::Source::SWITCHER) Spread(true, 0, false); } else // #3 above @@ -443,7 +443,7 @@ void ApplicationLauncherIcon::OnWindowMoved(guint32 moved_win) if (!app_->OwnsWindow(moved_win)) return; - _source_manager.AddTimeout(250, [&] { + _source_manager.AddTimeout(250, [this] { EnsureWindowState(); UpdateIconGeometries(GetCenters()); @@ -468,31 +468,32 @@ void ApplicationLauncherIcon::UpdateDesktopFile() glib::Object<GFile> desktop_file(g_file_new_for_path(_desktop_file.c_str())); _desktop_file_monitor = g_file_monitor_file(desktop_file, G_FILE_MONITOR_NONE, nullptr, nullptr); - g_file_monitor_set_rate_limit(_desktop_file_monitor, 1000); - - auto sig = new glib::Signal<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(_desktop_file_monitor, "changed", - [&] (GFileMonitor*, GFile* f, GFile*, GFileMonitorEvent event_type) { - switch (event_type) - { - case G_FILE_MONITOR_EVENT_DELETED: - { - glib::Object<GFile> file(f, glib::AddRef()); - _source_manager.AddTimeoutSeconds(1, [this, file] { - if (!g_file_query_exists (file, nullptr)) - UnStick(); - return false; - }); - break; - } - case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: - UpdateDesktopQuickList(); - UpdateBackgroundColor(); - break; - default: - break; - } - }); - _gsignals.Add(sig); + g_file_monitor_set_rate_limit(_desktop_file_monitor, 2000); + + _gsignals.Add<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(_desktop_file_monitor, "changed", + [this] (GFileMonitor*, GFile* f, GFile*, GFileMonitorEvent event_type) { + switch (event_type) + { + case G_FILE_MONITOR_EVENT_DELETED: + { + glib::Object<GFile> file(f, glib::AddRef()); + _source_manager.AddTimeoutSeconds(1, [this, file] { + if (!g_file_query_exists (file, nullptr)) + UnStick(); + return false; + }); + break; + } + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + { + UpdateDesktopQuickList(); + UpdateBackgroundColor(); + break; + } + default: + break; + } + }); } } @@ -591,7 +592,7 @@ void ApplicationLauncherIcon::Focus(ActionArg arg) return; } - bool show_only_visible = arg.source == ActionArg::SWITCHER; + bool show_only_visible = arg.source == ActionArg::Source::SWITCHER; app_->Focus(show_only_visible, arg.monitor); } @@ -645,7 +646,7 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList() { for (GList *l = dbusmenu_menuitem_get_children(_menu_desktop_shortcuts); l; l = l->next) { - _gsignals.Disconnect(l->data, "item-activated"); + _gsignals.Disconnect(l->data, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED); } } @@ -672,15 +673,12 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList() dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name); dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - dbusmenu_menuitem_property_set(item, "shortcut-nick", nicks[index]); + std::string nick(nicks[index]); - auto sig = new glib::Signal<void, DbusmenuMenuitem*, gint>(item, "item-activated", - [&] (DbusmenuMenuitem* item, gint) { - const gchar *nick; - nick = dbusmenu_menuitem_property_get(item, "shortcut-nick"); - indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick); - }); - _gsignals.Add(sig); + _gsignals.Add<void, DbusmenuMenuitem*, gint>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + [this, nick] (DbusmenuMenuitem* item, unsigned) { + indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick.c_str()); + }); dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item); index++; @@ -729,8 +727,8 @@ void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady() dbusmenu_menuitem_property_set_int(menu_item, QuicklistMenuItem::MAXIMUM_LABEL_WIDTH_PROPERTY, MAXIMUM_QUICKLIST_WIDTH); Window xid = w->window_id(); - _gsignals.Add<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - [xid] (DbusmenuMenuitem*, int) { + _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + [xid] (DbusmenuMenuitem*, unsigned) { WindowManager& wm = WindowManager::Default(); wm.Activate(xid); wm.Raise(xid); @@ -821,8 +819,8 @@ void ApplicationLauncherIcon::EnsureMenuItemsReady() dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); - _gsignals.Add<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - [&] (DbusmenuMenuitem*, int) { + _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + [this] (DbusmenuMenuitem*, unsigned) { ToggleSticky(); }); @@ -842,8 +840,8 @@ void ApplicationLauncherIcon::EnsureMenuItemsReady() dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); - _gsignals.Add<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - [&] (DbusmenuMenuitem*, int) { + _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + [this] (DbusmenuMenuitem*, unsigned) { Quit(); }); @@ -945,9 +943,9 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus() dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool(item, QuicklistMenuItem::MARKUP_ENABLED_PROPERTY, TRUE); - _gsignals.Add<void, DbusmenuMenuitem*, int>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - [&] (DbusmenuMenuitem*, int timestamp) { - _source_manager.AddIdle([&] { + _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + [this] (DbusmenuMenuitem*, unsigned timestamp) { + _source_manager.AddIdle([this, timestamp] { ActivateLauncherIcon(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); return false; }); @@ -1102,7 +1100,7 @@ void ApplicationLauncherIcon::OnDndHovered() void ApplicationLauncherIcon::OnDndEnter() { /* Disabled, since the DND code is currently disabled as well. - _source_manager.AddTimeout(1000, [&] { + _source_manager.AddTimeout(1000, [this] { OnDndHovered(); return false; }, ICON_DND_OVER_TIMEOUT); @@ -1152,7 +1150,7 @@ nux::DndAction ApplicationLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_dat void ApplicationLauncherIcon::OnAcceptDrop(DndData const& dnd_data) { - auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; + auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; OpenInstanceWithUris(ValidateUrisForLaunch(dnd_data), timestamp); } @@ -1169,7 +1167,7 @@ bool ApplicationLauncherIcon::ShowInSwitcher(bool current) } else { - for (int i = 0; i < max_num_monitors; i++) + for (int i = 0; i < max_num_monitors; ++i) { if (WindowVisibleOnMonitor(i)) { diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp index ee73cb274..0f4c6f020 100644 --- a/launcher/Launcher.cpp +++ b/launcher/Launcher.cpp @@ -303,7 +303,6 @@ void Launcher::SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon) icon->mouse_enter.emit(monitor); _icon_under_mouse = icon; - tooltip_manager_.SetIcon(icon); } bool Launcher::MouseBeyondDragThreshold() const @@ -2224,7 +2223,7 @@ void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags) { SetMousePosition(x, y); - tooltip_manager_.MouseMoved(); + tooltip_manager_.MouseMoved(_icon_under_mouse); if (!_hidden) UpdateChangeInMousePosition(dx, dy); @@ -2245,7 +2244,7 @@ void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned lo } else if (_icon_under_mouse) { - auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; + auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; auto scroll_direction = (wheel_delta < 0) ? AbstractLauncherIcon::ScrollDirection::DOWN : AbstractLauncherIcon::ScrollDirection::UP; _icon_under_mouse->PerformScroll(scroll_direction, timestamp); } diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp index 25da39a3a..eef602458 100644 --- a/launcher/LauncherController.cpp +++ b/launcher/LauncherController.cpp @@ -1262,9 +1262,9 @@ bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym, if (TimeUtil::TimeDelta(¤t, &last_action_time) > local::ignore_repeat_shortcut_duration) { if (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask)) - (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0, timestamp)); + (*it)->OpenInstance(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); else - (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0, timestamp)); + (*it)->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); } // disable the "tap on super" check @@ -1384,10 +1384,10 @@ void Controller::KeyNavTerminate(bool activate) if (activate) { - auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; + auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; pimpl->sources_.AddIdle([this, timestamp] { - pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0, timestamp)); + pimpl->model_->Selection()->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); return false; }); } @@ -1488,8 +1488,8 @@ void Controller::Impl::ReceiveLauncherKeyPress(unsigned long eventType, // <SPACE> (open a new instance) case NUX_VK_SPACE: { - auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; - model_->Selection()->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0, timestamp)); + auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; + model_->Selection()->OpenInstance(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); parent_->KeyNavTerminate(false); break; } diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp index 927df2763..7efe4b458 100644 --- a/launcher/LauncherIcon.cpp +++ b/launcher/LauncherIcon.cpp @@ -62,6 +62,8 @@ const std::string UNITY_THEME_NAME = "unity-icon-theme"; const std::string CENTER_STABILIZE_TIMEOUT = "center-stabilize-timeout"; const std::string PRESENT_TIMEOUT = "present-timeout"; const std::string QUIRK_DELAY_TIMEOUT = "quirk-delay-timeout"; + +const unsigned TOOLTIP_FADE_DURATION = 80; } NUX_IMPLEMENT_OBJECT_TYPE(LauncherIcon); @@ -86,6 +88,7 @@ LauncherIcon::LauncherIcon(IconType type) , _parent_geo(max_num_monitors) , _saved_center(max_num_monitors) , _allow_quicklist_to_show(true) + , _tooltip_fade_animator(TOOLTIP_FADE_DURATION) { for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i) { @@ -115,6 +118,19 @@ LauncherIcon::LauncherIcon(IconType type) mouse_down.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseDown)); mouse_up.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseUp)); mouse_click.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseClick)); + + _tooltip_fade_animator.updated.connect([this] (double opacity) { + if (_tooltip) + { + _tooltip->SetOpacity(opacity); + + if (opacity == 0.0f && _tooltip_fade_animator.GetStartValue() > _tooltip_fade_animator.GetFinishValue()) + { + _tooltip->ShowWindow(false); + _tooltip->SetOpacity(0.0f); + } + } + }); } LauncherIcon::~LauncherIcon() @@ -143,6 +159,7 @@ LauncherIcon::~LauncherIcon() void LauncherIcon::LoadTooltip() { _tooltip = new Tooltip(); + _tooltip->SetOpacity(0.0f); AddChild(_tooltip.GetPointer()); _tooltip->text = tooltip_text(); @@ -522,6 +539,11 @@ LauncherIcon::ShowTooltip() _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); _tooltip->ShowWindow(!tooltip_text().empty()); tooltip_visible.emit(_tooltip); + + if (_tooltip_fade_animator.CurrentState() == nux::animation::Animation::State::Running) + _tooltip_fade_animator.Reverse(); + else + _tooltip_fade_animator.SetStartValue(0.0f).SetFinishValue(1.0f).Start(); } void @@ -651,9 +673,9 @@ void LauncherIcon::RecvMouseUp(int button, int monitor, unsigned long key_flags) void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_flags) { - auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp; + auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; - ActionArg arg(ActionArg::LAUNCHER, button, timestamp); + ActionArg arg(ActionArg::Source::LAUNCHER, button, timestamp); arg.monitor = monitor; bool shift_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_SHIFT); @@ -669,7 +691,13 @@ void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_fla void LauncherIcon::HideTooltip() { if (_tooltip) - _tooltip->ShowWindow(false); + { + if (_tooltip_fade_animator.CurrentState() == nux::animation::Animation::State::Running) + _tooltip_fade_animator.Reverse(); + else + _tooltip_fade_animator.SetStartValue(1.0f).SetFinishValue(0.0f).Start(); + } + tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr)); } diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h index 26f8b04e4..68a783b60 100644 --- a/launcher/LauncherIcon.h +++ b/launcher/LauncherIcon.h @@ -21,12 +21,9 @@ #ifndef LAUNCHERICON_H #define LAUNCHERICON_H -#include <set> -#include <boost/unordered_map.hpp> - #include <Nux/Nux.h> #include <Nux/BaseWindow.h> -#include <NuxCore/Math/MathInc.h> +#include <NuxCore/Animation.h> #include <gtk/gtk.h> #include <libdbusmenu-glib/client.h> @@ -338,6 +335,8 @@ private: std::list<LauncherEntryRemote::Ptr> _entry_list; + nux::animation::AnimateValue<double> _tooltip_fade_animator; + protected: glib::SourceManager _source_manager; }; diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h index 06e0edb33..e1057515c 100644 --- a/launcher/MockLauncherIcon.h +++ b/launcher/MockLauncherIcon.h @@ -22,7 +22,6 @@ #define MOCKLAUNCHERICON_H #include <Nux/Nux.h> -#include <NuxCore/Math/MathInc.h> #include <Nux/BaseWindow.h> #include <Nux/View.h> diff --git a/launcher/StandaloneLauncher.cpp b/launcher/StandaloneLauncher.cpp index 777951f6f..cec0cd82d 100644 --- a/launcher/StandaloneLauncher.cpp +++ b/launcher/StandaloneLauncher.cpp @@ -18,7 +18,9 @@ * */ -#include "Nux/Nux.h" +#include <Nux/Nux.h> +#include <Nux/NuxTimerTickSource.h> +#include <NuxCore/AnimationController.h> #include <gtk/gtk.h> #include "unity-shared/BackgroundEffectHelper.h" @@ -43,6 +45,7 @@ struct LauncherWindow { LauncherWindow() : wt(nux::CreateGUIThread("Unity Launcher", win_size.width, win_size.height, 0, &LauncherWindow::ThreadWidgetInit, this)) + , animation_controller(tick_source) {} void Show() @@ -85,6 +88,8 @@ private: unity::Settings settings; panel::Style panel_style; std::shared_ptr<nux::WindowThread> wt; + nux::NuxTimerTickSource tick_source; + nux::animation::AnimationController animation_controller; launcher::Controller::Ptr controller; }; diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp index 89922e006..bd48fb74f 100644 --- a/launcher/SwitcherController.cpp +++ b/launcher/SwitcherController.cpp @@ -426,8 +426,8 @@ void Controller::Impl::Hide(bool accept_state) Selection selection = GetCurrentSelection(); if (selection.application_) { - Time timestamp = -1; - selection.application_->Activate(ActionArg(ActionArg::SWITCHER, 0, + Time timestamp = 0; + selection.application_->Activate(ActionArg(ActionArg::Source::SWITCHER, 0, timestamp, selection.window_)); } } diff --git a/launcher/TooltipManager.cpp b/launcher/TooltipManager.cpp index c34783233..dee8a5103 100644 --- a/launcher/TooltipManager.cpp +++ b/launcher/TooltipManager.cpp @@ -15,6 +15,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Jacob Edwards <j.johan.edwards@gmail.com> + * Andrea Azzarone <andrea.azzarone@canonical.com> */ #include "TooltipManager.h" @@ -23,104 +24,69 @@ namespace unity { namespace launcher { - namespace { -const unsigned int TOOLTIPS_SHOW_TIMEOUT_LENGTH = 1000; +const unsigned int TOOLTIPS_SHOW_TIMEOUT_LENGTH = 500; } TooltipManager::TooltipManager() - : show_tooltips_(false) - , hovered_(false) - , timer_locked_(false) + : skip_timeout_(false) {} -void TooltipManager::SetIcon(AbstractLauncherIcon::Ptr const& newIcon) -{ - if (icon_ == newIcon) +void TooltipManager::MouseMoved(AbstractLauncherIcon::Ptr const& icon_under_mouse) +{ + if (icon_ == icon_under_mouse) return; - // Unlock hover timer, in case the previous icon had no valid tooltip - timer_locked_ = false; - - if (show_tooltips_) - { - // Show new tooltip, get rid of the old olne - if (icon_) - icon_->HideTooltip(); - if (newIcon) - newIcon->ShowTooltip(); - } - else if (!newIcon) - { - // Stop the hover timer for null launcher space - StopTimer(); - } - else - { - AbstractLauncherIcon::IconType type = newIcon->GetIconType(); - if ((type == AbstractLauncherIcon::IconType::HOME || - type == AbstractLauncherIcon::IconType::HUD) && - newIcon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE)) - { - // Lock the hover timer for no valid tooltip cases - timer_locked_ = true; - StopTimer(); - } - } + StopTimer(); + if (icon_) + icon_->HideTooltip(); + + icon_ = icon_under_mouse; - icon_ = newIcon; + if (icon_ && !skip_timeout_) + ResetTimer(icon_); + else if (icon_ && skip_timeout_) + icon_->ShowTooltip(); } -void TooltipManager::SetHover(bool on_launcher) -{ - if (hovered_ == on_launcher) - return; - hovered_ = on_launcher; - - if (show_tooltips_ && !hovered_) - { - show_tooltips_ = false; - if (icon_) - icon_->HideTooltip(); - } +void TooltipManager::IconClicked() +{ + if (icon_) + icon_->HideTooltip(); } -void TooltipManager::MouseMoved() +void TooltipManager::SetHover(bool hovered) { - if (!icon_ || show_tooltips_) - return; - - ResetTimer(); + if (!hovered) + Reset(); } -void TooltipManager::IconClicked() +void TooltipManager::Reset() { StopTimer(); - if (show_tooltips_ && icon_) + + if (icon_) icon_->HideTooltip(); - show_tooltips_ = false; - timer_locked_ = true; + icon_ = AbstractLauncherIcon::Ptr(); + skip_timeout_ = false; } -void TooltipManager::ResetTimer() +void TooltipManager::ResetTimer(AbstractLauncherIcon::Ptr const& icon_under_mouse) { - if (timer_locked_) - return; - hover_timer_.reset(new glib::Timeout(TOOLTIPS_SHOW_TIMEOUT_LENGTH)); hover_timer_->Run([&] () { - show_tooltips_ = true; - icon_->ShowTooltip(); + skip_timeout_ = true; + icon_under_mouse->ShowTooltip(); return false; }); -} - + } + void TooltipManager::StopTimer() { - hover_timer_.reset(); + hover_timer_.reset(); } -} // namespace launcher -} // namespace unity +} +} diff --git a/launcher/TooltipManager.h b/launcher/TooltipManager.h index f61fc199f..817239d26 100644 --- a/launcher/TooltipManager.h +++ b/launcher/TooltipManager.h @@ -15,10 +15,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Jacob Edwards <j.johan.edwards@gmail.com> + * Andrea Azzarone <andrea.azzarone@canonical.com> */ -#ifndef TOOLTIPMANAGER -#define TOOLTIPMANAGER +#ifndef LAUNCHER_TOOLTIP_MANAGER_H +#define LAUNCHER_TOOLTIP_MANAGER_H #include <boost/noncopyable.hpp> #include <UnityCore/GLibSource.h> @@ -35,23 +36,21 @@ class TooltipManager : public boost::noncopyable public: TooltipManager(); - void SetHover(bool on_launcher); - void SetIcon(AbstractLauncherIcon::Ptr const& newIcon); - void MouseMoved(); + void SetHover(bool hovered); + void MouseMoved(AbstractLauncherIcon::Ptr const& icon_under_mouse); void IconClicked(); private: - void ResetTimer(); + void Reset(); + void ResetTimer(AbstractLauncherIcon::Ptr const& icon_under_mouse); void StopTimer(); - bool show_tooltips_; - bool hovered_; + bool skip_timeout_; AbstractLauncherIcon::Ptr icon_; - glib::Source::UniquePtr hover_timer_; - bool timer_locked_; + glib::Source::UniquePtr hover_timer_; }; -} // namespace launcher -} // namespace unity +} +} #endif diff --git a/plugins/unityshell/src/unity-launcher-icon-accessible.cpp b/plugins/unityshell/src/unity-launcher-icon-accessible.cpp index b0331eb00..66643eadf 100644 --- a/plugins/unityshell/src/unity-launcher-icon-accessible.cpp +++ b/plugins/unityshell/src/unity-launcher-icon-accessible.cpp @@ -465,7 +465,7 @@ unity_launcher_icon_accessible_do_action(AtkAction *action, icon = dynamic_cast<LauncherIcon*>(nux_object); - icon->Activate(ActionArg(ActionArg::LAUNCHER, 0)); + icon->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0)); return TRUE; } diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index 0fabcffbb..f06cb360b 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -425,7 +425,6 @@ UnityScreen::~UnityScreen() notify_uninit(); unity_a11y_finalize(); - ::unity::ui::IconRenderer::DestroyTextures(); QuicklistManager::Destroy(); reset_glib_logging(); diff --git a/po/POTFILES.in b/po/POTFILES.in index 5db06e85e..dd5b73a1f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -33,6 +33,7 @@ shortcuts/ShortcutHintPrivate.cpp shortcuts/ShortcutView.cpp shortcuts/CompizShortcutModeller.cpp shutdown/SessionView.cpp +shutdown/SessionButton.cpp services/panel-service.c unity-shared/DashStyle.cpp unity-shared/SearchBar.cpp diff --git a/resources/launcher_icon_back_170.png b/resources/launcher_icon_back_170.png Binary files differdeleted file mode 100644 index efc6794a4..000000000 --- a/resources/launcher_icon_back_170.png +++ /dev/null diff --git a/resources/launcher_icon_edge_150.png b/resources/launcher_icon_edge_150.png Binary files differindex df07bd264..9a982fefb 100644 --- a/resources/launcher_icon_edge_150.png +++ b/resources/launcher_icon_edge_150.png diff --git a/resources/launcher_icon_edge_170.png b/resources/launcher_icon_edge_170.png Binary files differdeleted file mode 100644 index 5ed464976..000000000 --- a/resources/launcher_icon_edge_170.png +++ /dev/null diff --git a/resources/launcher_icon_edge_54.png b/resources/launcher_icon_edge_54.png Binary files differindex e0f85f305..e97bfdb7f 100644 --- a/resources/launcher_icon_edge_54.png +++ b/resources/launcher_icon_edge_54.png diff --git a/resources/launcher_icon_selected_back_170.png b/resources/launcher_icon_selected_back_170.png Binary files differdeleted file mode 100644 index 303532ee2..000000000 --- a/resources/launcher_icon_selected_back_170.png +++ /dev/null diff --git a/resources/launcher_icon_selected_edge_170.png b/resources/launcher_icon_selected_edge_170.png Binary files differdeleted file mode 100644 index 4ec6455fe..000000000 --- a/resources/launcher_icon_selected_edge_170.png +++ /dev/null diff --git a/resources/launcher_icon_shine_170.png b/resources/launcher_icon_shine_170.png Binary files differdeleted file mode 100644 index 41aba4632..000000000 --- a/resources/launcher_icon_shine_170.png +++ /dev/null diff --git a/resources/launcher_pip_large_ltr.png b/resources/launcher_pip_large_ltr.png Binary files differnew file mode 100644 index 000000000..33f0a6d45 --- /dev/null +++ b/resources/launcher_pip_large_ltr.png diff --git a/resources/launcher_pip_large_rtl.png b/resources/launcher_pip_large_rtl.png Binary files differnew file mode 100644 index 000000000..9c036c921 --- /dev/null +++ b/resources/launcher_pip_large_rtl.png diff --git a/shutdown/SessionButton.cpp b/shutdown/SessionButton.cpp index ef45506c1..8af0b6ee7 100644 --- a/shutdown/SessionButton.cpp +++ b/shutdown/SessionButton.cpp @@ -22,7 +22,7 @@ #include <Nux/VLayout.h> #include <UnityCore/Variant.h> - +#include <glib/gi18n-lib.h> namespace unity { @@ -38,15 +38,47 @@ namespace style NUX_IMPLEMENT_OBJECT_TYPE(Button); -Button::Button(std::string const& label, std::string const& texture_name, NUX_FILE_LINE_DECL) +Button::Button(Action action, NUX_FILE_LINE_DECL) : nux::View(NUX_FILE_LINE_PARAM) , highlighted(false) + , action([this] { return action_; }) , label([this] { return label_view_->GetText(); }) + , action_(action) { SetAcceptKeyNavFocusOnMouseDown(false); SetAcceptKeyNavFocusOnMouseEnter(true); - std::string texture_prefix = PKGDATADIR"/" + texture_name; + std::string texture_prefix = PKGDATADIR"/"; + std::string label; + + switch (action_) + { + case Action::LOCK: + texture_prefix += "lockscreen"; + label = _("Lock"); + break; + case Action::LOGOUT: + texture_prefix += "logout"; + label = _("Log Out"); + break; + case Action::SUSPEND: + texture_prefix += "suspend"; + label = _("Suspend"); + break; + case Action::HIBERNATE: + texture_prefix += "hibernate"; + label = _("Hibernate"); + break; + case Action::SHUTDOWN: + texture_prefix += "shutdown"; + label = _("Shut Down"); + break; + case Action::REBOOT: + texture_prefix += "restart"; + label = _("Restart"); + break; + } + normal_tex_.Adopt(nux::CreateTexture2DFromFile((texture_prefix + ".png").c_str(), -1, true)); highlight_tex_.Adopt(nux::CreateTexture2DFromFile((texture_prefix + "_highlight.png").c_str(), -1, true)); diff --git a/shutdown/SessionButton.h b/shutdown/SessionButton.h index f9b0ae362..055360048 100644 --- a/shutdown/SessionButton.h +++ b/shutdown/SessionButton.h @@ -37,9 +37,20 @@ class Button : public nux::View, public debug::Introspectable { NUX_DECLARE_OBJECT_TYPE(Button, nux::View); public: - Button(std::string const& label, std::string const& texture_name, NUX_FILE_LINE_PROTO); + enum class Action + { + LOCK, + LOGOUT, + SUSPEND, + HIBERNATE, + SHUTDOWN, + REBOOT + }; + + Button(Action, NUX_FILE_LINE_PROTO); nux::Property<bool> highlighted; + nux::ROProperty<Action> action; nux::ROProperty<std::string> label; sigc::signal<void> activated; @@ -54,6 +65,7 @@ protected: private: friend class TestSessionButton; + Action action_; IconTexture* image_view_; StaticCairoText* label_view_; nux::ObjectPtr<nux::BaseTexture> normal_tex_; diff --git a/shutdown/SessionView.cpp b/shutdown/SessionView.cpp index 93e77c996..2fa8cf0cd 100644 --- a/shutdown/SessionView.cpp +++ b/shutdown/SessionView.cpp @@ -173,11 +173,11 @@ void View::Populate() if (mode() == Mode::LOGOUT) { - auto* button = new Button(_("Lock"), "lockscreen", NUX_TRACKER_LOCATION); + auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION); button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen)); AddButton(button); - button = new Button(_("Logout"), "logout", NUX_TRACKER_LOCATION); + button = new Button(Button::Action::LOGOUT, NUX_TRACKER_LOCATION); button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Logout)); AddButton(button); } @@ -185,20 +185,20 @@ void View::Populate() { if (mode() == Mode::FULL) { - auto* button = new Button(_("Lock"), "lockscreen", NUX_TRACKER_LOCATION); + auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION); button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen)); AddButton(button); if (manager_->CanSuspend()) { - button = new Button(_("Suspend"), "suspend", NUX_TRACKER_LOCATION); + button = new Button(Button::Action::SUSPEND, NUX_TRACKER_LOCATION); button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Suspend)); AddButton(button); } if (manager_->CanHibernate()) { - button = new Button(_("Hibernate"), "hibernate", NUX_TRACKER_LOCATION); + button = new Button(Button::Action::HIBERNATE, NUX_TRACKER_LOCATION); button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Hibernate)); AddButton(button); } @@ -206,17 +206,17 @@ void View::Populate() if (manager_->CanShutdown()) { - auto* button = new Button(_("Shutdown"), "shutdown", NUX_TRACKER_LOCATION); - button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Shutdown)); + auto *button = new Button(Button::Action::REBOOT, NUX_TRACKER_LOCATION); + button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Reboot)); AddButton(button); - button = new Button(_("Restart"), "restart", NUX_TRACKER_LOCATION); - button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Reboot)); + button = new Button(Button::Action::SHUTDOWN, NUX_TRACKER_LOCATION); + button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Shutdown)); AddButton(button); } else if (mode() == Mode::FULL) { - auto* button = new Button(_("Logout"), "logout", NUX_TRACKER_LOCATION); + auto* button = new Button(Button::Action::LOGOUT, NUX_TRACKER_LOCATION); button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Logout)); AddButton(button); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8fdb8444f..d07dd17e2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -99,6 +99,27 @@ if (GTEST_SRC_DIR AND test_service_panel.cpp) target_link_libraries(test-gtest-service unity-shared ${LIBS}) +# gtest-slow, start moving things over that are slow running tests + set (GTEST_SLOW_SOURCES + test_main.cpp + logger_helper.cpp + test_im_text_entry_slow.cpp + test_im_text_entry_class.cpp + test_tooltip_manager.cpp + ) + + set (GTEST_SLOW_LIBS + gtest + gmock + launcher-lib + unity-shared + ) + + add_executable(test-gtest-slow ${GTEST_SLOW_SOURCES}) + + target_link_libraries(test-gtest-slow ${GTEST_SLOW_LIBS}) + + add_test(UnityGTestSlow test-gtest-slow) # The actual test executable (xless) - do not put anything that requires X in here set (GTEST_XLESS_SOURCES @@ -218,6 +239,7 @@ if (ENABLE_X_SUPPORT) test_hud_view.cpp test_icon_loader.cpp test_im_text_entry.cpp + test_im_text_entry_class.cpp test_launcher.cpp test_launcher_controller.cpp test_launcher_drag_window.cpp @@ -263,7 +285,6 @@ if (ENABLE_X_SUPPORT) test_texture_cache.cpp test_text_input.cpp test_thumbnail_generator.cpp - test_tooltip_manager.cpp test_trash_launcher_icon.cpp test_unity_settings.cpp test_unity_window_style.cpp @@ -322,6 +343,7 @@ if (ENABLE_X_SUPPORT) set (GTEST_TEST_COMMAND_GESTURES ./test-gestures/test-gestures) endif (ENABLE_X_SUPPORT) set (GTEST_TEST_COMMAND_XLESS ./test-gtest-xless) +set (GTEST_TEST_COMMAND_SLOW ./test-gtest-slow) set (GTEST_TEST_COMMAND_DBUS dbus-test-runner --task ./test-gtest-service --task ./test-gtest-dbus) set (TEST_COMMAND @@ -330,6 +352,7 @@ set (TEST_COMMAND && ${GTEST_TEST_COMMAND_XLESS} --gtest_output=xml:./ && ${GTEST_TEST_COMMAND_GESTURES} --gtest_output=xml:./ && ${GTEST_TEST_COMMAND_DBUS} --gtest_output=xml:./ + && ${GTEST_TEST_COMMAND_SLOW} --gtest_output=xml:./ ) set (TEST_COMMAND_HEADLESS @@ -340,7 +363,7 @@ set (TEST_COMMAND_HEADLESS if (GTEST_SRC_DIR) if (ENABLE_X_SUPPORT) - add_custom_target (check COMMAND ${TEST_COMMAND} DEPENDS test-unit test-gtest test-gtest-xless test-gtest-dbus test-gestures) + add_custom_target (check COMMAND ${TEST_COMMAND} DEPENDS test-unit test-gtest test-gtest-slow test-gtest-xless test-gtest-dbus test-gestures) add_custom_target (check-headless COMMAND ${TEST_COMMAND_HEADLESS} DEPENDS test-gtest-xless test-gtest-dbus test-gestures) add_custom_target (gcheck COMMAND ${DBUS_TEST_COMMAND} DEPENDS test-gtest test-gtest-xless) else () diff --git a/tests/autopilot/unity/emulators/launcher.py b/tests/autopilot/unity/emulators/launcher.py index ac7842192..0f74d9bff 100644 --- a/tests/autopilot/unity/emulators/launcher.py +++ b/tests/autopilot/unity/emulators/launcher.py @@ -494,7 +494,7 @@ class LauncherModel(UnityIntrospectionObject): looking for an icon. For example, to find an icon with a particular desktop_id, one might do this from within a test: - >>> self.launcher.model.get_icon(desktop_id="gnome-calculator.desktop") + >>> self.launcher.model.get_icon(desktop_id="gcalctool.desktop") This method returns only one icon. It is the callers responsibility to ensure that the filter matches only one icon. diff --git a/tests/autopilot/unity/tests/launcher/test_icon_behavior.py b/tests/autopilot/unity/tests/launcher/test_icon_behavior.py index c7c0847b1..da6e38cae 100644 --- a/tests/autopilot/unity/tests/launcher/test_icon_behavior.py +++ b/tests/autopilot/unity/tests/launcher/test_icon_behavior.py @@ -315,7 +315,7 @@ class LauncherDragIconsBehavior(LauncherTestCase): # not exist, and we don't want to wait for 10 seconds, so we do this # the old fashioned way. get_icon_fn = lambda: self.unity.launcher.model.get_children_by_type( - ApplicationLauncherIcon, desktop_id="gnome-calculator.desktop") + ApplicationLauncherIcon, desktop_id="gcalctool.desktop") calc_icon = get_icon_fn() if calc_icon: self.launcher_instance.unlock_from_launcher(calc_icon[0]) diff --git a/tests/autopilot/unity/tests/test_dash.py b/tests/autopilot/unity/tests/test_dash.py index 26e092402..64d61d8b6 100644 --- a/tests/autopilot/unity/tests/test_dash.py +++ b/tests/autopilot/unity/tests/test_dash.py @@ -972,6 +972,12 @@ class PreviewNavigateTests(DashTestCase): self.assertThat(self.unity.dash.preview_displaying, Eventually(Equals(False))) + def test_overlay_text(self): + """Fallback overlay text is internationalized, should always be valid.""" + cover_art = self.get_current_preview().cover_art[0] + self.assertThat(cover_art.overlay_text, + Eventually(Equals("No Image Available"))) + class PreviewClickCancelTests(DashTestCase): """Tests that the preview closes when left, middle, and right clicking in the preview""" diff --git a/tests/autopilot/unity/tests/test_hud.py b/tests/autopilot/unity/tests/test_hud.py index 97938b9d9..bc040a1ed 100644 --- a/tests/autopilot/unity/tests/test_hud.py +++ b/tests/autopilot/unity/tests/test_hud.py @@ -459,6 +459,17 @@ class HudBehaviorTests(HudTestsBase): self.assertProperty(char_win, is_active=True) + def test_mouse_does_not_steal_button_focus(self): + """When typing in the hud the mouse must not steal button focus.""" + + self.unity.hud.ensure_visible() + + (x,y,w,h) = self.unity.hud.view.geometry + self.mouse.move(w/4, h/4) + + self.keyboard.type("a") + self.assertThat(self.unity.hud.view.selected_button, Eventually(Equals(1))) + class HudLauncherInteractionsTests(HudTestsBase): diff --git a/tests/test_application_launcher_icon.cpp b/tests/test_application_launcher_icon.cpp index ed8ff310e..d1fc452b1 100644 --- a/tests/test_application_launcher_icon.cpp +++ b/tests/test_application_launcher_icon.cpp @@ -30,9 +30,11 @@ #include "StandaloneWindowManager.h" #include "mock-application.h" #include "StandaloneWindowManager.h" +#include "test_utils.h" -using namespace unity; +using namespace testing; using namespace testmocks; +using namespace unity; using namespace unity::launcher; namespace @@ -41,22 +43,39 @@ 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"; -class TestApplicationLauncherIcon : public testing::Test +struct MockApplicationLauncherIcon : ApplicationLauncherIcon +{ + MockApplicationLauncherIcon(ApplicationPtr const& app) + : ApplicationLauncherIcon(app) + {} + + MOCK_METHOD1(ActivateLauncherIcon, void(ActionArg)); +}; + +MATCHER_P(AreArgsEqual, a, "") +{ + return arg.source == a.source && + arg.button == a.button && + arg.timestamp == a.timestamp && + arg.target == a.target; + arg.monitor = a.monitor; +} + +struct TestApplicationLauncherIcon : Test { -public: virtual void SetUp() { WM = dynamic_cast<StandaloneWindowManager*>(&WindowManager::Default()); - usc_app.reset(new MockApplication(USC_DESKTOP, "softwarecenter")); - usc_icon = new launcher::ApplicationLauncherIcon(usc_app); + usc_app = std::make_shared<MockApplication>(USC_DESKTOP, "softwarecenter"); + usc_icon = new NiceMock<MockApplicationLauncherIcon>(usc_app); ASSERT_EQ(usc_icon->DesktopFile(), USC_DESKTOP); - empty_app.reset(new MockApplication(NO_ICON_DESKTOP)); - empty_icon = new launcher::ApplicationLauncherIcon(empty_app); + empty_app = std::make_shared<MockApplication>(NO_ICON_DESKTOP); + empty_icon = new NiceMock<MockApplicationLauncherIcon>(empty_app); ASSERT_EQ(empty_icon->DesktopFile(), NO_ICON_DESKTOP); - mock_app.reset(new MockApplication("")); - mock_icon = new launcher::ApplicationLauncherIcon(mock_app); + mock_app = std::make_shared<MockApplication>(""); + mock_icon = new NiceMock<MockApplicationLauncherIcon>(mock_app); ASSERT_TRUE(mock_icon->DesktopFile().empty()); } @@ -76,9 +95,9 @@ public: 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; + nux::ObjectPtr<MockApplicationLauncherIcon> usc_icon; + nux::ObjectPtr<MockApplicationLauncherIcon> empty_icon; + nux::ObjectPtr<MockApplicationLauncherIcon> mock_icon; }; TEST_F(TestApplicationLauncherIcon, Position) @@ -443,4 +462,29 @@ TEST_F(TestApplicationLauncherIcon, WindowListMenusWithEmptyTitles) ASSERT_EQ(menu1_it, menus.end()); } +TEST_F(TestApplicationLauncherIcon, QuicklistMenuItemForAppName) +{ + mock_app->title_ = "MockApplicationTitle"; + + auto const& menus = mock_icon->Menus(); + auto app_it = std::find_if(menus.begin(), menus.end(), [this] (glib::Object<DbusmenuMenuitem> it) { + auto* label = dbusmenu_menuitem_property_get(it, DBUSMENU_MENUITEM_PROP_LABEL); + return (label && std::string(label) == ("<b>"+mock_app->title_+"</b>")); + }); + + ASSERT_NE(app_it, menus.end()); + + bool method_called = false; + ON_CALL(*mock_icon, ActivateLauncherIcon(_)).WillByDefault(Invoke([&method_called] (ActionArg arg) { + method_called = true; + })); + + unsigned time = g_random_int(); + EXPECT_CALL(*mock_icon, ActivateLauncherIcon(AreArgsEqual(ActionArg(ActionArg::Source::LAUNCHER, 0, time)))); + dbusmenu_menuitem_handle_event(*app_it, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, time); + + Utils::WaitUntilMSec(method_called); + EXPECT_TRUE(method_called); +} + } diff --git a/tests/test_im_text_entry.cpp b/tests/test_im_text_entry.cpp index 2c5457119..334b6ab9d 100644 --- a/tests/test_im_text_entry.cpp +++ b/tests/test_im_text_entry.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012 Canonical Ltd. + * Copyright 2012-2013 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 @@ -19,49 +19,12 @@ * */ -#include <gmock/gmock.h> -#include "unity-shared/IMTextEntry.h" +#include "test_im_text_entry.h" using namespace testing; using namespace unity; using namespace nux; -namespace -{ - -class TestEvent : public nux::Event -{ -public: - TestEvent(nux::KeyModifier keymod, unsigned long keysym) - { - type = NUX_KEYDOWN; - key_modifiers = keymod; - x11_keysym = keysym; - } - - TestEvent(unsigned long keysym) - { - type = NUX_KEYDOWN; - x11_keysym = keysym; - } -}; - -class MockTextEntry : public IMTextEntry -{ -public: - MOCK_METHOD0(CutClipboard, void()); - MOCK_METHOD0(CopyClipboard, void()); - MOCK_METHOD0(PasteClipboard, void()); - MOCK_METHOD0(PastePrimaryClipboard, void()); - - bool InspectKeyEvent(nux::Event const& event) - { - key_down.emit(event.type, event.GetKeySym(), event.GetKeyState(), nullptr, 0); - return IMTextEntry::InspectKeyEvent(event); - } -}; - - TEST(TestIMTextEntry, CopyCtrlC) { MockTextEntry text_entry; @@ -173,27 +136,3 @@ TEST(TestIMTextEntry, CtrlKeybindings) EXPECT_TRUE(text_entry.InspectKeyEvent(event)); } } - -TEST(TestIMTextEntry, AltKeybindings) -{ - MockTextEntry text_entry; - - for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym) - { - TestEvent event(KEY_MODIFIER_ALT, keysym); - EXPECT_FALSE(text_entry.InspectKeyEvent(event)); - } -} - -TEST(TestIMTextEntry, SuperKeybindings) -{ - MockTextEntry text_entry; - - for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym) - { - TestEvent event(KEY_MODIFIER_SUPER, keysym); - EXPECT_FALSE(text_entry.InspectKeyEvent(event)); - } -} - -} diff --git a/tests/test_im_text_entry.h b/tests/test_im_text_entry.h new file mode 100644 index 000000000..1fa0e8f10 --- /dev/null +++ b/tests/test_im_text_entry.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2013 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: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> + * + */ + +#ifndef TEST_IM_TEXT_ENTRY_H +#define TEST_IM_TEXT_ENTRY_H + +#include <gmock/gmock.h> +#include "unity-shared/IMTextEntry.h" + +class TestEvent : public nux::Event +{ +public: + TestEvent(nux::KeyModifier keymod, unsigned long keysym); + + TestEvent(unsigned long keysym); +}; + +class MockTextEntry : public unity::IMTextEntry +{ +public: + MOCK_METHOD0(CutClipboard, void()); + MOCK_METHOD0(CopyClipboard, void()); + MOCK_METHOD0(PasteClipboard, void()); + MOCK_METHOD0(PastePrimaryClipboard, void()); + + bool InspectKeyEvent(nux::Event const& event); +}; + +#endif // TEST_IM_TEXT_ENTRY_H diff --git a/tests/test_im_text_entry_class.cpp b/tests/test_im_text_entry_class.cpp new file mode 100644 index 000000000..52083994f --- /dev/null +++ b/tests/test_im_text_entry_class.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2013 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: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> + * + */ + +#include "test_im_text_entry.h" + +TestEvent::TestEvent(nux::KeyModifier keymod, unsigned long keysym) +{ + type = nux::NUX_KEYDOWN; + key_modifiers = keymod; + x11_keysym = keysym; +} + +TestEvent::TestEvent(unsigned long keysym) +{ + type = nux::NUX_KEYDOWN; + x11_keysym = keysym; +} + +bool MockTextEntry::InspectKeyEvent(nux::Event const& event) +{ + key_down.emit(event.type, event.GetKeySym(), event.GetKeyState(), nullptr, 0); + return IMTextEntry::InspectKeyEvent(event); +} diff --git a/tests/test_im_text_entry_slow.cpp b/tests/test_im_text_entry_slow.cpp new file mode 100644 index 000000000..caa3493b8 --- /dev/null +++ b/tests/test_im_text_entry_slow.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2012-2013 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: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> + * + */ + +#include "test_im_text_entry.h" + +using namespace nux; + +TEST(TestIMTextEntry, AltKeybindings) +{ + MockTextEntry text_entry; + + for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym) + { + TestEvent event(KEY_MODIFIER_ALT, keysym); + EXPECT_FALSE(text_entry.InspectKeyEvent(event)); + } +} + +TEST(TestIMTextEntry, SuperKeybindings) +{ + MockTextEntry text_entry; + + for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym) + { + TestEvent event(KEY_MODIFIER_SUPER, keysym); + EXPECT_FALSE(text_entry.InspectKeyEvent(event)); + } +} diff --git a/tests/test_session_button.cpp b/tests/test_session_button.cpp index a108a7373..67e28d496 100644 --- a/tests/test_session_button.cpp +++ b/tests/test_session_button.cpp @@ -31,7 +31,7 @@ struct TestSessionButton : testing::Test { struct ButtonWrap : Button { - ButtonWrap() : Button("ButtonLabel", "hibernate") {} + ButtonWrap() : Button(Action::LOCK) {} using Button::AcceptKeyNavFocusOnMouseEnter; using Button::AcceptKeyNavFocusOnMouseDown; @@ -46,8 +46,8 @@ struct TestSessionButton : testing::Test TEST_F(TestSessionButton, Construct) { + EXPECT_EQ(button.action(), Button::Action::LOCK); EXPECT_FALSE(button.highlighted()); - EXPECT_EQ(button.label(), "ButtonLabel"); EXPECT_TRUE(button.AcceptKeyNavFocusOnMouseEnter()); EXPECT_FALSE(button.AcceptKeyNavFocusOnMouseDown()); } @@ -120,5 +120,50 @@ TEST_F(TestSessionButton, KeyFocusActivatesIt) EXPECT_TRUE(activated); } +// Action typed buttons tests + +struct ActionButton : public testing::TestWithParam<Button::Action> { + ActionButton() + : button(GetParam()) + {} + + std::string GetExpectedLabel() + { + switch (GetParam()) + { + case Button::Action::LOCK: + return "Lock"; + case Button::Action::LOGOUT: + return "Log Out"; + case Button::Action::SUSPEND: + return "Suspend"; + case Button::Action::HIBERNATE: + return "Hibernate"; + case Button::Action::SHUTDOWN: + return "Shut Down"; + case Button::Action::REBOOT: + return "Restart"; + } + + return ""; + } + + Button button; +}; + +INSTANTIATE_TEST_CASE_P(TestSessionButtonTypes, ActionButton, + testing::Values(Button::Action::LOCK, Button::Action::LOGOUT, Button::Action::SUSPEND, + Button::Action::HIBERNATE, Button::Action::SHUTDOWN, Button::Action::REBOOT)); + +TEST_P(/*TestSessionButtonTypes*/ActionButton, Label) +{ + EXPECT_EQ(button.label(), GetExpectedLabel()); +} + +TEST_P(/*TestSessionButtonTypes*/ActionButton, Action) +{ + EXPECT_EQ(button.action(), GetParam()); +} + } // session } // unity \ No newline at end of file diff --git a/tests/test_session_view.cpp b/tests/test_session_view.cpp index 5b65178e6..4cdebefad 100644 --- a/tests/test_session_view.cpp +++ b/tests/test_session_view.cpp @@ -60,16 +60,30 @@ struct TestSessionView : testing::Test return buttons; } - Button* GetButtonByLabel(std::string const& label) const + Button* GetButtonByAction(Button::Action action) const { for (auto const& button : GetButtons()) { - if (button->label() == label) + if (button->action() == action) return button; } return nullptr; } + + int GetButtonPosition(Button::Action action) const + { + int pos = 0; + for (auto const& button : GetButtons()) + { + if (button->action() == action) + return pos; + + ++pos; + } + + return -1; + } }; void TearDown() @@ -129,29 +143,29 @@ TEST_F(TestSessionView, FullModeButtons) ON_CALL(*manager, CanHibernate()).WillByDefault(testing::Return(true)); view.mode.changed.emit(View::Mode::FULL); - EXPECT_EQ(view.GetButtonByLabel("Logout"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Lock"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Suspend"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Hibernate"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Shutdown"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Restart"), nullptr); + EXPECT_EQ(view.GetButtonByAction(Button::Action::LOGOUT), nullptr); + EXPECT_EQ(view.GetButtonPosition(Button::Action::LOCK), 0); + EXPECT_EQ(view.GetButtonPosition(Button::Action::SUSPEND), 1); + EXPECT_EQ(view.GetButtonPosition(Button::Action::HIBERNATE), 2); + EXPECT_EQ(view.GetButtonPosition(Button::Action::REBOOT), 3); + EXPECT_EQ(view.GetButtonPosition(Button::Action::SHUTDOWN), 4); ON_CALL(*manager, CanShutdown()).WillByDefault(testing::Return(false)); view.mode.changed.emit(View::Mode::FULL); - EXPECT_NE(view.GetButtonByLabel("Logout"), nullptr); - EXPECT_EQ(view.GetButtonByLabel("Shutdown"), nullptr); - EXPECT_EQ(view.GetButtonByLabel("Restart"), nullptr); + EXPECT_NE(view.GetButtonByAction(Button::Action::LOGOUT), nullptr); + EXPECT_EQ(view.GetButtonByAction(Button::Action::SHUTDOWN), nullptr); + EXPECT_EQ(view.GetButtonByAction(Button::Action::REBOOT), nullptr); ON_CALL(*manager, CanSuspend()).WillByDefault(testing::Return(false)); view.mode.changed.emit(View::Mode::FULL); - EXPECT_EQ(view.GetButtonByLabel("Suspend"), nullptr); + EXPECT_EQ(view.GetButtonByAction(Button::Action::SUSPEND), nullptr); ON_CALL(*manager, CanHibernate()).WillByDefault(testing::Return(false)); view.mode.changed.emit(View::Mode::FULL); - EXPECT_EQ(view.GetButtonByLabel("Hibernate"), nullptr); + EXPECT_EQ(view.GetButtonByAction(Button::Action::HIBERNATE), nullptr); } TEST_F(TestSessionView, ShutdownModeButtons) @@ -160,8 +174,8 @@ TEST_F(TestSessionView, ShutdownModeButtons) view.mode = View::Mode::SHUTDOWN; EXPECT_EQ(view.GetButtons().size(), 2); - EXPECT_NE(view.GetButtonByLabel("Shutdown"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Restart"), nullptr); + EXPECT_EQ(view.GetButtonPosition(Button::Action::REBOOT), 0); + EXPECT_EQ(view.GetButtonPosition(Button::Action::SHUTDOWN), 1); } TEST_F(TestSessionView, LogoutModeButtons) @@ -169,8 +183,8 @@ TEST_F(TestSessionView, LogoutModeButtons) view.mode = View::Mode::LOGOUT; EXPECT_EQ(view.GetButtons().size(), 2); - EXPECT_NE(view.GetButtonByLabel("Logout"), nullptr); - EXPECT_NE(view.GetButtonByLabel("Lock"), nullptr); + EXPECT_EQ(view.GetButtonPosition(Button::Action::LOCK), 0); + EXPECT_EQ(view.GetButtonPosition(Button::Action::LOGOUT), 1); } TEST_F(TestSessionView, FullModeTitle) @@ -198,7 +212,7 @@ TEST_F(TestSessionView, ButtonsActivateRequestsHide) bool request_hide = false; view.request_hide.connect([&request_hide] { request_hide = true; }); - auto button = view.GetButtonByLabel("Lock"); + auto button = view.GetButtonByAction(Button::Action::LOCK); ASSERT_NE(button, nullptr); button->activated.emit(); @@ -207,7 +221,7 @@ TEST_F(TestSessionView, ButtonsActivateRequestsHide) TEST_F(TestSessionView, ButtonsActivateDeselectButton) { - auto button = view.GetButtonByLabel("Lock"); + auto button = view.GetButtonByAction(Button::Action::LOCK); ASSERT_NE(button, nullptr); button->highlighted = true; button->activated.emit(); @@ -218,7 +232,7 @@ TEST_F(TestSessionView, ButtonsActivateDeselectButton) TEST_F(TestSessionView, LockButtonActivateLocks) { EXPECT_CALL(*manager, LockScreen()); - auto button = view.GetButtonByLabel("Lock"); + auto button = view.GetButtonByAction(Button::Action::LOCK); ASSERT_NE(button, nullptr); button->activated.emit(); } @@ -227,7 +241,7 @@ TEST_F(TestSessionView, LogoutButtonActivateLogouts) { view.mode = View::Mode::LOGOUT; EXPECT_CALL(*manager, Logout()); - auto button = view.GetButtonByLabel("Logout"); + auto button = view.GetButtonByAction(Button::Action::LOGOUT); ASSERT_NE(button, nullptr); button->activated.emit(); } @@ -238,7 +252,7 @@ TEST_F(TestSessionView, SuspendButtonActivateSuspends) view.mode.changed.emit(View::Mode::FULL); EXPECT_CALL(*manager, Suspend()); - auto button = view.GetButtonByLabel("Suspend"); + auto button = view.GetButtonByAction(Button::Action::SUSPEND); ASSERT_NE(button, nullptr); button->activated.emit(); } @@ -249,7 +263,7 @@ TEST_F(TestSessionView, HibernateButtonActivateHibernates) view.mode.changed.emit(View::Mode::FULL); EXPECT_CALL(*manager, Hibernate()); - auto button = view.GetButtonByLabel("Hibernate"); + auto button = view.GetButtonByAction(Button::Action::HIBERNATE); ASSERT_NE(button, nullptr); button->activated.emit(); } @@ -260,7 +274,7 @@ TEST_F(TestSessionView, ShutdownButtonActivateShutsdown) view.mode = View::Mode::SHUTDOWN; EXPECT_CALL(*manager, Shutdown()); - auto button = view.GetButtonByLabel("Shutdown"); + auto button = view.GetButtonByAction(Button::Action::SHUTDOWN); ASSERT_NE(button, nullptr); button->activated.emit(); } @@ -271,7 +285,7 @@ TEST_F(TestSessionView, RebootButtonActivateReboots) view.mode = View::Mode::SHUTDOWN; EXPECT_CALL(*manager, Reboot()); - auto button = view.GetButtonByLabel("Restart"); + auto button = view.GetButtonByAction(Button::Action::REBOOT); ASSERT_NE(button, nullptr); button->activated.emit(); } diff --git a/tests/test_tooltip_manager.cpp b/tests/test_tooltip_manager.cpp index c7f2583ed..5badb4edf 100644 --- a/tests/test_tooltip_manager.cpp +++ b/tests/test_tooltip_manager.cpp @@ -15,40 +15,79 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Jacob Edwards <j.johan.edwards@gmail.com> + * Andrea Azzarone <andrea.azzarone@gmail.com> */ -#include <gtest/gtest.h> +#include <gmock/gmock.h> using namespace testing; #include "launcher/TooltipManager.h" #include "launcher/MockLauncherIcon.h" +using unity::launcher::MockLauncherIcon; +using unity::launcher::TooltipManager; + #include "test_utils.h" -namespace unity -{ -namespace launcher +namespace { -namespace +bool CheckIsTooltipVisible(nux::ObjectPtr<MockLauncherIcon> const& icon, bool value) { + return icon->IsTooltipVisible() == value; +} + +struct TestTooltipManager : public Test { + TooltipManager tooltip_manager; +}; + +TEST_F(TestTooltipManager, MouseMoved) { + nux::ObjectPtr<MockLauncherIcon> icon1(new MockLauncherIcon()); + nux::ObjectPtr<MockLauncherIcon> icon2(new MockLauncherIcon()); + + tooltip_manager.MouseMoved(icon1); + ASSERT_FALSE(icon1->IsTooltipVisible()); // don't skip the timeout! + Utils::WaitUntil(std::bind(CheckIsTooltipVisible, icon1, true)); + Utils::WaitUntil(std::bind(CheckIsTooltipVisible, icon2, false)); + + tooltip_manager.MouseMoved(icon2); + ASSERT_FALSE(icon1->IsTooltipVisible()); + ASSERT_TRUE(icon2->IsTooltipVisible()); + + tooltip_manager.MouseMoved(nux::ObjectPtr<MockLauncherIcon>()); + ASSERT_FALSE(icon1->IsTooltipVisible()); + ASSERT_FALSE(icon2->IsTooltipVisible()); -TEST(TestTooltipManager, TestHideAndShowTooltip) + tooltip_manager.MouseMoved(icon1); + ASSERT_TRUE(icon1->IsTooltipVisible()); + ASSERT_FALSE(icon2->IsTooltipVisible()); +} + +TEST_F(TestTooltipManager, IconClicked) { - // Makes sure that TooltipManager calls icon->ShowTooltip() when the mouse - // hovers it, and icon->HideTooltip() after the mouse dehovers it. - TooltipManager tm; - MockLauncherIcon* icon = new MockLauncherIcon(); - - tm.SetIcon(AbstractLauncherIcon::Ptr(icon)); - tm.MouseMoved(); - Utils::WaitForTimeoutMSec(1050); - - EXPECT_TRUE(icon->IsTooltipVisible()); - tm.SetIcon(AbstractLauncherIcon::Ptr()); - EXPECT_FALSE(icon->IsTooltipVisible()); + nux::ObjectPtr<MockLauncherIcon> icon(new MockLauncherIcon()); + + tooltip_manager.MouseMoved(icon); + ASSERT_FALSE(icon->IsTooltipVisible()); // don't skip the timeout! + Utils::WaitUntil(std::bind(CheckIsTooltipVisible, icon, true)); + + tooltip_manager.IconClicked(); + ASSERT_FALSE(icon->IsTooltipVisible()); } +TEST_F(TestTooltipManager, SetHover) +{ + nux::ObjectPtr<MockLauncherIcon> icon(new MockLauncherIcon()); + + tooltip_manager.MouseMoved(icon); + ASSERT_FALSE(icon->IsTooltipVisible()); // don't skip the timeout! + Utils::WaitUntil(std::bind(CheckIsTooltipVisible, icon, true)); + + tooltip_manager.SetHover(false); + ASSERT_FALSE(icon->IsTooltipVisible()); + + tooltip_manager.MouseMoved(icon); + ASSERT_FALSE(icon->IsTooltipVisible()); // don't skip the timeout! + Utils::WaitUntil(std::bind(CheckIsTooltipVisible, icon, true)); } -} // launcher -} // unity +} diff --git a/unity-shared/CoverArt.cpp b/unity-shared/CoverArt.cpp index 97375a6c2..23ef8ce44 100644 --- a/unity-shared/CoverArt.cpp +++ b/unity-shared/CoverArt.cpp @@ -20,6 +20,7 @@ * Nick Dedekind <nick.dedekind@canonical.com> * */ +#include "config.h" #include "CoverArt.h" #include "unity-shared/IntrospectableWrappers.h" @@ -29,6 +30,7 @@ #include "DashStyle.h" #include "IconLoader.h" #include "PreviewStyle.h" +#include <glib/gi18n-lib.h> namespace unity { @@ -83,7 +85,8 @@ void CoverArt::AddProperties(GVariantBuilder* builder) variant::BuilderWrapper(builder) .add(GetAbsoluteGeometry()) .add("image-hint", image_hint_) - .add("waiting", waiting_); + .add("waiting", waiting_) + .add("overlay-text", overlay_text_->GetText()); } void CoverArt::SetImage(std::string const& image_hint) @@ -446,7 +449,7 @@ void CoverArt::SetupViews() overlay_text_->SetTextAlignment(StaticCairoText::NUX_ALIGN_CENTRE); overlay_text_->SetFont("Ubuntu 14"); overlay_text_->SetLines(-3); - overlay_text_->SetText("No Image Available"); + overlay_text_->SetText(_("No Image Available")); dash::Style& style = dash::Style::Instance(); spin_ = style.GetSearchSpinIcon(); diff --git a/unity-shared/IconRenderer.cpp b/unity-shared/IconRenderer.cpp index 39153795b..da8c2b868 100644 --- a/unity-shared/IconRenderer.cpp +++ b/unity-shared/IconRenderer.cpp @@ -25,7 +25,9 @@ #include <NuxGraphics/GpuDevice.h> #include <NuxGraphics/GLTextureResourceManager.h> +#include <UnityCore/GLibWrapper.h> #include <NuxGraphics/CairoGraphics.h> +#include "unity-shared/CairoTexture.h" #include "GraphicsUtils.h" #include <gtk/gtk.h> @@ -39,6 +41,8 @@ namespace unity { namespace ui { +namespace +{ #ifdef USE_GLES #define VertexShaderHeader "#version 100\n" @@ -171,6 +175,7 @@ LRP temp, factor.x, color, desat; \n\ MUL result.color.rgb, temp, colorify_color; \n\ MOV result.color.a, color; \n\ END"); +} // anonymous namespace // The local namespace is purely for namespacing the file local variables below. namespace local @@ -181,58 +186,83 @@ enum IconSize { SMALL = 0, BIG, - LAST, + SIZE, }; +} // anonymous namespace +} // local namespace + +struct IconRenderer::TexturesPool +{ + static std::shared_ptr<TexturesPool> Get() + { + static std::shared_ptr<TexturesPool> instance(new TexturesPool()); + return instance; + } -bool textures_created = false; -nux::BaseTexture* progress_bar_trough = 0; -nux::BaseTexture* progress_bar_fill = 0; -nux::BaseTexture* pip_ltr = 0; -nux::BaseTexture* pip_rtl = 0; -nux::BaseTexture* arrow_ltr = 0; -nux::BaseTexture* arrow_rtl = 0; -nux::BaseTexture* arrow_empty_ltr = 0; -nux::BaseTexture* arrow_empty_rtl = 0; - -// nux::BaseTexture* squircle_base = 0; -// nux::BaseTexture* squircle_base_selected = 0; -// nux::BaseTexture* squircle_edge = 0; -// nux::BaseTexture* squircle_glow = 0; -// nux::BaseTexture* squircle_shadow = 0; -// nux::BaseTexture* squircle_shine = 0; - -std::vector<nux::BaseTexture*> icon_background; -std::vector<nux::BaseTexture*> icon_selected_background; -std::vector<nux::BaseTexture*> icon_edge; -std::vector<nux::BaseTexture*> icon_glow; -std::vector<nux::BaseTexture*> icon_shadow; -std::vector<nux::BaseTexture*> icon_shine; -nux::ObjectPtr<nux::IOpenGLBaseTexture> offscreen_progress_texture; -nux::ObjectPtr<nux::IOpenGLShaderProgram> shader_program_uv_persp_correction; + nux::ObjectPtr<nux::BaseTexture> RenderLabelTexture(char label, int icon_size, nux::Color const& bg_color); + + BaseTexturePtr progress_bar_trough; + BaseTexturePtr progress_bar_fill; + BaseTexturePtr pip_ltr; + BaseTexturePtr large_pip_ltr; + // BaseTexturePtr pip_rtl; + // BaseTexturePtr large_pip_rtl; + BaseTexturePtr arrow_ltr; + BaseTexturePtr arrow_rtl; + BaseTexturePtr arrow_empty_ltr; + // BaseTexturePtr arrow_empty_rtl; + + // BaseTexturePtr squircle_base; + // BaseTexturePtr squircle_base_selected; + // BaseTexturePtr squircle_edge; + // BaseTexturePtr squircle_glow; + // BaseTexturePtr squircle_shadow; + // BaseTexturePtr squircle_shine; + + BaseTexturePtr icon_background[local::IconSize::SIZE]; + BaseTexturePtr icon_selected_background[local::IconSize::SIZE]; + BaseTexturePtr icon_edge[local::IconSize::SIZE]; + BaseTexturePtr icon_glow[local::IconSize::SIZE]; + BaseTexturePtr icon_shadow[local::IconSize::SIZE]; + BaseTexturePtr icon_shine[local::IconSize::SIZE]; + + nux::ObjectPtr<nux::IOpenGLBaseTexture> offscreen_progress_texture; + nux::ObjectPtr<nux::IOpenGLShaderProgram> shader_program_uv_persp_correction; #ifndef USE_GLES -nux::ObjectPtr<nux::IOpenGLAsmShaderProgram> asm_shader; + nux::ObjectPtr<nux::IOpenGLAsmShaderProgram> asm_shader; #endif -std::map<char, nux::BaseTexture*> label_map; -void generate_textures(); -void destroy_textures(); -} -} + std::map<char, BaseTexturePtr> labels; + +private: + TexturesPool(); + + inline void LoadTexture(BaseTexturePtr &texture_ptr, std::string const& filename) + { + texture_ptr.Adopt(nux::CreateTexture2DFromFile(filename.c_str(), -1, true)); + } + + inline void GenerateTextures(BaseTexturePtr (&texture)[local::IconSize::SIZE], + std::string const& big_file, std::string const& small_file) + { + LoadTexture(texture[local::IconSize::SMALL], small_file); + LoadTexture(texture[local::IconSize::BIG], big_file); + } + + void SetupShaders(); +}; IconRenderer::IconRenderer() : icon_size(0) , image_size(0) , spacing(0) + , textures_(TexturesPool::Get()) { pip_style = OUTSIDE_TILE; - - if (!local::textures_created) - local::generate_textures(); } IconRenderer::~IconRenderer() -{ -} +{} void IconRenderer::SetTargetSize(int tile_size, int image_size_, int spacing_) { @@ -248,7 +278,7 @@ void IconRenderer::PreprocessIcons(std::list<RenderArg>& args, nux::Geometry con nux::Matrix4 ProjectionMatrix; nux::Matrix4 ViewProjectionMatrix; - _stored_projection_matrix = nux::GetWindowThread()->GetGraphicsEngine().GetOpenGLModelViewProjectionMatrix(); + stored_projection_matrix_ = nux::GetWindowThread()->GetGraphicsEngine().GetOpenGLModelViewProjectionMatrix(); GetInverseScreenPerspectiveMatrix(ViewMatrix, ProjectionMatrix, geo.width, geo.height, 0.1f, 1000.0f, DEGTORAD(90)); @@ -404,19 +434,20 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& nux::Color background_tile_color = arg.icon->BackgroundColor(); nux::Color glow_color = arg.icon->GlowColor(); - nux::Color edge_color(0x55555555); + nux::Color edge_color = nux::color::White; nux::Color colorify = arg.colorify; nux::Color background_tile_colorify = arg.colorify; + nux::Color edge_tile_colorify = nux::color::White; bool colorify_background = arg.colorify_background; float backlight_intensity = arg.backlight_intensity; float glow_intensity = arg.glow_intensity; float shadow_intensity = 0.6f; - nux::BaseTexture* background = local::icon_background[size]; - nux::BaseTexture* edge = local::icon_edge[size]; - nux::BaseTexture* glow = local::icon_glow[size]; - nux::BaseTexture* shine = local::icon_shine[size]; - nux::BaseTexture* shadow = local::icon_shadow[size]; + BaseTexturePtr background = textures_->icon_background[size]; + BaseTexturePtr const& edge = textures_->icon_edge[size]; + BaseTexturePtr const& glow = textures_->icon_glow[size]; + BaseTexturePtr const& shine = textures_->icon_shine[size]; + BaseTexturePtr const& shadow = textures_->icon_shadow[size]; nux::Color shortcut_color = arg.colorify; @@ -445,7 +476,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& glow_intensity = 1.0f; shadow_intensity = 0.0f; - background = local::icon_selected_background[size]; + background = textures_->icon_selected_background[size]; } else { @@ -477,8 +508,6 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& { nux::Color shadow_color = background_tile_colorify * 0.3f; - // FIXME it is using the same transformation of the glow, - // should have its own transformation. RenderElement(GfxContext, arg, shadow->GetDeviceTexture(), @@ -502,10 +531,9 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& backlight_intensity * arg.alpha, force_filter, tile_transform); - } - edge_color = edge_color + ((background_tile_color - edge_color) * backlight_intensity); - nux::Color edge_tile_colorify = background_tile_colorify; + edge_color = edge_color + ((background_tile_color - edge_color) * backlight_intensity); + } if (colorify_background && !arg.keyboard_nav_hl) { @@ -575,7 +603,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& RenderElement(GfxContext, arg, - local::icon_glow[size]->GetDeviceTexture(), + textures_->icon_glow[size]->GetDeviceTexture(), arg.icon->GlowColor(), nux::color::White, fade_out * arg.alpha, @@ -588,17 +616,17 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& // draw progress bar if (arg.progress_bias > -1.0f && arg.progress_bias < 1.0f) { - if (local::offscreen_progress_texture->GetWidth() != icon_size || - local::offscreen_progress_texture->GetHeight() != icon_size) + if (textures_->offscreen_progress_texture->GetWidth() != icon_size || + textures_->offscreen_progress_texture->GetHeight() != icon_size) { - local::offscreen_progress_texture = nux::GetGraphicsDisplay()->GetGpuDevice() + textures_->offscreen_progress_texture = nux::GetGraphicsDisplay()->GetGpuDevice() ->CreateSystemCapableDeviceTexture(icon_size, icon_size, 1, nux::BITFMT_R8G8B8A8); } - RenderProgressToTexture(GfxContext, local::offscreen_progress_texture, arg.progress, arg.progress_bias); + RenderProgressToTexture(GfxContext, textures_->offscreen_progress_texture, arg.progress, arg.progress_bias); RenderElement(GfxContext, arg, - local::offscreen_progress_texture, + textures_->offscreen_progress_texture, nux::color::White, nux::color::White, arg.alpha, @@ -631,12 +659,22 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& { char shortcut = (char) arg.shortcut_label; - if (local::label_map.find(shortcut) == local::label_map.end()) - local::label_map[shortcut] = RenderCharToTexture(shortcut, icon_size, icon_size, shortcut_color); + BaseTexturePtr label; + auto label_it = textures_->labels.find(shortcut); + + if (label_it != textures_->labels.end()) + { + label = label_it->second; + } + else + { + label = textures_->RenderLabelTexture(shortcut, icon_size, shortcut_color); + textures_->labels[shortcut] = label; + } RenderElement(GfxContext, arg, - local::label_map[shortcut]->GetDeviceTexture(), + label->GetDeviceTexture(), nux::Color(0xFFFFFFFF), nux::color::White, arg.alpha, @@ -645,23 +683,19 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& } } -nux::BaseTexture* IconRenderer::RenderCharToTexture(char label, int width, int height, nux::Color const& bg_color) +nux::ObjectPtr<nux::BaseTexture> IconRenderer::TexturesPool::RenderLabelTexture(char label, int icon_size, nux::Color const& bg_color) { - nux::BaseTexture* texture = NULL; - nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, width, height); - cairo_t* cr = cg.GetInternalContext(); - PangoLayout* layout = NULL; - PangoFontDescription* desc = NULL; - GtkSettings* settings = gtk_settings_get_default(); // not ref'ed - gchar* fontName = NULL; - - double label_ratio = 0.44f; - double label_size = icon_size * label_ratio; - double label_x = (icon_size - label_size) / 2; - double label_y = (icon_size - label_size) / 2; - double label_w = label_size; - double label_h = label_size; - double label_radius = 3.0f; + nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, icon_size, icon_size); + cairo_t* cr = cg.GetInternalContext(); + glib::String font_name; + + const double label_ratio = 0.44f; + const double label_size = icon_size * label_ratio; + const double label_x = (icon_size - label_size) / 2.0f; + const double label_y = (icon_size - label_size) / 2.0f; + const double label_w = label_size; + const double label_h = label_size; + const double label_radius = 3.0f; cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); @@ -673,35 +707,27 @@ nux::BaseTexture* IconRenderer::RenderCharToTexture(char label, int width, int h cairo_set_source_rgba(cr, bg_color.red, bg_color.green, bg_color.blue, 0.20f); cairo_fill(cr); - double text_ratio = 0.75; - double text_size = label_size * text_ratio; - layout = pango_cairo_create_layout(cr); - g_object_get(settings, "gtk-font-name", &fontName, NULL); - desc = pango_font_description_from_string(fontName); - pango_font_description_set_absolute_size(desc, text_size * PANGO_SCALE); - pango_layout_set_font_description(layout, desc); + const double text_ratio = 0.75; + double text_size = label_size * text_ratio; + glib::Object<PangoLayout> layout(pango_cairo_create_layout(cr)); + g_object_get(gtk_settings_get_default(), "gtk-font-name", &font_name, NULL); + std::shared_ptr<PangoFontDescription> desc(pango_font_description_from_string(font_name), + pango_font_description_free); + pango_font_description_set_absolute_size(desc.get(), text_size * PANGO_SCALE); + pango_layout_set_font_description(layout, desc.get()); pango_layout_set_text(layout, &label, 1); - PangoRectangle logRect; - PangoRectangle inkRect; - pango_layout_get_extents(layout, &inkRect, &logRect); + nux::Size extents; + pango_layout_get_pixel_size(layout, &extents.width, &extents.height); // position and paint text cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f); - double x = label_x - ((logRect.width / PANGO_SCALE) - label_w) / 2.0f; - double y = label_y - ((logRect.height / PANGO_SCALE) - label_h) / 2.0f - 1; + double x = label_x - std::round((extents.width - label_w) / 2.0f); + double y = label_y - std::round((extents.height - label_h) / 2.0f); cairo_move_to(cr, x, y); pango_cairo_show_layout(cr, layout); - nux::NBitmapData* bitmap = cg.GetBitmap(); - texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture(); - texture->Update(bitmap); - delete bitmap; - g_object_unref(layout); - pango_font_description_free(desc); - g_free(fontName); - - return texture; + return texture_ptr_from_cairo_graphics(cg); } void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, @@ -783,28 +809,28 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, if (nux::GetWindowThread()->GetGraphicsEngine().UsingGLSLCodePath()) { - local::shader_program_uv_persp_correction->Begin(); + textures_->shader_program_uv_persp_correction->Begin(); - int TextureObjectLocation = local::shader_program_uv_persp_correction->GetUniformLocationARB("TextureObject0"); - VertexLocation = local::shader_program_uv_persp_correction->GetAttributeLocation("iVertex"); - TextureCoord0Location = local::shader_program_uv_persp_correction->GetAttributeLocation("iTexCoord0"); - FragmentColor = local::shader_program_uv_persp_correction->GetUniformLocationARB("color0"); - ColorifyColor = local::shader_program_uv_persp_correction->GetUniformLocationARB("colorify_color"); - DesatFactor = local::shader_program_uv_persp_correction->GetUniformLocationARB("desat_factor"); + int TextureObjectLocation = textures_->shader_program_uv_persp_correction->GetUniformLocationARB("TextureObject0"); + VertexLocation = textures_->shader_program_uv_persp_correction->GetAttributeLocation("iVertex"); + TextureCoord0Location = textures_->shader_program_uv_persp_correction->GetAttributeLocation("iTexCoord0"); + FragmentColor = textures_->shader_program_uv_persp_correction->GetUniformLocationARB("color0"); + ColorifyColor = textures_->shader_program_uv_persp_correction->GetUniformLocationARB("colorify_color"); + DesatFactor = textures_->shader_program_uv_persp_correction->GetUniformLocationARB("desat_factor"); if (TextureObjectLocation != -1) CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); - int VPMatrixLocation = local::shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix"); + int VPMatrixLocation = textures_->shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix"); if (VPMatrixLocation != -1) { - local::shader_program_uv_persp_correction->SetUniformLocMatrix4fv((GLint)VPMatrixLocation, 1, false, (GLfloat*) & (_stored_projection_matrix.m)); + textures_->shader_program_uv_persp_correction->SetUniformLocMatrix4fv((GLint)VPMatrixLocation, 1, false, (GLfloat*) & (stored_projection_matrix_.m)); } } #ifndef USE_GLES else { - local::asm_shader->Begin(); + textures_->asm_shader->Begin(); VertexLocation = nux::VTXATTRIB_POSITION; TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0; @@ -866,12 +892,12 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, if (nux::GetWindowThread()->GetGraphicsEngine().UsingGLSLCodePath()) { - local::shader_program_uv_persp_correction->End(); + textures_->shader_program_uv_persp_correction->End(); } else { #ifndef USE_GLES - local::asm_shader->End(); + textures_->asm_shader->End(); #endif } } @@ -890,8 +916,8 @@ void IconRenderer::RenderIndicators(nux::GraphicsEngine& GfxContext, if (running > 0) { int scale = 1; - int markerX; + if (pip_style == OUTSIDE_TILE) { markerX = geo.x; @@ -899,8 +925,7 @@ void IconRenderer::RenderIndicators(nux::GraphicsEngine& GfxContext, else { auto bounds = arg.icon->GetTransform(ui::IconTextureSource::TRANSFORM_TILE, monitor); - markerX = bounds[0].x + 2; - scale = 2; + markerX = bounds[0].x + 1; } nux::TexCoordXForm texxform; @@ -914,46 +939,66 @@ void IconRenderer::RenderIndicators(nux::GraphicsEngine& GfxContext, color = color * alpha; - nux::BaseTexture* texture; + BaseTexturePtr texture; // markers are well outside screen bounds to start int markers [3] = {-100, -100, -100}; if (!arg.running_on_viewport) { + scale = (pip_style == OUTSIDE_TILE) ? 1 : 2; markers[0] = markerCenter; - texture = local::arrow_empty_ltr; + texture = textures_->arrow_empty_ltr; } else if (running == 1) { + scale = (pip_style == OUTSIDE_TILE) ? 1 : 2; markers[0] = markerCenter; - texture = local::arrow_ltr; + texture = textures_->arrow_ltr; } else if (running == 2) { - markers[0] = markerCenter - 2 * scale; - markers[1] = markerCenter + 2 * scale; - texture = local::pip_ltr; + if (pip_style == OUTSIDE_TILE) + { + texture = textures_->pip_ltr; + markers[0] = markerCenter - 2; + markers[1] = markerCenter + 2; + } + else + { + texture = textures_->large_pip_ltr; + markers[0] = markerCenter - 4; + markers[1] = markerCenter + 4; + } } else { - markers[0] = markerCenter - 4 * scale; - markers[1] = markerCenter; - markers[2] = markerCenter + 4 * scale; - texture = local::pip_ltr; + if (pip_style == OUTSIDE_TILE) + { + texture = textures_->pip_ltr; + markers[0] = markerCenter - 4; + markers[1] = markerCenter; + markers[2] = markerCenter + 4; + } + else + { + texture = textures_->large_pip_ltr; + markers[0] = markerCenter - 8; + markers[1] = markerCenter; + markers[2] = markerCenter + 8; + } } - for (int i = 0; i < 3; i++) { int center = markers[i]; if (center == -100) break; - + GfxContext.QRP_1Tex(markerX, - center - ((texture->GetHeight() * scale) / 2) - 1, - (float) texture->GetWidth() * scale, - (float) texture->GetHeight() * scale, + center - std::round((texture->GetHeight() * scale) / 2.0f), + texture->GetWidth() * scale, + texture->GetHeight() * scale, texture->GetDeviceTexture(), texxform, color); @@ -965,11 +1010,11 @@ void IconRenderer::RenderIndicators(nux::GraphicsEngine& GfxContext, nux::TexCoordXForm texxform; nux::Color color = nux::color::LightGrey * alpha; - GfxContext.QRP_1Tex((geo.x + geo.width) - local::arrow_rtl->GetWidth(), - markerCenter - (local::arrow_rtl->GetHeight() / 2) - 1, - (float) local::arrow_rtl->GetWidth(), - (float) local::arrow_rtl->GetHeight(), - local::arrow_rtl->GetDeviceTexture(), + GfxContext.QRP_1Tex((geo.x + geo.width) - textures_->arrow_rtl->GetWidth(), + markerCenter - std::round(textures_->arrow_rtl->GetHeight() / 2.0f), + textures_->arrow_rtl->GetWidth(), + textures_->arrow_rtl->GetHeight(), + textures_->arrow_rtl->GetDeviceTexture(), texxform, color); } @@ -984,10 +1029,10 @@ void IconRenderer::RenderProgressToTexture(nux::GraphicsEngine& GfxContext, int height = texture->GetHeight(); int progress_width = icon_size; - int progress_height = local::progress_bar_trough->GetHeight(); + int progress_height = textures_->progress_bar_trough->GetHeight(); int fill_width = image_size - (icon_size - image_size); - int fill_height = local::progress_bar_fill->GetHeight(); + int fill_height = textures_->progress_bar_fill->GetHeight(); int fill_offset = (progress_width - fill_width) / 2; @@ -1022,10 +1067,10 @@ void IconRenderer::RenderProgressToTexture(nux::GraphicsEngine& GfxContext, // left door GfxContext.PushClippingRectangle(nux::Geometry(left_edge, 0, half_size, height)); GfxContext.QRP_1Tex(left_edge, progress_y, progress_width, progress_height, - local::progress_bar_trough->GetDeviceTexture(), texxform, + textures_->progress_bar_trough->GetDeviceTexture(), texxform, nux::color::White); GfxContext.QRP_1Tex(left_edge + fill_offset, fill_y, fill_width, fill_height, - local::progress_bar_fill->GetDeviceTexture(), texxform, + textures_->progress_bar_fill->GetDeviceTexture(), texxform, nux::color::White); GfxContext.PopClippingRectangle(); @@ -1033,11 +1078,11 @@ void IconRenderer::RenderProgressToTexture(nux::GraphicsEngine& GfxContext, GfxContext.PushClippingRectangle(nux::Geometry(left_edge + half_size, 0, half_size, height)); GfxContext.QRP_1Tex(right_edge - progress_width, progress_y, progress_width, progress_height, - local::progress_bar_trough->GetDeviceTexture(), texxform, + textures_->progress_bar_trough->GetDeviceTexture(), texxform, nux::color::White); GfxContext.QRP_1Tex(right_edge - progress_width + fill_offset, fill_y, fill_width, fill_height, - local::progress_bar_fill->GetDeviceTexture(), texxform, + textures_->progress_bar_fill->GetDeviceTexture(), texxform, nux::color::White); GfxContext.PopClippingRectangle(); @@ -1045,16 +1090,9 @@ void IconRenderer::RenderProgressToTexture(nux::GraphicsEngine& GfxContext, unity::graphics::PopOffscreenRenderTarget(); } -void IconRenderer::DestroyTextures() -{ - local::destroy_textures(); -} - void IconRenderer::DestroyShortcutTextures() { - for (auto texture : local::label_map) - texture.second->UnReference(); - local::label_map.clear(); + TexturesPool::Get()->labels.clear(); } void IconRenderer::GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix, @@ -1142,12 +1180,57 @@ void IconRenderer::GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, n PerspectiveMatrix.Perspective(Fovy, AspectRatio, NearClipPlane, FarClipPlane); } -// The local namespace is purely for namespacing the file local variables below. -namespace local +IconRenderer::TexturesPool::TexturesPool() + : offscreen_progress_texture(nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(2, 2, 1, nux::BITFMT_R8G8B8A8)) { -namespace -{ -void setup_shaders() + LoadTexture(progress_bar_trough, PKGDATADIR"/progress_bar_trough.png"); + LoadTexture(progress_bar_fill, PKGDATADIR"/progress_bar_fill.png"); + LoadTexture(pip_ltr, PKGDATADIR"/launcher_pip_ltr.png"); + LoadTexture(large_pip_ltr, PKGDATADIR"/launcher_pip_large_ltr.png"); + // LoadTexture(pip_rtl, PKGDATADIR"/launcher_pip_rtl.png"); + // LoadTexture(large_pip_rtl, PKGDATADIR"/launcher_pip_large_rtl.png"); + LoadTexture(arrow_ltr, PKGDATADIR"/launcher_arrow_ltr.png"); + LoadTexture(arrow_rtl, PKGDATADIR"/launcher_arrow_rtl.png"); + LoadTexture(arrow_empty_ltr, PKGDATADIR"/launcher_arrow_outline_ltr.png"); + // LoadTexture(arrow_empty_rtl, PKGDATADIR"/launcher_arrow_outline_rtl.png"); + + // LoadTexture(squircle_base, PKGDATADIR"/squircle_base_54.png"); + // LoadTexture(squircle_base_selected, PKGDATADIR"/squircle_base_selected_54.png"); + // LoadTexture(squircle_edge, PKGDATADIR"/squircle_edge_54.png"); + // LoadTexture(squircle_glow, PKGDATADIR"/squircle_glow_62.png"); + // LoadTexture(squircle_shadow, PKGDATADIR"/squircle_shadow_62.png"); + // LoadTexture(squircle_shine, PKGDATADIR"/squircle_shine_54.png"); + + // BaseTexturePtr icon_background[local::IconSize::SIZE]; + // BaseTexturePtr icon_selected_background[local::IconSize::SIZE]; + // BaseTexturePtr icon_edge[local::IconSize::SIZE]; + // BaseTexturePtr icon_glow[local::IconSize::SIZE]; + // BaseTexturePtr icon_shadow[local::IconSize::SIZE]; + // BaseTexturePtr icon_shine[local::IconSize::SIZE]; + + GenerateTextures(icon_background, + PKGDATADIR"/launcher_icon_back_150.png", + PKGDATADIR"/launcher_icon_back_54.png"); + GenerateTextures(icon_selected_background, + PKGDATADIR"/launcher_icon_selected_back_150.png", + PKGDATADIR"/launcher_icon_back_54.png"); + GenerateTextures(icon_edge, + PKGDATADIR"/launcher_icon_edge_150.png", + PKGDATADIR"/launcher_icon_edge_54.png"); + GenerateTextures(icon_glow, + PKGDATADIR"/launcher_icon_glow_200.png", + PKGDATADIR"/launcher_icon_glow_62.png"); + GenerateTextures(icon_shadow, + PKGDATADIR"/launcher_icon_shadow_200.png", + PKGDATADIR"/launcher_icon_shadow_62.png"); + GenerateTextures(icon_shine, + PKGDATADIR"/launcher_icon_shine_150.png", + PKGDATADIR"/launcher_icon_shine_54.png"); + + SetupShaders(); +} + +void IconRenderer::TexturesPool::SetupShaders() { if (nux::GetWindowThread()->GetGraphicsEngine().UsingGLSLCodePath()) { @@ -1178,107 +1261,5 @@ void setup_shaders() } } - -inline nux::BaseTexture* load_texture(const char* filename) -{ - return nux::CreateTexture2DFromFile(filename, -1, true); -} - -void generate_textures(std::vector<nux::BaseTexture*>& icons, const char* big_file, const char* small_file) -{ - icons.resize(IconSize::LAST); - icons[IconSize::BIG] = load_texture(big_file); - icons[IconSize::SMALL] = load_texture(small_file); -} - -void generate_textures() -{ - progress_bar_trough = load_texture(PKGDATADIR"/progress_bar_trough.png"); - progress_bar_fill = load_texture(PKGDATADIR"/progress_bar_fill.png"); - - generate_textures(icon_background, - PKGDATADIR"/launcher_icon_back_150.png", - PKGDATADIR"/launcher_icon_back_54.png"); - generate_textures(icon_selected_background, - PKGDATADIR"/launcher_icon_selected_back_150.png", - PKGDATADIR"/launcher_icon_back_54.png"); - generate_textures(icon_edge, - PKGDATADIR"/launcher_icon_edge_150.png", - PKGDATADIR"/launcher_icon_edge_54.png"); - generate_textures(icon_glow, - PKGDATADIR"/launcher_icon_glow_200.png", - PKGDATADIR"/launcher_icon_glow_62.png"); - generate_textures(icon_shadow, - PKGDATADIR"/launcher_icon_shadow_200.png", - PKGDATADIR"/launcher_icon_shadow_62.png"); - generate_textures(icon_shine, - PKGDATADIR"/launcher_icon_shine_150.png", - PKGDATADIR"/launcher_icon_shine_54.png"); - - // squircle_base = load_texture(PKGDATADIR"/squircle_base_54.png"); - // squircle_base_selected = load_texture(PKGDATADIR"/squircle_base_selected_54.png"); - // squircle_edge = load_texture(PKGDATADIR"/squircle_edge_54.png"); - // squircle_glow = load_texture(PKGDATADIR"/squircle_glow_62.png"); - // squircle_shadow = load_texture(PKGDATADIR"/squircle_shadow_62.png"); - // squircle_shine = load_texture(PKGDATADIR"/squircle_shine_54.png"); - - pip_ltr = load_texture(PKGDATADIR"/launcher_pip_ltr.png"); - arrow_ltr = load_texture(PKGDATADIR"/launcher_arrow_ltr.png"); - arrow_empty_ltr = load_texture(PKGDATADIR"/launcher_arrow_outline_ltr.png"); - - pip_rtl = load_texture(PKGDATADIR"/launcher_pip_rtl.png"); - arrow_rtl = load_texture(PKGDATADIR"/launcher_arrow_rtl.png"); - arrow_empty_rtl = load_texture(PKGDATADIR"/launcher_arrow_outline_rtl.png"); - - offscreen_progress_texture = nux::GetGraphicsDisplay()->GetGpuDevice() - ->CreateSystemCapableDeviceTexture(2, 2, 1, nux::BITFMT_R8G8B8A8); - - setup_shaders(); - textures_created = true; -} - -void destroy_textures(std::vector<nux::BaseTexture*>& icons) -{ - icons[SMALL]->UnReference(); - icons[BIG]->UnReference(); - icons.clear(); -} - -void destroy_textures() -{ - if (!textures_created) - return; - - progress_bar_trough->UnReference(); - progress_bar_fill->UnReference(); - pip_ltr->UnReference(); - pip_rtl->UnReference(); - arrow_ltr->UnReference(); - arrow_rtl->UnReference(); - arrow_empty_ltr->UnReference(); - arrow_empty_rtl->UnReference(); - - destroy_textures(icon_background); - destroy_textures(icon_selected_background); - destroy_textures(icon_edge); - destroy_textures(icon_glow); - destroy_textures(icon_shadow); - destroy_textures(icon_shine); - - // squircle_base->UnReference(); - // squircle_base_selected->UnReference(); - // squircle_edge->UnReference(); - // squircle_glow->UnReference(); - // squircle_shadow->UnReference(); - // squircle_shine->UnReference(); - - IconRenderer::DestroyShortcutTextures(); - - textures_created = false; -} - -} // anon namespace -} // namespace local - } // namespace ui } // namespace unity diff --git a/unity-shared/IconRenderer.h b/unity-shared/IconRenderer.h index e3e458bb5..00b5985d8 100644 --- a/unity-shared/IconRenderer.h +++ b/unity-shared/IconRenderer.h @@ -45,12 +45,9 @@ public: void SetTargetSize(int tile_size, int image_size, int spacing); - static void DestroyTextures(); static void DestroyShortcutTextures(); protected: - nux::BaseTexture* RenderCharToTexture(char label, int width, int height, nux::Color const& bg_color); - void RenderElement(nux::GraphicsEngine& GfxContext, RenderArg const& arg, nux::ObjectPtr<nux::IOpenGLBaseTexture> const& icon, @@ -90,7 +87,9 @@ private: int image_size; int spacing; - nux::Matrix4 _stored_projection_matrix; + struct TexturesPool; + std::shared_ptr<TexturesPool> textures_; + nux::Matrix4 stored_projection_matrix_; }; } diff --git a/unity-shared/SearchBar.cpp b/unity-shared/SearchBar.cpp index bb6b8c15f..80e850457 100644 --- a/unity-shared/SearchBar.cpp +++ b/unity-shared/SearchBar.cpp @@ -187,7 +187,7 @@ void SearchBar::Init() show_filters_->SetFont(SHOW_FILTERS_LABEL_DEFAULT_FONT.c_str()); show_filters_->SetTextColor(nux::color::White); show_filters_->SetTextAlignment(StaticCairoText::NUX_ALIGN_RIGHT); - show_filters_->SetLines(1); + show_filters_->SetLines(-1); nux::BaseTexture* arrow; arrow = style.GetGroupExpandIcon(); diff --git a/unity-shared/SearchBar.h b/unity-shared/SearchBar.h index 8095f8348..5b502ffb7 100644 --- a/unity-shared/SearchBar.h +++ b/unity-shared/SearchBar.h @@ -68,7 +68,6 @@ public: sigc::signal<void, std::string const&> live_search_reached; private: - void Init(); void OnFontChanged(GtkSettings* settings, GParamSpec* pspec=NULL); diff --git a/unity-shared/StaticCairoText.cpp b/unity-shared/StaticCairoText.cpp index 7def057c8..e1e0de781 100644 --- a/unity-shared/StaticCairoText.cpp +++ b/unity-shared/StaticCairoText.cpp @@ -67,6 +67,8 @@ struct StaticCairoText::Impl std::shared_ptr<CairoGraphics> cr; }; + + void UpdateBaseSize(); Size GetTextExtents() const; void SetAttributes(PangoLayout* layout); @@ -92,7 +94,7 @@ struct StaticCairoText::Impl EllipsizeState ellipsize_; AlignState align_; AlignState valign_; - UnderlineState underline_; + UnderlineState underline_; std::string font_; @@ -114,7 +116,7 @@ StaticCairoText::Impl::Impl(StaticCairoText* parent, std::string const& text) , text_color_(color::White) , ellipsize_(NUX_ELLIPSIZE_END) , align_(NUX_ALIGN_LEFT) - , valign_(NUX_ALIGN_TOP) + , valign_(NUX_ALIGN_CENTRE) , underline_(NUX_UNDERLINE_NONE) , lines_(-2) // should find out why -2... // the desired height of the layout in Pango units if positive, or desired @@ -173,7 +175,6 @@ StaticCairoText::StaticCairoText(std::string const& text, : View(NUX_FILE_LINE_PARAM) , pimpl(new Impl(this, text)) { - SetMinimumSize(1, 1); SetAcceptKeyNavFocusOnMouseDown(false); } @@ -182,7 +183,6 @@ StaticCairoText::StaticCairoText(std::string const& text, bool escape_text, : View(NUX_FILE_LINE_PARAM) , pimpl(new Impl(this, escape_text ? GetEscapedText(text) : text)) { - SetMinimumSize(1, 1); SetAcceptKeyNavFocusOnMouseDown(false); } @@ -226,17 +226,14 @@ void StaticCairoText::SetLineSpacing(float line_spacing) void StaticCairoText::PreLayoutManagement() { - Geometry geo = GetGeometry(); + Geometry const& geo = GetGeometry(); pimpl->pre_layout_size_.width = geo.width; pimpl->pre_layout_size_.height = geo.height; + pimpl->UpdateBaseSize(); - SetBaseSize(pimpl->cached_extent_.width, - pimpl->cached_extent_.height); if (pimpl->textures2D_.empty()) - { pimpl->UpdateTexture(); - } View::PreLayoutManagement(); } @@ -293,15 +290,28 @@ void StaticCairoText::Draw(GraphicsEngine& gfxContext, bool forceDraw) gfxContext.GetRenderStates().GetBlend(alpha, src, dest); gfxContext.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - Color col = color::Black; - col.alpha = 0; - gfxContext.QRP_Color(base.x, - base.y, - base.width, - base.height, - col); + gfxContext.QRP_Color(base.x, base.y, base.width, base.height, color::Transparent); + + int current_x = base.x; + int current_y = base.y; - int current_y = base.y + ((base.height - pimpl->cached_extent_.height) / 2); + if (pimpl->align_ == NUX_ALIGN_CENTRE) + { + current_x += std::round((base.width - pimpl->cached_extent_.width) / 2.0f); + } + else if (pimpl->align_ == NUX_ALIGN_RIGHT) + { + current_x += base.width - pimpl->cached_extent_.width; + } + + if (pimpl->valign_ == NUX_ALIGN_CENTRE) + { + current_y += std::round((base.height - pimpl->cached_extent_.height) / 2.0f); + } + else if (pimpl->valign_ == NUX_ALIGN_BOTTOM) + { + current_y += base.height - pimpl->cached_extent_.height; + } for (BaseTexturePtr tex : pimpl->textures2D_) { @@ -309,7 +319,7 @@ void StaticCairoText::Draw(GraphicsEngine& gfxContext, bool forceDraw) if (!text_tex) break; - gfxContext.QRP_1Tex(base.x, + gfxContext.QRP_1Tex(current_x, current_y, text_tex->GetWidth(), text_tex->GetHeight(), @@ -406,7 +416,7 @@ void StaticCairoText::SetTextColor(Color const& textColor) void StaticCairoText::SetFont(std::string const& font) { if (pimpl->font_ != font) - { + { pimpl->font_ = font; pimpl->need_new_extent_cache_ = true; Size s = GetTextExtents(); @@ -501,7 +511,8 @@ std::string StaticCairoText::GetName() const void StaticCairoText::AddProperties(GVariantBuilder* builder) { unity::variant::BuilderWrapper(builder) - .add(GetGeometry()); + .add(GetGeometry()) + .add("text", pimpl->text_); } std::string StaticCairoText::Impl::GetEffectiveFont() const @@ -524,8 +535,6 @@ Size StaticCairoText::Impl::GetTextExtents() const PangoLayout* layout = NULL; PangoFontDescription* desc = NULL; PangoContext* pangoCtx = NULL; - PangoRectangle inkRect = {0, 0, 0, 0}; - PangoRectangle logRect = {0, 0, 0, 0}; int dpi = 0; GdkScreen* screen = gdk_screen_get_default(); // is not ref'ed GtkSettings* settings = gtk_settings_get_default(); // is not ref'ed @@ -537,8 +546,7 @@ Size StaticCairoText::Impl::GetTextExtents() const Size result; std::string font = GetEffectiveFont(); - - int maxwidth = parent_->GetMaximumWidth(); + nux::Size layout_size(-1, lines_ < 0 ? lines_ : std::numeric_limits<int>::min()); surface = cairo_image_surface_create(CAIRO_FORMAT_A1, 1, 1); cr = cairo_create(surface); @@ -550,8 +558,8 @@ Size StaticCairoText::Impl::GetTextExtents() const pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_ellipsize(layout, GetPangoEllipsizeMode()); pango_layout_set_alignment(layout, GetPangoAlignment()); - pango_layout_set_height(layout, lines_); - pango_layout_set_width(layout, maxwidth * PANGO_SCALE); + pango_layout_set_width(layout, layout_size.width); + pango_layout_set_height(layout, layout_size.height); pango_layout_set_markup(layout, text_.c_str(), -1); pango_layout_set_spacing(layout, line_spacing_ * PANGO_SCALE); @@ -570,15 +578,15 @@ Size StaticCairoText::Impl::GetTextExtents() const (float) dpi / (float) PANGO_SCALE); } pango_layout_context_changed(layout); - pango_layout_get_extents(layout, &inkRect, &logRect); + pango_layout_get_pixel_size(layout, &result.width, &result.height); - // logRect has some issues using italic style - if (inkRect.x + inkRect.width > logRect.x + logRect.width) - result.width = std::ceil(static_cast<float>(inkRect.x + inkRect.width - logRect.x) / PANGO_SCALE); - else - result.width = std::ceil(static_cast<float>(logRect.width) / PANGO_SCALE); + if (result.width > parent_->GetMaximumWidth()) + { + pango_layout_set_width(layout, parent_->GetMaximumWidth() * PANGO_SCALE); + pango_layout_context_changed(layout); + pango_layout_get_pixel_size(layout, &result.width, &result.height); + } - result.height = std::ceil(static_cast<float>(logRect.height) / PANGO_SCALE); cached_extent_ = result; baseline_ = pango_layout_get_baseline(layout) / PANGO_SCALE; need_new_extent_cache_ = false; @@ -671,22 +679,8 @@ void StaticCairoText::Impl::DrawText(CacheTexture::Ptr const& texture) if (!texture) return; - nux::Size tex_size(parent_->GetMaximumWidth(), parent_->GetMaximumHeight()); - nux::Size layout_size(tex_size.width * PANGO_SCALE, tex_size.height * PANGO_SCALE); - - if (tex_size.width == nux::AREA_MAX_WIDTH) - { - tex_size.width = parent_->GetWidth(); - layout_size.width = -1; - } - - if (tex_size.height == nux::AREA_MAX_HEIGHT) - { - tex_size.height = parent_->GetHeight(); - layout_size.height = -1; - } - - texture->cr.reset(new CairoGraphics(CAIRO_FORMAT_ARGB32, tex_size.width, tex_size.height)); + nux::Size layout_size(-1, lines_ < 0 ? lines_ : std::numeric_limits<int>::min()); + texture->cr.reset(new CairoGraphics(CAIRO_FORMAT_ARGB32, cached_extent_.width, cached_extent_.height)); cairo_t* cr = texture->cr->GetInternalContext(); PangoLayout* layout = NULL; @@ -702,8 +696,9 @@ void StaticCairoText::Impl::DrawText(CacheTexture::Ptr const& texture) 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()); + + desc = pango_font_description_from_string(font.c_str()); pango_layout_set_font_description(layout, desc); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_ellipsize(layout, GetPangoEllipsizeMode()); @@ -713,8 +708,6 @@ void StaticCairoText::Impl::DrawText(CacheTexture::Ptr const& texture) pango_layout_set_height(layout, layout_size.height); 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 @@ -732,14 +725,22 @@ void StaticCairoText::Impl::DrawText(CacheTexture::Ptr const& texture) (float) dpi / (float) PANGO_SCALE); } + Size result; + pango_layout_context_changed(layout); + pango_layout_get_pixel_size(layout, &result.width, &result.height); + + if (result.width > parent_->GetMaximumWidth()) + { + pango_layout_set_width(layout, parent_->GetMaximumWidth() * PANGO_SCALE); + pango_layout_context_changed(layout); + } + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(cr, text_color_.red, text_color_.green, text_color_.blue, text_color_.alpha); - pango_layout_context_changed(layout); - cairo_move_to(cr, 0.0f, 0.0f); pango_cairo_show_layout(cr, layout); @@ -750,10 +751,15 @@ void StaticCairoText::Impl::DrawText(CacheTexture::Ptr const& texture) g_object_unref(layout); } +void StaticCairoText::Impl::UpdateBaseSize() +{ + parent_->SetBaseSize(cached_extent_.width, cached_extent_.height); +} + void StaticCairoText::Impl::UpdateTexture() { - auto const& size = GetTextExtents(); - parent_->SetBaseSize(size.width, size.height); + GetTextExtents(); + UpdateBaseSize(); textures2D_.clear(); for (auto const& texture : cache_textures_) diff --git a/unity-shared/Timer.h b/unity-shared/Timer.h index 8669164b5..a646dec62 100644 --- a/unity-shared/Timer.h +++ b/unity-shared/Timer.h @@ -20,7 +20,6 @@ #ifndef UNITY_TIMER_H #define UNITY_TIMER_H -#include <iosfwd> #include <string> #include <glib.h> |
