diff options
44 files changed, 1287 insertions, 815 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7134b2d93..27dbc4546 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,10 +230,10 @@ set(UNITY_PLUGIN_SHARED_DEPS libbamf3>=0.5.0 libnotify libstartup-notification-1.0 - nux-4.0>=4.0.1 + nux-4.0>=4.0.4 sigc++-2.0 unity-misc>=0.4.0 - xpathselect>=1.2 + xpathselect=1.4 zeitgeist-2.0 ) diff --git a/UnityCore/Filters.cpp b/UnityCore/Filters.cpp index f5d2fde12..c30901316 100644 --- a/UnityCore/Filters.cpp +++ b/UnityCore/Filters.cpp @@ -103,7 +103,7 @@ void FilterAdaptor::MergeState(glib::HintsMap const& hints) current_hints[iter->first] = iter->second; } - dee_model_set_value(model_, iter_, FilterColumn::RENDERER_STATE, glib::Variant::FromHints(current_hints)); + dee_model_set_value(model_, iter_, FilterColumn::RENDERER_STATE, glib::Variant(current_hints)); } diff --git a/UnityCore/Result.cpp b/UnityCore/Result.cpp index c2c02a9ef..104da7e05 100644 --- a/UnityCore/Result.cpp +++ b/UnityCore/Result.cpp @@ -150,18 +150,11 @@ bool LocalResult::operator!=(LocalResult const& rhs) const std::vector<glib::Variant> LocalResult::Variants() const { - std::vector<glib::Variant> vars; - vars.push_back(g_variant_new_string(uri.c_str())); - vars.push_back(g_variant_new_string(icon_hint.c_str())); - vars.push_back(g_variant_new_uint32(category_index)); - vars.push_back(g_variant_new_uint32(result_type)); - vars.push_back(g_variant_new_string(mimetype.c_str())); - vars.push_back(g_variant_new_string(name.c_str())); - vars.push_back(g_variant_new_string(comment.c_str())); - vars.push_back(g_variant_new_string(dnd_uri.c_str())); - vars.push_back(glib::Variant::FromHints(hints)); - - return vars; + return { + glib::Variant(uri), glib::Variant(icon_hint), glib::Variant(category_index), + glib::Variant(result_type), glib::Variant(mimetype), glib::Variant(name), + glib::Variant(comment), glib::Variant(dnd_uri), glib::Variant(hints) + }; } glib::Variant LocalResult::Variant() const diff --git a/UnityCore/Scope.cpp b/UnityCore/Scope.cpp index 5e3174932..35937490c 100644 --- a/UnityCore/Scope.cpp +++ b/UnityCore/Scope.cpp @@ -278,7 +278,7 @@ void Scope::ActivatePreviewAction(Preview::ActionPtr const& action, } glib::HintsMap tmp_hints = hints; - tmp_hints["preview-action-id"] = g_variant_new_string(action->id.c_str()); + tmp_hints["preview-action-id"] = action->id; pimpl->Activate(result, UNITY_PROTOCOL_ACTION_TYPE_PREVIEW_ACTION, tmp_hints, callback, cancellable); } diff --git a/UnityCore/ScopeProxy.cpp b/UnityCore/ScopeProxy.cpp index d5ba31bf6..59c44fe46 100644 --- a/UnityCore/ScopeProxy.cpp +++ b/UnityCore/ScopeProxy.cpp @@ -401,7 +401,7 @@ void ScopeProxy::Impl::OnChannelOpened(glib::String const& opened_channel, glib: glib::HintsMap hints; if (!owner_->form_factor().empty()) { - hints["form-factor"] = g_variant_new_string(owner_->form_factor().c_str()); + hints["form-factor"] = owner_->form_factor(); } hints["changed-filter-row"] = filter->VariantValue(); Search(last_search_, hints, nullptr, cancel_scope_); @@ -521,7 +521,7 @@ void ScopeProxy::Impl::Search(std::string const& search_string, glib::HintsMap c glib::HintsMap updated_hints(hints); if (!owner_->form_factor().empty()) { - updated_hints["form-factor"] = g_variant_new_string(owner_->form_factor().c_str()); + updated_hints["form-factor"] = owner_->form_factor(); } Search(search_string, updated_hints, callback, canc); } @@ -791,9 +791,9 @@ void ScopeProxy::DisconnectProxy() void ScopeProxy::Search(std::string const& search_string, glib::HintsMap const& user_hints, SearchCallback const& callback, GCancellable* cancellable) { glib::HintsMap hints = user_hints; - if (!form_factor.Get().empty() && hints.find("form-factor") == hints.end()) + if (!form_factor().empty() && hints.find("form-factor") == hints.end()) { - hints["form-factor"] = g_variant_new_string(form_factor().c_str()); + hints["form-factor"] = form_factor(); } pimpl->Search(search_string, hints, callback, cancellable); } diff --git a/UnityCore/Variant.cpp b/UnityCore/Variant.cpp index 4cb102b96..1efb81f9b 100644 --- a/UnityCore/Variant.cpp +++ b/UnityCore/Variant.cpp @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2010 Canonical Ltd + * Copyright (C) 2010-2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -15,6 +15,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Tim Penhey <tim.penhey@canonical.com> + * Marco Trevisan <marco.trevisan@canonical.com> */ #include "Variant.h" @@ -27,7 +28,7 @@ namespace glib DECLARE_LOGGER(logger, "unity.glib.variant"); Variant::Variant() - : variant_(NULL) + : variant_(nullptr) {} Variant::Variant(GVariant* variant) @@ -41,9 +42,71 @@ Variant::Variant(GVariant* variant, StealRef const& ref) {} Variant::Variant(Variant const& other) - : variant_(other.variant_) + : Variant(other.variant_) +{} + +Variant::Variant(std::nullptr_t) + : Variant() +{} + +Variant::Variant(const char* value) + : Variant(g_variant_new_string(value ? value : value)) +{} + +Variant::Variant(std::string const& value) + : Variant(g_variant_new_string(value.c_str())) +{} + +Variant::Variant(unsigned char value) + : Variant(g_variant_new_byte(value)) +{} + +Variant::Variant(int16_t value) + : Variant(g_variant_new_int16(value)) +{} + +Variant::Variant(uint16_t value) + : Variant(g_variant_new_uint16(value)) +{} + +Variant::Variant(int32_t value) + : Variant(g_variant_new_int32(value)) +{} + +Variant::Variant(uint32_t value) + : Variant(g_variant_new_uint32(value)) +{} + +Variant::Variant(int64_t value) + : Variant(g_variant_new_int64(value)) +{} + +Variant::Variant(uint64_t value) + : Variant(g_variant_new_uint64(value)) +{} + +Variant::Variant(bool value) + : Variant(g_variant_new_boolean(value)) +{} + +Variant::Variant(double value) + : Variant(g_variant_new_double(value)) +{} + +Variant::Variant(float value) + : Variant(static_cast<double>(value)) +{} + +Variant::Variant(HintsMap const& hints) { - if (variant_) g_variant_ref_sink(variant_); + GVariantBuilder b; + g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}")); + + for (auto const& hint : hints) + g_variant_builder_add(&b, "{sv}", hint.first.c_str(), static_cast<GVariant*>(hint.second)); + + variant_ = g_variant_builder_end(&b); + g_variant_ref_sink(variant_); } Variant::~Variant() @@ -51,6 +114,25 @@ Variant::~Variant() if (variant_) g_variant_unref(variant_); } +glib::Variant get_variant(GVariant *variant_) +{ + Variant value; + + if (!variant_) + return value; + + if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_VARIANT)) + { + value = Variant(g_variant_get_variant(variant_), StealRef()); + } + else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(v)"))) + { + g_variant_get(variant_, "(v)", &value); + } + + return value; +} + std::string Variant::GetString() const { const gchar *result = nullptr; @@ -70,182 +152,91 @@ std::string Variant::GetString() const } else { - auto const& variant = GetVariant(); + auto const& variant = get_variant(variant_); if (variant) return variant.GetString(); - LOG_ERROR(logger) << "You're trying to extract a String from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); + LOG_ERROR(logger) << "You're trying to extract a 's' from a variant which is of type '" + << g_variant_type_peek_string(g_variant_get_type(variant_)) << "'"; } return result ? result : ""; } -int32_t Variant::GetInt32() const +template <typename TYPE, typename GTYPE> +TYPE get_numeric_value(GVariant *variant_, const char *type_str, const char *fallback_type_str) { - gint32 value = 0; + GTYPE value = 0; if (!variant_) - return static_cast<int>(value); + return static_cast<TYPE>(value); - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_INT32)) + if (g_variant_is_of_type(variant_, G_VARIANT_TYPE(type_str))) { - value = g_variant_get_int32(variant_); + g_variant_get(variant_, type_str, &value); } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(i)"))) + else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE(fallback_type_str))) { - g_variant_get(variant_, "(i)", &value); + g_variant_get(variant_, fallback_type_str, &value); } else { - auto const& variant = GetVariant(); + auto const& variant = get_variant(variant_); if (variant) - return variant.GetInt32(); + return get_numeric_value<TYPE, GTYPE>(static_cast<GVariant*>(variant), type_str, fallback_type_str); - LOG_ERROR(logger) << "You're trying to extract an Int32 from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); + LOG_ERROR(logger) << "You're trying to extract a '" << type_str << "'" + << " from a variant which is of type '" + << g_variant_type_peek_string(g_variant_get_type(variant_)) + << "'"; } - return static_cast<int32_t>(value); + return static_cast<TYPE>(value); } -uint32_t Variant::GetUInt32() const +unsigned char Variant::GetByte() const { - guint32 value = 0; + return get_numeric_value<unsigned char, guchar>(variant_, "y", "(y)"); +} - if (!variant_) - return static_cast<unsigned>(value); +int16_t Variant::GetInt16() const +{ + return get_numeric_value<int16_t, gint16>(variant_, "n", "(n)"); +} - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_UINT32)) - { - value = g_variant_get_uint32(variant_); - } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(u)"))) - { - g_variant_get(variant_, "(u)", &value); - } - else - { - auto const& variant = GetVariant(); - if (variant) - return variant.GetUInt32(); +uint16_t Variant::GetUInt16() const +{ + return get_numeric_value<uint16_t, guint16>(variant_, "q", "(q)"); +} - LOG_ERROR(logger) << "You're trying to extract an UInt32 from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); - } +int32_t Variant::GetInt32() const +{ + return get_numeric_value<int32_t, gint32>(variant_, "i", "(i)"); +} - return static_cast<uint32_t>(value);} +uint32_t Variant::GetUInt32() const +{ + return get_numeric_value<uint32_t, guint32>(variant_, "u", "(u)"); +} int64_t Variant::GetInt64() const { - gint64 value = 0; - - if (!variant_) - return static_cast<int64_t>(value); - - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_INT64)) - { - value = g_variant_get_int64(variant_); - } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(x)"))) - { - g_variant_get(variant_, "(x)", &value); - } - else - { - auto const& variant = GetVariant(); - if (variant) - return variant.GetInt64(); - - LOG_ERROR(logger) << "You're trying to extract an Int64 from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); - } - - return static_cast<int64_t>(value); + return get_numeric_value<int64_t, gint64>(variant_, "x", "(x)"); } uint64_t Variant::GetUInt64() const { - guint64 value = 0; - - if (!variant_) - return static_cast<uint64_t>(value); - - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_UINT64)) - { - value = g_variant_get_uint64(variant_); - } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(t)"))) - { - g_variant_get(variant_, "(t)", &value); - } - else - { - auto const& variant = GetVariant(); - if (variant) - return variant.GetUInt64(); - - LOG_ERROR(logger) << "You're trying to extract an UInt64 from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); - } - - return static_cast<uint64_t>(value); + return get_numeric_value<uint64_t, guint64>(variant_, "t", "(t)"); } bool Variant::GetBool() const { - gboolean value = FALSE; - - if (!variant_) - return (value != FALSE); - - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_BOOLEAN)) - { - value = g_variant_get_boolean(variant_); - } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(b)"))) - { - g_variant_get(variant_, "(b)", &value); - } - else - { - auto const& variant = GetVariant(); - if (variant) - return variant.GetBool(); - - LOG_ERROR(logger) << "You're trying to extract a Boolean from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); - } - - return (value != FALSE); + return get_numeric_value<bool, gboolean>(variant_, "b", "(b)"); } double Variant::GetDouble() const { - double value = 0.0; - - if (!variant_) - return value; - - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_DOUBLE)) - { - value = g_variant_get_double(variant_); - } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(d)"))) - { - g_variant_get(variant_, "(d)", &value); - } - else - { - auto const& variant = GetVariant(); - if (variant) - return variant.GetDouble(); - - LOG_ERROR(logger) << "You're trying to extract a Double from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); - } - - return value; + return get_numeric_value<double, gdouble>(variant_, "d", "(d)"); } float Variant::GetFloat() const @@ -260,18 +251,12 @@ Variant Variant::GetVariant() const if (!variant_) return value; - if (g_variant_is_of_type(variant_, G_VARIANT_TYPE_VARIANT)) - { - value = Variant(g_variant_get_variant(variant_), StealRef()); - } - else if (g_variant_is_of_type(variant_, G_VARIANT_TYPE("(v)"))) - { - g_variant_get(variant_, "(v)", &value); - } - else + value = get_variant(variant_); + + if (!value) { - LOG_ERROR(logger) << "You're trying to extract a Variant from a variant which is of type " - << g_variant_type_peek_string(g_variant_get_type(variant_)); + LOG_ERROR(logger) << "You're trying to extract a 'v' from a variant which is of type '" + << g_variant_type_peek_string(g_variant_get_type(variant_)) << "'"; } return value; @@ -304,22 +289,6 @@ bool Variant::ASVToHints(HintsMap& hints) const return true; } -Variant Variant::FromHints(HintsMap const& hints) -{ - GVariantBuilder b; - g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}")); - - for (glib::HintsMap::const_iterator it = hints.begin(); it != hints.end(); ++it) - { - const gchar* key = it->first.c_str(); - GVariant* ptr = it->second; - - g_variant_builder_add(&b, "{sv}", key, ptr); - } - - return g_variant_builder_end(&b); -} - void Variant::swap(Variant& other) { std::swap(this->variant_, other.variant_); @@ -340,6 +309,21 @@ Variant& Variant::operator=(Variant other) return *this; } +Variant& Variant::operator=(std::nullptr_t) { return operator=(Variant()); } +Variant& Variant::operator=(HintsMap const& map) { return operator=(Variant(map)); } +Variant& Variant::operator=(std::string const& value) { return operator=(Variant(value)); } +Variant& Variant::operator=(const char* value) { return operator=(Variant(value)); } +Variant& Variant::operator=(unsigned char value) { return operator=(Variant(value)); } +Variant& Variant::operator=(int16_t value) { return operator=(Variant(value)); } +Variant& Variant::operator=(uint16_t value) { return operator=(Variant(value)); } +Variant& Variant::operator=(int32_t value) { return operator=(Variant(value)); } +Variant& Variant::operator=(uint32_t value) { return operator=(Variant(value)); } +Variant& Variant::operator=(int64_t value) { return operator=(Variant(value)); } +Variant& Variant::operator=(uint64_t value) { return operator=(Variant(value)); } +Variant& Variant::operator=(bool value) { return operator=(Variant(value)); } +Variant& Variant::operator=(double value) { return operator=(Variant(value)); } +Variant& Variant::operator=(float value) { return operator=(Variant(value)); } + Variant::operator GVariant* () const { return variant_; @@ -396,90 +380,116 @@ HintsMap const& hintsmap_from_hashtable(GHashTable* hashtable, HintsMap& hints) namespace variant { +using namespace glib; BuilderWrapper::BuilderWrapper(GVariantBuilder* builder) : builder_(builder) {} -BuilderWrapper& BuilderWrapper::add(char const* name, bool value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, ValueType type, std::vector<Variant> const& values) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_boolean(value)); + GVariantBuilder array; + g_variant_builder_init(&array, G_VARIANT_TYPE("av")); + g_variant_builder_add(&array, "v", g_variant_new_uint32(static_cast<uint32_t>(type))); + + for (auto const& value : values) + g_variant_builder_add(&array, "v", static_cast<GVariant*>(value)); + + g_variant_builder_add(builder_, "{sv}", name.c_str(), g_variant_builder_end(&array)); + return *this; } -BuilderWrapper& BuilderWrapper::add(char const* name, char const* value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, bool value) { - if (value) - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_string(value)); - else - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_string("")); + return add(name, ValueType::SIMPLE, {Variant(value)}); +} - return *this; +BuilderWrapper& BuilderWrapper::add(std::string const& name, char const* value) +{ + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, std::string const& value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, std::string const& value) { - g_variant_builder_add(builder_, "{sv}", name, - g_variant_new_string(value.c_str())); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, int16_t value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, int16_t value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int16(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, int32_t value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, int32_t value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int32(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, int64_t value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, int64_t value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int64(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, uint16_t value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, uint16_t value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_uint16(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, uint32_t value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, uint32_t value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_uint32(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, uint64_t value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, uint64_t value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_uint64(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, float value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, float value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_double(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, double value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, double value) { - g_variant_builder_add(builder_, "{sv}", name, g_variant_new_double(value)); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); } -BuilderWrapper& BuilderWrapper::add(char const* name, GVariant* value) +BuilderWrapper& BuilderWrapper::add(std::string const& name, GVariant* value) { - g_variant_builder_add(builder_, "{sv}", name, value); - return *this; + return add(name, ValueType::SIMPLE, {Variant(value)}); +} + +BuilderWrapper& BuilderWrapper::add(std::string const& name, glib::Variant const& value) +{ + return add(name, ValueType::SIMPLE, {value}); +} + +BuilderWrapper& BuilderWrapper::add(std::string const& name, nux::Rect const& r) +{ + return add(name, ValueType::RECTANGLE, {Variant(r.x), Variant(r.y), Variant(r.width), Variant(r.height)}); +} + +BuilderWrapper& BuilderWrapper::add(std::string const& name, nux::Point const& p) +{ + return add(name, ValueType::POINT, {Variant(p.x), Variant(p.y)}); +} + +BuilderWrapper& BuilderWrapper::add(std::string const& name, nux::Size const& s) +{ + return add(name, ValueType::SIZE, {Variant(s.width), Variant(s.height)}); +} + +BuilderWrapper& BuilderWrapper::add(std::string const& name, nux::Color const& c) +{ + int32_t r = c.red * 255.0f, g = c.green * 255.0f, b = c.blue * 255.0f, a = c.alpha * 255.0f; + return add(name, ValueType::COLOR, {Variant(r), Variant(g), Variant(b), Variant(a)}); } BuilderWrapper& BuilderWrapper::add(nux::Rect const& value) { + add("globalRect", value); + // Legacy support add("x", value.x); add("y", value.y); add("width", value.width); diff --git a/UnityCore/Variant.h b/UnityCore/Variant.h index 8217963d6..d0a6a3f2f 100644 --- a/UnityCore/Variant.h +++ b/UnityCore/Variant.h @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2011 Canonical Ltd + * Copyright (C) 2011-2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -15,6 +15,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Tim Penhey <tim.penhey@canonical.com> + * Marco Trevisan <marco.trevisan@canonical.com> */ #ifndef UNITY_VARIANT_H @@ -22,9 +23,11 @@ #include <string> #include <glib.h> +#include <vector> #include <map> #include <NuxCore/Rect.h> +#include <NuxCore/Color.h> namespace unity { @@ -45,10 +48,28 @@ public: Variant(GVariant*); Variant(GVariant*, StealRef const&); + Variant(HintsMap const& hints); + explicit Variant(std::nullptr_t); + explicit Variant(std::string const&); + explicit Variant(const char*); + explicit Variant(unsigned char); + explicit Variant(int16_t); + explicit Variant(uint16_t); + explicit Variant(int32_t); + explicit Variant(uint32_t); + explicit Variant(int64_t); + explicit Variant(uint64_t); + explicit Variant(bool); + explicit Variant(double); + explicit Variant(float); + Variant(Variant const&); ~Variant(); std::string GetString() const; + unsigned char GetByte() const; + int16_t GetInt16() const; + uint16_t GetUInt16() const; int32_t GetInt32() const; uint32_t GetUInt32() const; int64_t GetInt64() const; @@ -59,11 +80,24 @@ public: Variant GetVariant() const; bool ASVToHints(HintsMap& hints) const; - static Variant FromHints(HintsMap const& hints); void swap(Variant&); Variant& operator=(GVariant*); Variant& operator=(Variant); + Variant& operator=(HintsMap const&); + Variant& operator=(std::nullptr_t); + Variant& operator=(std::string const&); + Variant& operator=(const char*); + Variant& operator=(unsigned char); + Variant& operator=(int16_t); + Variant& operator=(uint16_t); + Variant& operator=(int32_t); + Variant& operator=(uint32_t); + Variant& operator=(int64_t); + Variant& operator=(uint64_t); + Variant& operator=(bool); + Variant& operator=(double); + Variant& operator=(float); operator GVariant*() const; operator bool() const; @@ -78,24 +112,44 @@ namespace variant class BuilderWrapper { +// XXX: Move this to Introspectable public: + enum class ValueType : uint32_t + { + // This should match the Autopilot Type IDs + SIMPLE = 0, + RECTANGLE = 1, + POINT = 2, + SIZE = 3, + COLOR = 4, + DATE = 5, + TIME = 6, + }; + BuilderWrapper(GVariantBuilder* builder); - BuilderWrapper& add(char const* name, bool value); - BuilderWrapper& add(char const* name, char const* value); - BuilderWrapper& add(char const* name, std::string const& value); - BuilderWrapper& add(char const* name, int16_t value); - BuilderWrapper& add(char const* name, int32_t value); - BuilderWrapper& add(char const* name, int64_t value); - BuilderWrapper& add(char const* name, uint16_t value); - BuilderWrapper& add(char const* name, uint32_t value); - BuilderWrapper& add(char const* name, uint64_t value); - BuilderWrapper& add(char const* name, float value); - BuilderWrapper& add(char const* name, double value); - BuilderWrapper& add(char const* name, GVariant* value); - BuilderWrapper& add(nux::Rect const& value); + BuilderWrapper& add(std::string const& name, bool); + BuilderWrapper& add(std::string const& name, const char*); + BuilderWrapper& add(std::string const& name, std::string const&); + BuilderWrapper& add(std::string const& name, int16_t); + BuilderWrapper& add(std::string const& name, int32_t); + BuilderWrapper& add(std::string const& name, int64_t); + BuilderWrapper& add(std::string const& name, uint16_t); + BuilderWrapper& add(std::string const& name, uint32_t); + BuilderWrapper& add(std::string const& name, uint64_t); + BuilderWrapper& add(std::string const& name, float); + BuilderWrapper& add(std::string const& name, double); + BuilderWrapper& add(std::string const& name, glib::Variant const&); + BuilderWrapper& add(std::string const& name, GVariant*); + + BuilderWrapper& add(std::string const& name, nux::Rect const&); + BuilderWrapper& add(std::string const& name, nux::Point const&); + BuilderWrapper& add(std::string const& name, nux::Size const&); + BuilderWrapper& add(std::string const& name, nux::Color const&); + BuilderWrapper& add(nux::Rect const&); private: + BuilderWrapper& add(std::string const& name, ValueType, std::vector<glib::Variant> const&); GVariantBuilder* builder_; }; diff --git a/dash/FilterBar.cpp b/dash/FilterBar.cpp index b5cca7a68..52713c603 100644 --- a/dash/FilterBar.cpp +++ b/dash/FilterBar.cpp @@ -144,11 +144,7 @@ std::string FilterBar::GetName() const void FilterBar::AddProperties(GVariantBuilder* builder) { - variant::BuilderWrapper(builder) - .add("x", GetAbsoluteX()) - .add("y", GetAbsoluteY()) - .add("width", GetAbsoluteWidth()) - .add("height", GetAbsoluteHeight()); + variant::BuilderWrapper(builder).add(GetAbsoluteGeometry()); } } // namespace dash diff --git a/dash/PlacesGroup.cpp b/dash/PlacesGroup.cpp index e54f1e6c9..b67229a9c 100755 --- a/dash/PlacesGroup.cpp +++ b/dash/PlacesGroup.cpp @@ -649,6 +649,7 @@ void PlacesGroup::AddProperties(GVariantBuilder* builder) wrapper.add("header-y", _header_view->GetAbsoluteY()); wrapper.add("header-width", _header_view->GetAbsoluteWidth()); wrapper.add("header-height", _header_view->GetAbsoluteHeight()); + wrapper.add("header-geo", _header_view->GetAbsoluteGeometry()); wrapper.add("header-has-keyfocus", HeaderHasKeyFocus()); wrapper.add("header-is-highlighted", ShouldBeHighlighted()); wrapper.add("name", _name->GetText()); @@ -656,22 +657,24 @@ void PlacesGroup::AddProperties(GVariantBuilder* builder) wrapper.add("is-expanded", GetExpanded()); wrapper.add("expand-label-is-visible", _expand_label->IsVisible()); wrapper.add("expand-label-y", _expand_label->GetAbsoluteY()); + wrapper.add("expand-label-geo", _expand_label->GetAbsoluteGeometry()); wrapper.add("expand-label-baseline", _expand_label->GetBaseline()); wrapper.add("name-label-y", _name->GetAbsoluteY()); wrapper.add("name-label-baseline", _name->GetBaseline()); + wrapper.add("name-label-geo", _name->GetAbsoluteGeometry()); } glib::Variant PlacesGroup::GetCurrentFocus() const { if (_header_view && _header_view->HasKeyFocus()) { - return g_variant_new_string("HeaderView"); + return glib::Variant("HeaderView"); } else if (_child_view && _child_view->HasKeyFocus()) { return g_variant_new("(si)", "ResultView", _child_view->GetSelectedIndex()); } - return glib::Variant(); + return nullptr; } void PlacesGroup::SetCurrentFocus(glib::Variant const& variant) diff --git a/dash/previews/MusicPaymentPreview.cpp b/dash/previews/MusicPaymentPreview.cpp index dea364ca8..dba1cf2a8 100644 --- a/dash/previews/MusicPaymentPreview.cpp +++ b/dash/previews/MusicPaymentPreview.cpp @@ -98,9 +98,8 @@ void MusicPaymentPreview::OnActionActivated(ActionButton* button, std::string co { // HACK: We need to think a better way to do this auto const& password = password_entry_->text_entry()->GetText(); - glib::Variant variant_pw(g_variant_new_string(password.c_str())); glib::HintsMap hints { - std::make_pair(MusicPaymentPreview::DATA_PASSWORD_KEY, variant_pw) + {MusicPaymentPreview::DATA_PASSWORD_KEY, glib::Variant(password)} }; preview_model_->PerformAction(id, hints); diff --git a/dash/previews/PaymentPreview.cpp b/dash/previews/PaymentPreview.cpp index e3773c7bc..9c8943e98 100644 --- a/dash/previews/PaymentPreview.cpp +++ b/dash/previews/PaymentPreview.cpp @@ -170,13 +170,7 @@ std::string OverlaySpinner::GetName() const void OverlaySpinner::AddProperties(GVariantBuilder* builder) { - nux::Geometry geo = GetGeometry(); - - variant::BuilderWrapper(builder) - .add("x", geo.x) - .add("y", geo.y) - .add("width", geo.width) - .add("height", geo.height); + variant::BuilderWrapper(builder).add(GetAbsoluteGeometry()); } diff --git a/dash/previews/PreviewNavigator.cpp b/dash/previews/PreviewNavigator.cpp index 2c765007d..d71c2217c 100644 --- a/dash/previews/PreviewNavigator.cpp +++ b/dash/previews/PreviewNavigator.cpp @@ -70,6 +70,7 @@ void PreviewNavigator::AddProperties(GVariantBuilder* builder) .add("button-y", texture_->GetAbsoluteY()) .add("button-width", texture_->GetGeometry().width) .add("button-height", texture_->GetGeometry().height) + .add("button-geo", texture_->GetAbsoluteGeometry()) .add("direction", static_cast<int>(direction_)); } diff --git a/dash/previews/Track.cpp b/dash/previews/Track.cpp index 51393fceb..64d9d291c 100644 --- a/dash/previews/Track.cpp +++ b/dash/previews/Track.cpp @@ -149,7 +149,8 @@ void Track::AddProperties(GVariantBuilder* builder) .add("playpause-x", track_status_layout_->GetAbsoluteX()) .add("playpause-y", track_status_layout_->GetAbsoluteX()) .add("playpause-width", track_status_layout_->GetGeometry().width) - .add("playpause-height", track_status_layout_->GetGeometry().height); + .add("playpause-height", track_status_layout_->GetGeometry().height) + .add("playpause-geo", track_status_layout_->GetAbsoluteGeometry()); } void Track::Update(dash::Track const& track) diff --git a/debian/changelog b/debian/changelog index a08d25628..56023e476 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,76 @@ +unity (7.1.2+14.04.20131106.1-0ubuntu1) trusty; urgency=low + + [ Ted Gould ] + * Clean up NIH Errors so they don't get reported on exit. (LP: + #1236720) + + [ Brandon Schaefer ] + * Workaround for now, replace all blacklisted chars in the results + name with a '?'. So we can still render all the results with out a + crash. This needs to be fixed in pango/harfbuzz. (LP: #1239381) + * Get the current char before moving on to the next char!. + + [ Marco Trevisan (Treviño) ] + * UnityScreen: also redraw the HudView if it has not been fully + damaged. (LP: #1240322) + * OverlayRenderer: only and correctly initialize the BGLayer when not + on GLSL codepath Make sure we set the initial bg_layer_ value to the + average color, and do this only if really needed. (LP: #1232726) + * Launcher: desaturate the inactive icons when in Spread mode. (LP: + #1238892, #1238638) + * LauncherIcon: add MultiMonitor quirks support A quirk can be now set + for all monitors or for just one. (LP: #1051913, #1215738, #1240750, + #1240737) + * UnityScreen: CreateSuperNewAction with Shift and Numpad for launcher + This fixes the bug that caused Super+Shift+KP_x not to work as it + should. (LP: #1240806) + * AnimationUtils: add Start, Skip and SetValue methods These allows to + start an animation, to skip it or to just set its value. The + templates now are more intelligent and we define the values that can + assume just once, by specializing a StartValueForDirection function. + * Support libxpathselect1.4. (LP: #1243529) + * LauncherIcon: use nux::Animation for each Quirk property Update + Launcher and Icons code accordingly, get rid of the timespec. Remove + unneded Quirks, reduce redraws and update tests. + * Invalidate the Icon Centers when the monitor layout changes, so we + make sure that if an icon center is set, then the icon is available + on that monitor. Added GetCenterForMonitor that allows to retrieve + the nearest valid icon center for a given monitor, and in this way + we can get the best icon that can handle a window minimization. (LP: + #767752) + + [ Lars Uebernickel ] + * panel-service.c: don't warn about unknown image type unnecessarily + Don't warn about indicators that explicitely don't have an image + set. However, continue warning when the set image is of an unknown + type. + + [ Chris Townsend ] + * Instead of using NeedSoftRedraw(), use QueueDraw() for the Launcher + and Panel to force a redraw to fix issue where leaving a full screen + unredirected window would not redraw the Launcher and Panel. (LP: + #1240595) + + [ Eleni Maria Stea ] + * Added --compiz-path parameter to the unity startup script. It allows + us to start unity with custom builds of compiz (not only + /usr/bin/compiz) like that: ./unity --compiz-path + custom_compiz_build_directory/bin/compiz --replace ccp. + + [ Francis Ginther ] + * Reverting support for libxpathselect1.4. (LP: #1245988) + + [ Łukasz 'sil2100' Zemczak ] + * DebugDBusInterface: add support to libxpathselect-1.4 Some cleanups + and reworking of glib::Variant and debug::DBusInterface Same as + lp:~3v1n0/unity/xpathselect-1.4 but with double function removed and + packaging dependencies added. + + [ Ubuntu daily release ] + * Automatic snapshot from revision 3588 + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 06 Nov 2013 18:29:25 +0000 + unity (7.1.2+13.10.20131014.1-0ubuntu1) saucy; urgency=low [ William Grant ] diff --git a/debian/control b/debian/control index 2865a231a..1c796d8b2 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: gnome Priority: optional Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> Build-Depends: cmake, - compiz-dev (>= 1:0.9.10), + compiz-dev (>= 1:0.9.11), debhelper (>= 9.0.0~), dbus-test-runner, dh-migrations, @@ -18,7 +18,7 @@ Build-Depends: cmake, libboost-serialization-dev, libcairo2-dev, libdbus-1-dev, - libcompizconfig0-dev (>= 1:0.9.10), + libcompizconfig0-dev (>= 1:0.9.11), libdbusmenu-glib-dev (>= 0.3.91), libdee-dev (>= 1.2.6), libgee-dev (>= 0.5.0), @@ -36,7 +36,7 @@ Build-Depends: cmake, libnih-dbus-dev, libnih-dev, libnotify-dev, - libnux-4.0-dev (>= 4.0.2+13.10.20130718.1), + libnux-4.0-dev (>= 4.0.4), libpango1.0-dev, libsigc++-2.0-dev, libstartup-notification0-dev, @@ -48,7 +48,7 @@ Build-Depends: cmake, libxcb-icccm4-dev, libxfixes-dev (>= 1:5.0.1-1), libxi-dev (>= 2:1.7.1.901), - libxpathselect-dev (>=1.3), + libxpathselect-dev (>=1.4), libzeitgeist-2.0-dev, pkg-config, python (>= 2.7), @@ -148,7 +148,7 @@ Depends: ${misc:Depends}, libunity-core-6.0-8 (= ${binary:Version}), libglib2.0-dev, libsigc++-2.0-dev, - libnux-4.0-dev (>= 4.0.2), + libnux-4.0-dev (>= 4.0.4), libunity-dev (>= 7.1.0~), libdee-dev, Description: Core library for the Unity interface - development files @@ -178,7 +178,7 @@ Depends: ${misc:Depends}, python-testtools, python-xdg, python-xlib, - libxpathselect1.3 (>= 1.3), + libxpathselect1.4 (>= 1.4), Description: Autopiloted tests for Unity We test Unity automatically through autopilot, a framework which enables us to trigger keyboard and mouse events on the fly as well as introspecting diff --git a/launcher/CairoBaseWindow.cpp b/launcher/CairoBaseWindow.cpp index 751386ae9..d26ce8706 100644 --- a/launcher/CairoBaseWindow.cpp +++ b/launcher/CairoBaseWindow.cpp @@ -74,12 +74,6 @@ bool CairoBaseWindow::HasBlurredBackground() const return use_blurred_background_; } -void CairoBaseWindow::NeedSoftRedraw() -{ - compute_blur_bkg_ = true; - QueueDraw(); -} - void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) { nux::Geometry base(GetGeometry()); diff --git a/launcher/CairoBaseWindow.h b/launcher/CairoBaseWindow.h index a92a76070..029e4e0f9 100644 --- a/launcher/CairoBaseWindow.h +++ b/launcher/CairoBaseWindow.h @@ -36,7 +36,6 @@ public: virtual void Show(); virtual void Hide(); - void NeedSoftRedraw() override; bool HasBlurredBackground() const; protected: diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp index de74c6ba7..689cfa752 100644 --- a/launcher/Launcher.cpp +++ b/launcher/Launcher.cpp @@ -2402,12 +2402,6 @@ void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, nux::ObjectP unity::graphics::PopOffscreenRenderTarget(); } -// FIXME: This will need to be removed when the Unity performance branch is merged. -void Launcher::NeedSoftRedraw() -{ - QueueDraw(); -} - #ifdef NUX_GESTURES_SUPPORT nux::GestureDeliveryRequest Launcher::GestureEvent(const nux::GestureEvent &event) { diff --git a/launcher/Launcher.h b/launcher/Launcher.h index 09282a853..b9d28a744 100644 --- a/launcher/Launcher.h +++ b/launcher/Launcher.h @@ -151,9 +151,6 @@ public: void RenderIconToTexture(nux::GraphicsEngine&, nux::ObjectPtr<nux::IOpenGLBaseTexture> const&, AbstractLauncherIcon::Ptr const&); - // FIXME: This will need to be removed when the Unity performance branch is merged. - void NeedSoftRedraw() override; - #ifdef NUX_GESTURES_SUPPORT virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event); #endif diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp index e4df86642..bc4cbe455 100644 --- a/launcher/LauncherController.cpp +++ b/launcher/LauncherController.cpp @@ -164,8 +164,7 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager, if (selected) { - ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, glib::Variant(selected->tooltip_text())); } }); @@ -1065,7 +1064,7 @@ Controller::Controller(XdndManager::Ptr const& xdnd_manager, ui::EdgeBarrierCont , multiple_launchers(true) , pimpl(new Impl(this, xdnd_manager, edge_barriers)) { - multiple_launchers.changed.connect([&](bool value) -> void { + multiple_launchers.changed.connect([this] (bool value) { UScreen* uscreen = UScreen::GetDefault(); auto monitors = uscreen->GetMonitors(); int primary = uscreen->GetPrimaryMonitor(); @@ -1164,7 +1163,7 @@ void Controller::HandleLauncherKeyPress(int when) { pimpl->launcher_key_press_time_ = when; - auto show_launcher = [&]() + auto show_launcher = [this] { if (pimpl->keyboard_launcher_.IsNull()) pimpl->keyboard_launcher_ = pimpl->CurrentLauncher(); @@ -1177,7 +1176,7 @@ void Controller::HandleLauncherKeyPress(int when) }; pimpl->sources_.AddTimeout(options()->super_tap_duration, show_launcher, local::KEYPRESS_TIMEOUT); - auto show_shortcuts = [&]() + auto show_shortcuts = [this] { if (!pimpl->launcher_keynav) { @@ -1233,7 +1232,7 @@ void Controller::HandleLauncherKeyRelease(bool was_tap, int when) { int time_left = local::launcher_minimum_show_duration - ms_since_show; - auto hide_launcher = [&]() + auto hide_launcher = [this] { if (pimpl->keyboard_launcher_.IsValid()) { @@ -1312,12 +1311,12 @@ void Controller::KeyNavActivate() if (pimpl->launcher_grabbed) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_NAV, - g_variant_new_int32(pimpl->keyboard_launcher_->monitor)); + glib::Variant(pimpl->keyboard_launcher_->monitor())); } else { pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_SWITCHER, - g_variant_new_int32(pimpl->keyboard_launcher_->monitor)); + glib::Variant(pimpl->keyboard_launcher_->monitor())); } AbstractLauncherIcon::Ptr const& selected = pimpl->model_->Selection(); @@ -1325,7 +1324,7 @@ void Controller::KeyNavActivate() if (selected) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + glib::Variant(selected->tooltip_text())); } } @@ -1338,7 +1337,7 @@ void Controller::KeyNavNext() if (selected) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + glib::Variant(selected->tooltip_text())); } } @@ -1351,7 +1350,7 @@ void Controller::KeyNavPrevious() if (selected) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + glib::Variant(selected->tooltip_text())); } } @@ -1376,12 +1375,12 @@ void Controller::KeyNavTerminate(bool activate) pimpl->launcher_event_outside_connection_->disconnect(); pimpl->launcher_grabbed = false; pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_NAV, - g_variant_new_boolean(pimpl->keynav_restore_window_)); + glib::Variant(pimpl->keynav_restore_window_)); } else { pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_SWITCHER, - g_variant_new_boolean(pimpl->keynav_restore_window_)); + glib::Variant(pimpl->keynav_restore_window_)); } if (activate) diff --git a/launcher/QuicklistView.cpp b/launcher/QuicklistView.cpp index e8dc2662d..6ac11a1a6 100644 --- a/launcher/QuicklistView.cpp +++ b/launcher/QuicklistView.cpp @@ -1303,6 +1303,7 @@ void QuicklistView::AddProperties(GVariantBuilder* builder) .add(GetAbsoluteGeometry()) .add("base_x", GetBaseX()) .add("base_y", GetBaseY()) + .add("base", nux::Point(GetBaseX(), GetBaseY())) .add("active", IsVisible()); } diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp index 1701af857..618c76a10 100644 --- a/launcher/SwitcherController.cpp +++ b/launcher/SwitcherController.cpp @@ -395,7 +395,7 @@ void Controller::Impl::OnModelSelectionChanged(AbstractLauncherIcon::Ptr const& } ubus_manager_.SendMessage(UBUS_SWITCHER_SELECTION_CHANGED, - g_variant_new_string(icon->tooltip_text().c_str())); + glib::Variant(icon->tooltip_text())); } } @@ -497,7 +497,7 @@ void Controller::Impl::Hide(bool accept_state) } } - ubus_manager_.SendMessage(UBUS_SWITCHER_END, g_variant_new_boolean(!accept_state)); + ubus_manager_.SendMessage(UBUS_SWITCHER_END, glib::Variant(!accept_state)); ubus_manager_.SendMessage(UBUS_SWITCHER_SHOWN, g_variant_new("(bi)", false, obj_->monitor_)); sources_.Remove(VIEW_CONSTRUCT_IDLE); diff --git a/launcher/Tooltip.cpp b/launcher/Tooltip.cpp index 00095ffd7..f053a925f 100644 --- a/launcher/Tooltip.cpp +++ b/launcher/Tooltip.cpp @@ -559,11 +559,8 @@ void Tooltip::AddProperties(GVariantBuilder* builder) { variant::BuilderWrapper(builder) .add("text", text) - .add("x", GetBaseX()) - .add("y", GetBaseY()) - .add("width", GetBaseWidth()) - .add("height", GetBaseHeight()) - .add("active", IsVisible()); + .add("active", IsVisible()) + .add(GetAbsoluteGeometry()); } } // namespace nux diff --git a/launcher/XdndCollectionWindowImp.cpp b/launcher/XdndCollectionWindowImp.cpp index 6b240edec..57f979fa0 100644 --- a/launcher/XdndCollectionWindowImp.cpp +++ b/launcher/XdndCollectionWindowImp.cpp @@ -38,6 +38,10 @@ public: auto uscreen = UScreen::GetDefault(); SetGeometry(uscreen->GetScreenGeometry()); + // We are not calling ShowWindow () as this window + // isn't really visible + PushToBack(); + if (nux::GetWindowThread()->IsEmbeddedWindow()) { // Hack to create the X Window as soon as possible. diff --git a/panel/PanelIndicatorEntryView.cpp b/panel/PanelIndicatorEntryView.cpp index 374c57787..0657cc805 100644 --- a/panel/PanelIndicatorEntryView.cpp +++ b/panel/PanelIndicatorEntryView.cpp @@ -664,6 +664,7 @@ void PanelIndicatorEntryView::AddProperties(GVariantBuilder* builder) .add("menu_y", proxy_->geometry().y) .add("menu_width", proxy_->geometry().width) .add("menu_height", proxy_->geometry().height) + .add("menu_geo", proxy_->geometry()) .add("focused", IsFocused()); } diff --git a/panel/PanelView.cpp b/panel/PanelView.cpp index 67284c247..dd56bd346 100644 --- a/panel/PanelView.cpp +++ b/panel/PanelView.cpp @@ -787,10 +787,4 @@ ui::EdgeBarrierSubscriber::Result PanelView::HandleBarrierEvent(ui::PointerBarri return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE; } -// FIXME: This will need to be removed when the Unity performance branch is merged. -void PanelView::NeedSoftRedraw() -{ - QueueDraw(); -} - } // namespace unity diff --git a/panel/PanelView.h b/panel/PanelView.h index 78b55c6ba..a1becbe80 100644 --- a/panel/PanelView.h +++ b/panel/PanelView.h @@ -78,9 +78,6 @@ public: ui::EdgeBarrierSubscriber::Result HandleBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event) override; - // FIXME: This will need to be removed when the Unity performance branch is merged. - void NeedSoftRedraw() override; - protected: void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw); diff --git a/plugins/unityshell/src/AggregateMonitor.cpp b/plugins/unityshell/src/AggregateMonitor.cpp deleted file mode 100644 index 62eb5c2e8..000000000 --- a/plugins/unityshell/src/AggregateMonitor.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- -/* -* Copyright (C) 2011 Canonical Ltd -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 3 as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* Authored by: Alex Launi <alex.launi@canonical.com> -*/ - -#include "AggregateMonitor.h" -#include "ElapsedTimeMonitor.h" -#include <UnityCore/Variant.h> - -namespace unity { -namespace performance { - -AggregateMonitor::AggregateMonitor() -{ - _monitors.push_back(new ElapsedTimeMonitor()); -} - -AggregateMonitor::~AggregateMonitor() -{ -} - -std::string AggregateMonitor::GetName() const -{ - return "AggregateMonitor"; -} - -void AggregateMonitor::StartMonitor() -{ - for (std::list<Monitor*>::iterator iter = _monitors.begin(), end = _monitors.end(); - iter != end; ++iter) - { - Monitor* monitor = *iter; - monitor->Start(); - } -} - -void AggregateMonitor::StopMonitor(GVariantBuilder* builder) -{ - variant::BuilderWrapper wrapper(builder); - for (std::list<Monitor*>::iterator iter = _monitors.begin(), end = _monitors.end(); - iter != end; ++iter) - { - Monitor* monitor = *iter; - wrapper.add(monitor->GetName().c_str(), monitor->Stop()); - } -} - -} -} diff --git a/plugins/unityshell/src/AggregateMonitor.h b/plugins/unityshell/src/AggregateMonitor.h deleted file mode 100644 index 251f8158d..000000000 --- a/plugins/unityshell/src/AggregateMonitor.h +++ /dev/null @@ -1,50 +0,0 @@ -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- -/* -* Copyright (C) 2011 Canonical Ltd -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 3 as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* Authored by: Alex Launi <alex.launi@canonical.com> -*/ - -#ifndef UNITY_PERFORMANCE_AGGREGATE_MONITOR -#define UNITY_PERFORMANCE_AGGREGATE_MONITOR - -#include <list> -#include <string> -#include <gio/gio.h> - -#include "Monitor.h" - -namespace unity { -namespace performance { - -class AggregateMonitor : public Monitor -{ -public: - AggregateMonitor(); - ~AggregateMonitor(); - std::string GetName() const; - -protected: - void StartMonitor(); - void StopMonitor(GVariantBuilder* builder); - -private: - std::list<Monitor*> _monitors; -}; - -} -} - -#endif // UNITY_PERFORMANCE_AGGREGATE_MONITOR diff --git a/plugins/unityshell/src/ElapsedTimeMonitor.cpp b/plugins/unityshell/src/ElapsedTimeMonitor.cpp deleted file mode 100644 index 586ab6368..000000000 --- a/plugins/unityshell/src/ElapsedTimeMonitor.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- -/* -* Copyright (C) 2011 Canonical Ltd -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 3 as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* Authored by: Alex Launi <alex.launi@canonical.com> -*/ - -#include <UnityCore/Variant.h> - -#include "ElapsedTimeMonitor.h" -#include "TimeUtil.h" - -namespace unity{ -namespace performance { - -std::string ElapsedTimeMonitor::GetName() const -{ - return "ElapsedTimeMonitor"; -} - -void ElapsedTimeMonitor::StartMonitor() -{ - clock_gettime(CLOCK_MONOTONIC, &_start); -} - -void ElapsedTimeMonitor::StopMonitor(GVariantBuilder* builder) -{ - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - DeltaTime diff = TimeUtil::TimeDelta(¤t, &_start); - - variant::BuilderWrapper(builder) - .add("elapsed-time", diff); -} - -} -} diff --git a/plugins/unityshell/src/ElapsedTimeMonitor.h b/plugins/unityshell/src/ElapsedTimeMonitor.h deleted file mode 100644 index 55f6d9d83..000000000 --- a/plugins/unityshell/src/ElapsedTimeMonitor.h +++ /dev/null @@ -1,47 +0,0 @@ -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- -/* -* Copyright (C) 2011 Canonical Ltd -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 3 as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* Authored by: Alex Launi <alex.launi@canonical.com> -*/ - -#ifndef UNITY_PERFORMANCE_ELAPSED_TIME_MONITOR -#define UNITY_PERFORMANCE_ELAPSED_TIME_MONITOR - -#include <glib.h> -#include <time.h> - -#include "Monitor.h" - -namespace unity { -namespace performance { - -class ElapsedTimeMonitor : public Monitor -{ -public: - std::string GetName() const; - -protected: - void StartMonitor(); - void StopMonitor(GVariantBuilder* builder); - -private: - struct timespec _start; -}; - -} -} - -#endif // UNITY_PERFORMANCE_ELAPSED_TIME_MONITOR diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index 6a6bc5c22..da44c28bb 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -81,6 +81,8 @@ /* Set up vtable symbols */ COMPIZ_PLUGIN_20090315(unityshell, unity::UnityPluginVTable); +namespace cgl = compiz::opengl; + namespace unity { using namespace launcher; @@ -142,6 +144,7 @@ UnityScreen::UnityScreen(CompScreen* screen) , allowWindowPaint(false) , _key_nav_mode_requested(false) , _last_output(nullptr) + , force_draw_countdown_ (0) , grab_index_ (0) , painting_tray_ (false) , last_scroll_event_(0) @@ -151,6 +154,9 @@ UnityScreen::UnityScreen(CompScreen* screen) , scale_just_activated_(false) , big_tick_(0) , screen_introspection_(screen) + , ignore_redraw_request_(false) + , dirty_helpers_on_this_frame_(false) + , back_buffer_age_(0) , is_desktop_active_(false) { Timer timer; @@ -392,6 +398,11 @@ UnityScreen::UnityScreen(CompScreen* screen) XSelectInput(display, GDK_ROOT_WINDOW(), PropertyChangeMask); LOG_INFO(logger) << "UnityScreen constructed: " << timer.ElapsedSeconds() << "s"; + UScreen::GetDefault()->resuming.connect([this]() { + /* Force paint 10 frames on resume */ + this->force_draw_countdown_ += 10; + }); + panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged)); minimize_speed_controller_.DurationChanged.connect( @@ -401,8 +412,13 @@ UnityScreen::UnityScreen(CompScreen* screen) WindowManager& wm = WindowManager::Default(); wm.initiate_spread.connect(sigc::mem_fun(this, &UnityScreen::OnInitiateSpread)); wm.terminate_spread.connect(sigc::mem_fun(this, &UnityScreen::OnTerminateSpread)); + wm.initiate_expo.connect(sigc::mem_fun(this, &UnityScreen::DamagePanelShadow)); + wm.terminate_expo.connect(sigc::mem_fun(this, &UnityScreen::DamagePanelShadow)); AddChild(&screen_introspection_); + + /* Track whole damage on the very first frame */ + cScreen->damageScreen(); } } @@ -477,6 +493,27 @@ void UnityScreen::OnTerminateSpread() UnityWindow::CleanupSharedTextures(); } +void UnityScreen::DamagePanelShadow() +{ + CompRect panelShadow; + + for (CompOutput const& output : screen->outputDevs()) + { + FillShadowRectForOutput(panelShadow, output); + cScreen->damageRegion(CompRegion(panelShadow)); + } +} + +void UnityScreen::OnViewHidden(nux::BaseWindow *bw) +{ + /* Count this as regular damage */ + nux::Geometry geometry(bw->GetAbsoluteGeometry()); + cScreen->damageRegion(CompRegion (geometry.x, + geometry.y, + geometry.width, + geometry.height)); +} + void UnityScreen::EnsureSuperKeybindings() { for (auto action : _shortcut_actions) @@ -569,6 +606,20 @@ void UnityScreen::setPanelShadowMatrix(GLMatrix const& matrix) panel_shadow_matrix_ = matrix; } +void UnityScreen::FillShadowRectForOutput(CompRect &shadowRect, + CompOutput const &output) +{ + if (_shadow_texture.empty ()) + return; + + float panel_h = static_cast<float>(panel_style_.panel_height); + float shadowX = output.x(); + float shadowY = output.y() + panel_h; + float shadowWidth = output.width(); + float shadowHeight = _shadow_texture[0]->height(); + shadowRect.setGeometry(shadowX, shadowY, shadowWidth, shadowHeight); +} + void UnityScreen::paintPanelShadow(CompRegion const& clip) { // You have no shadow texture. But how? @@ -596,11 +647,8 @@ void UnityScreen::paintPanelShadow(CompRegion const& clip) return; } - int shadowX = output->x(); - int shadowY = output->y() + panel_style_.panel_height; - int shadowWidth = output->width(); - int shadowHeight = _shadow_texture[0]->height(); - CompRect shadowRect(shadowX, shadowY, shadowWidth, shadowHeight); + CompRect shadowRect; + FillShadowRectForOutput(shadowRect, *output); CompRegion redraw(clip); redraw &= shadowRect; @@ -640,10 +688,10 @@ void UnityScreen::paintPanelShadow(CompRegion const& clip) float y2 = r.y2(); // Texture coordinates of the above rectangle: - float tx1 = (x1 - shadowX) / shadowWidth; - float ty1 = (y1 - shadowY) / shadowHeight; - float tx2 = (x2 - shadowX) / shadowWidth; - float ty2 = (y2 - shadowY) / shadowHeight; + float tx1 = (x1 - shadowRect.x()) / shadowRect.width(); + float ty1 = (y1 - shadowRect.y()) / shadowRect.height(); + float tx2 = (x2 - shadowRect.x()) / shadowRect.width(); + float ty2 = (y2 - shadowRect.y()) / shadowRect.height(); vertexData = { x1, y1, 0, @@ -707,28 +755,44 @@ void UnityScreen::paintDisplay() DrawPanelUnderDash(); - if (BackgroundEffectHelper::HasDirtyHelpers()) + /* Bind the currently bound draw framebuffer to the read framebuffer binding. + * The reason being that we want to use the results of nux images being + * drawn to this framebuffer in glCopyTexSubImage2D operations */ + GLint current_draw_binding = 0, + old_read_binding = 0; +#ifndef USE_GLES + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &old_read_binding); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, ¤t_draw_binding); + if (old_read_binding != current_draw_binding) + (*GL::bindFramebuffer) (GL_READ_FRAMEBUFFER_BINDING_EXT, current_draw_binding); +#else + glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤t_draw_binding); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_read_binding); +#endif + + /* If we have dirty helpers re-copy the backbuffer + * into a texture + * + * TODO: Make this faster by only copying the bits we + * need as opposed to the whole readbuffer */ + if (dirty_helpers_on_this_frame_) { auto gpu_device = nux::GetGraphicsDisplay()->GetGpuDevice(); auto graphics_engine = nux::GetGraphicsDisplay()->GetGraphicsEngine(); - - nux::ObjectPtr<nux::IOpenGLTexture2D> bg_texture = - graphics_engine->CreateTextureFromBackBuffer(0, 0, - screen->width(), - screen->height()); - gpu_device->backup_texture0_ = bg_texture; + gpu_device->backup_texture0_ = + graphics_engine->CreateTextureFromBackBuffer(0, 0, screen->width(), screen->height()); + back_buffer_age_ = 0; } nux::Geometry outputGeo(output->x (), output->y (), output->width (), output->height ()); BackgroundEffectHelper::monitor_rect_.Set(0, 0, screen->width(), screen->height()); - GLint fboID; - // Nux renders to the referenceFramebuffer when it's embedded. - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fboID); - wt->GetWindowCompositor().SetReferenceFramebuffer(fboID, outputGeo); + wt->GetWindowCompositor().SetReferenceFramebuffer(current_draw_binding, + old_read_binding, + outputGeo); nuxPrologue(); - wt->RenderInterfaceFromForeignCmd (&outputGeo); + wt->RenderInterfaceFromForeignCmd (outputGeo); nuxEpilogue(); for (Window tray_xid : panel_controller_->GetTrayXids()) @@ -745,9 +809,9 @@ void UnityScreen::paintDisplay() unsigned int oldGlAddGeometryIndex = uTrayWindow->gWindow->glAddGeometryGetCurrentIndex (); unsigned int oldGlDrawIndex = uTrayWindow->gWindow->glDrawGetCurrentIndex (); - attrib.opacity = OPAQUE; - attrib.brightness = BRIGHT; - attrib.saturation = COLOR; + attrib.opacity = COMPIZ_COMPOSITE_OPAQUE; + attrib.brightness = COMPIZ_COMPOSITE_BRIGHT; + attrib.saturation = COMPIZ_COMPOSITE_COLOR; oTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); @@ -1246,6 +1310,7 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib, doShellRepaint = force || ( !region.isEmpty() && ( !wt->GetDrawList().empty() || + !wt->GetPresentationListGeometries().empty() || (mask & PAINT_SCREEN_FULL_MASK) ) ); @@ -1281,10 +1346,142 @@ void UnityScreen::glPaintTransformedOutput(const GLScreenPaintAttrib& attrib, unsigned int mask) { allowWindowPaint = false; + + /* PAINT_SCREEN_FULL_MASK means that we are ignoring the damage + * region and redrawing the whole screen, so we should make all + * nux windows be added to the presentation list that intersect + * this output. + * + * However, damaging nux has a side effect of notifying compiz + * through onRedrawRequested that we need to queue another frame. + * In most cases that would be desirable, and in the case where + * we did that in damageCutoff, it would not be a problem as compiz + * does not queue up new frames for damage that can be processed + * on the current frame. However, we're now past damage cutoff, but + * a change in circumstances has required that we redraw all the nux + * windows on this frame. As such, we need to ensure that damagePending + * is not called as a result of queuing windows for redraw, as that + * would effectively result in a damage feedback loop in plugins that + * require screen transformations (eg, new frame -> plugin redraws full + * screen -> we reach this point and request another redraw implicitly) + */ + if (mask & PAINT_SCREEN_FULL_MASK) + { + ignore_redraw_request_ = true; + compizDamageNux(CompRegionRef(output->region())); + ignore_redraw_request_ = false; + + /* Fetch all the presentation list geometries - this will have the side + * effect of clearing any built-up damage state */ + std::vector<nux::Geometry> dirty = wt->GetPresentationListGeometries(); + } + gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask); paintPanelShadow(region); } +void UnityScreen::updateBlurDamage() +{ + /* If there are enabled helpers, we want to apply damage + * based on how old our tracking fbo is since we may need + * to redraw some of the blur regions if there has been + * damage since we last bound it + * + * XXX: Unfortunately there's a nasty feedback loop here, and not + * a whole lot we can do about it. If part of the damage from any frame + * intersects a nux window, we have to mark the entire region that the + * nux window covers as damaged, because nux does not have any concept + * of geometry clipping. That damage will feed back to us on the next frame. + */ + if (BackgroundEffectHelper::HasEnabledHelpers()) + { + cScreen->applyDamageForFrameAge(back_buffer_age_); + + /* + * Prioritise user interaction over active blur updates. So the general + * slowness of the active blur doesn't affect the UI interaction performance. + * + * Also, BackgroundEffectHelper::ProcessDamage() is causing a feedback loop + * while the dash is open. Calling it results in the NEXT frame (and the + * current one?) to get some damage. This GetDrawList().empty() check avoids + * that feedback loop and allows us to idle correctly. + * + * We are doing damage processing for the blurs here, as this represents + * the most up to date compiz damage under the nux windows. + */ + if (wt->GetDrawList().empty()) + { + CompRect::vector const& rects(buffered_compiz_damage_this_frame_.rects()); + for (CompRect const& r : rects) + { + nux::Geometry geo(r.x(), r.y(), r.width(), r.height()); + BackgroundEffectHelper::ProcessDamage(geo); + } + } + } +} + +void UnityScreen::damageCutoff() +{ + if (force_draw_countdown_) + { + typedef nux::WindowCompositor::WeakBaseWindowPtr WeakBaseWindowPtr; + + /* We have to force-redraw the whole scene because + * of a bug in the nvidia driver that causes framebuffers + * to be trashed on resume for a few swaps */ + wt->GetWindowCompositor().ForEachBaseWindow([](WeakBaseWindowPtr const &w) { + w->QueueDraw(); + }); + + force_draw_countdown_--; + } + + /* At this point we want to take all of the compiz damage + * for this frame and use it to determine which blur regions + * need to be redrawn. We don't want to do this any later because + * the nux damage is logically on top of the blurs and doesn't + * affect them */ + updateBlurDamage(); + + /* Determine nux region damage last */ + cScreen->damageCutoff(); + + CompRegion damage_buffer, last_damage_buffer; + + do + { + last_damage_buffer = damage_buffer; + + /* First apply any damage accumulated to nux to see + * what windows need to be redrawn there */ + compizDamageNux(buffered_compiz_damage_this_frame_); + + /* Apply the redraw regions to compiz so that we can + * draw this frame with that region included */ + determineNuxDamage(damage_buffer); + + /* We want to track the nux damage here as we will use it to + * determine if we need to present other nux windows too */ + cScreen->damageRegion(damage_buffer); + + /* If we had to put more damage into the damage buffer then + * damage compiz with it and keep going */ + } while (last_damage_buffer != damage_buffer); + + /* Clear damage buffer */ + buffered_compiz_damage_last_frame_ = buffered_compiz_damage_this_frame_; + buffered_compiz_damage_this_frame_ = CompRegion(); + + /* Tell nux that any damaged windows should be redrawn on the next + * frame and not this one */ + wt->ForeignFrameCutoff(); + + /* We need to track this per-frame to figure out whether or not + * to bind the contents fbo on each monitor pass */ + dirty_helpers_on_this_frame_ = BackgroundEffectHelper::HasDirtyHelpers(); +} + void UnityScreen::preparePaint(int ms) { cScreen->preparePaint(ms); @@ -1298,8 +1495,6 @@ void UnityScreen::preparePaint(int ms) didShellRepaint = false; panelShadowPainted = CompRegion(); firstWindowAboveShell = NULL; - - compizDamageNux(cScreen->currentDamage()); } void UnityScreen::donePaint() @@ -1313,11 +1508,22 @@ void UnityScreen::donePaint() * I think this is a Nux bug. ClearDrawList should ideally also mark all * the queued views as draw_cmd_queued_=false. */ + + /* To prevent any potential overflow problems, we are assuming here + * that compiz caps the maximum number of frames tracked at 10, so + * don't increment the age any more than 11 */ + if (back_buffer_age_ < 11) + ++back_buffer_age_; + if (didShellRepaint) wt->ClearDrawList(); + /* Tell nux that a new frame is now beginning and any damaged windows should + * now be painted on this frame */ + wt->ForeignFrameEnded(); + if (animation_controller_->HasRunningAnimations()) - nuxDamageCompiz(); + onRedrawRequested(); for (auto it = ShowdesktopHandler::animating_windows.begin(); it != ShowdesktopHandler::animating_windows.end();) { @@ -1341,90 +1547,53 @@ void UnityScreen::donePaint() cScreen->donePaint(); } -void redraw_view_if_damaged(nux::ObjectPtr<nux::View> const& view, CompRegion const& damage) -{ - if (!view || view->IsRedrawNeeded()) - return; - - auto const& geo = view->GetAbsoluteGeometry(); - CompRegion region(geo.x, geo.y, geo.width, geo.height); - - if (damage.intersects(region)) - view->NeedSoftRedraw(); -} - void UnityScreen::compizDamageNux(CompRegion const& damage) { - if (!launcher_controller_) - return; - - /* - * Prioritise user interaction over active blur updates. So the general - * slowness of the active blur doesn't affect the UI interaction performance. + /* Ask nux to present anything in our damage region * - * Also, BackgroundEffectHelper::ProcessDamage() is causing a feedback loop - * while the dash is open. Calling it results in the NEXT frame (and the - * current one?) to get some damage. This GetDrawList().empty() check avoids - * that feedback loop and allows us to idle correctly. + * Note: This is using a new nux API, to "present" windows + * to the screen, as opposed to drawing them. The difference is + * important. The former will just draw the window backing texture + * directly to the screen, the latter will re-draw the entire window. + * + * The former is a lot faster, do not use QueueDraw unless the contents + * of the window need to be re-drawn. */ - if (wt->GetDrawList().empty() && BackgroundEffectHelper::HasDamageableHelpers()) + CompRect::vector rects (damage.rects()); + for (const CompRect &r : rects) { - CompRect::vector const& rects(damage.rects()); - for (CompRect const& r : rects) - { - nux::Geometry geo(r.x(), r.y(), r.width(), r.height()); - BackgroundEffectHelper::ProcessDamage(geo); - } + nux::Geometry g(r.x(), r.y(), r.width(), r.height()); + wt->PresentWindowsIntersectingGeometryOnThisFrame(g); } +} - if (dash_controller_->IsVisible()) - redraw_view_if_damaged(dash_controller_->Dash(), damage); +/* Grab changed nux regions and add damage rects for them */ +void UnityScreen::determineNuxDamage(CompRegion &nux_damage) +{ + /* Fetch all the dirty geometry from nux and aggregate it */ + std::vector<nux::Geometry> dirty = wt->GetPresentationListGeometries(); - if (hud_controller_->IsVisible()) - redraw_view_if_damaged(hud_controller_->HudView(), damage); + for (auto const& geo : dirty) + nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height); - auto const& launchers = launcher_controller_->launchers(); - for (auto const& launcher : launchers) + /* Special case, we need to redraw the panel shadow on panel updates */ + for (auto const& panel_geo : panel_controller_->GetGeometries()) { - if (!launcher->Hidden()) + CompRect panel_rect(panel_geo.x, + panel_geo.y, + panel_geo.width, + panel_geo.height); + + if (nux_damage.intersects(panel_rect)) { - redraw_view_if_damaged(launcher, damage); - redraw_view_if_damaged(launcher->GetActiveTooltip(), damage); - redraw_view_if_damaged(launcher->GetDraggedIcon(), damage); + foreach (CompOutput const& o, screen->outputDevs()) + { + CompRect shadowRect; + FillShadowRectForOutput(shadowRect, o); + nux_damage += shadowRect; + } } } - - for (auto const& panel : panel_controller_->panels()) - redraw_view_if_damaged(panel, damage); - - if (QuicklistManager* qm = QuicklistManager::Default()) - redraw_view_if_damaged(qm->Current(), damage); - - if (switcher_controller_->Visible()) - redraw_view_if_damaged(switcher_controller_->GetView(), damage); -} - -/* Grab changed nux regions and add damage rects for them */ -void UnityScreen::nuxDamageCompiz() -{ - /* - * If Nux is going to redraw anything then we have to tell Compiz to - * redraw everything. This is because Nux has a bad habit (bug??) of drawing - * more than just the regions of its DrawList. (LP: #1036519) - * - * Forunately, this does not happen on most frames. Only when the Unity - * Shell needs to redraw something. - * - * TODO: Try to figure out why redrawing the panel makes the launcher also - * redraw even though the launcher's geometry is not in DrawList, and - * stop it. Then maybe we can revert back to the old code below #else. - */ - if (!wt->GetDrawList().empty() || animation_controller_->HasRunningAnimations()) - { - cScreen->damageRegionSetEnabled(this, false); - cScreen->damageScreen(); - cScreen->damageRegionSetEnabled(this, true); - } } /* handle X Events */ @@ -1689,7 +1858,7 @@ void UnityScreen::handleEvent(XEvent* event) void UnityScreen::damageRegion(const CompRegion ®ion) { - compizDamageNux(region); + buffered_compiz_damage_this_frame_ += region; cScreen->damageRegion(region); } @@ -2985,11 +3154,16 @@ void UnityScreen::initUnity(nux::NThread* thread, void* InitData) nux::ColorLayer background(nux::color::Transparent); static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background); LOG_INFO(logger) << "UnityScreen::initUnity: " << timer.ElapsedSeconds() << "s"; + + nux::GetWindowCompositor() + .sigHiddenViewWindow.connect(sigc::mem_fun(self, + &UnityScreen::OnViewHidden)); } void UnityScreen::onRedrawRequested() { - nuxDamageCompiz(); + if (!ignore_redraw_request_) + cScreen->damagePending(); } /* Handle option changes and plug that into nux windows */ @@ -3179,6 +3353,8 @@ void UnityScreen::Relayout() << " h=" << geo.height; needsRelayout = false; + + DamagePanelShadow(); } /* Handle changes in the number of workspaces by showing the switcher @@ -3504,6 +3680,7 @@ void UnityWindow::AddProperties(GVariantBuilder* builder) .add("vertically_maximized", wm.IsWindowVerticallyMaximized(xid)) .add("minimized", wm.IsWindowMinimized(xid)) .add("scaled", scaled) + .add("scaled_close_geo", close_button_geo_) .add("scaled_close_x", close_button_geo_.x) .add("scaled_close_y", close_button_geo_.y) .add("scaled_close_width", close_button_geo_.width) diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index 69a25b636..b4e5292cd 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -32,9 +32,22 @@ #include <scale/scale.h> #include <core/core.h> #include <core/pluginclasshandler.h> -#include <composite/composite.h> #include <opengl/opengl.h> +// These fixes some definitions from the composite header +#ifdef COLOR +#define COMPIZ_COMPOSITE_COLOR 0xffff +#undef COLOR +#endif +#ifdef OPAQUE +#define COMPIZ_COMPOSITE_OPAQUE 0xffff +#undef OPAQUE +#endif +#ifdef BRIGHT +#define COMPIZ_COMPOSITE_BRIGHT 0xffff +#undef BRIGHT +#endif + #include "unityshell_options.h" #include "Introspectable.h" @@ -98,9 +111,11 @@ public: /* nux draw wrapper */ void paintDisplay(); - void paintPanelShadow(const CompRegion& clip); + void paintPanelShadow(CompRegion const& clip); void setPanelShadowMatrix(const GLMatrix& matrix); + void updateBlurDamage(); + void damageCutoff(); void preparePaint (int ms); void paintFboForOutput (CompOutput *output); void donePaint (); @@ -219,7 +234,7 @@ private: void initLauncher(); void compizDamageNux(CompRegion const& region); - void nuxDamageCompiz(); + void determineNuxDamage(CompRegion &nux_damage); void onRedrawRequested(); void Relayout(); @@ -241,6 +256,12 @@ private: void OnInitiateSpread(); void OnTerminateSpread(); + void DamagePanelShadow(); + + void OnViewHidden(nux::BaseWindow *bw); + + void RestoreWindow(GVariant* data); + bool SaveInputThenFocus(const guint xid); void OnPanelStyleChanged(); @@ -249,6 +270,8 @@ private: void DrawPanelUnderDash(); + void FillShadowRectForOutput(CompRect &shadowRect, + CompOutput const &output); unsigned CompizModifiersToNux(unsigned input) const; unsigned XModifiersToNux(unsigned input) const; @@ -309,6 +332,12 @@ private: bool _key_nav_mode_requested; CompOutput* _last_output; + /* a small count-down work-a-around + * to force full redraws of the shell + * a certain number of frames after a + * suspend / resume cycle */ + unsigned int force_draw_countdown_; + CompRegion panelShadowPainted; CompRegion nuxRegion; CompRegion fullscreenRegion; @@ -342,6 +371,13 @@ private: UBusManager ubus_manager_; glib::SourceManager sources_; + CompRegion buffered_compiz_damage_this_frame_; + CompRegion buffered_compiz_damage_last_frame_; + bool ignore_redraw_request_; + bool dirty_helpers_on_this_frame_; + + unsigned int back_buffer_age_; + bool is_desktop_active_; friend class UnityWindow; diff --git a/shutdown/SessionButton.cpp b/shutdown/SessionButton.cpp index 8af0b6ee7..72000a26a 100644 --- a/shutdown/SessionButton.cpp +++ b/shutdown/SessionButton.cpp @@ -130,6 +130,7 @@ void Button::AddProperties(GVariantBuilder* builder) unity::variant::BuilderWrapper(builder) .add("highlighted", highlighted()) .add("label", label()) + .add("label_color", label_view_->GetTextColor()) .add("label_visible", label_view_->GetTextColor() != nux::color::Transparent); } diff --git a/tests/test_glib_variant.cpp b/tests/test_glib_variant.cpp index 0f3214fd9..d6659e8aa 100644 --- a/tests/test_glib_variant.cpp +++ b/tests/test_glib_variant.cpp @@ -71,6 +71,121 @@ TEST(TestGLibVariant, ConstructSteal) EXPECT_FALSE(IsFloating(v)); } +TEST(TestGLibVariant, ConstructNullptr) +{ + Variant v(nullptr); + EXPECT_FALSE(v); +} + +TEST(TestGLibVariant, ConstructNull) +{ + GVariant* value = NULL; + Variant v(value); + EXPECT_FALSE(v); +} + +TEST(TestGLibVariant, ConstructString) +{ + std::string value = "UnityVariant"; + Variant v(value); + EXPECT_EQ(value, g_variant_get_string(v, nullptr)); +} + +TEST(TestGLibVariant, ConstructCharString) +{ + const char* value = "UnityVariantCharStr"; + Variant v(value); + EXPECT_STREQ(value, g_variant_get_string(v, nullptr)); +} + +TEST(TestGLibVariant, ConstructByte) +{ + unsigned char value = g_random_int_range(0, 256); + Variant v(value); + EXPECT_EQ(value, g_variant_get_byte(v)); +} + +TEST(TestGLibVariant, ConstructInt16) +{ + int16_t value = g_random_int_range(G_MININT16, G_MAXINT16); + Variant v(value); + EXPECT_EQ(value, g_variant_get_int16(v)); +} + +TEST(TestGLibVariant, ConstructUInt16) +{ + uint16_t value = g_random_int_range(0, G_MAXUINT16); + Variant v(value); + EXPECT_EQ(value, g_variant_get_uint16(v)); +} + +TEST(TestGLibVariant, ConstructInt32) +{ + int32_t value = g_random_int_range(G_MININT32, G_MAXINT32); + Variant v(value); + EXPECT_EQ(value, g_variant_get_int32(v)); +} + +TEST(TestGLibVariant, ConstructUInt32) +{ + uint32_t value = g_random_int(); + Variant v(value); + EXPECT_EQ(value, g_variant_get_uint32(v)); +} + +TEST(TestGLibVariant, ConstructInt64) +{ + int64_t value = g_random_int_range(G_MININT, G_MAXINT); + Variant v(value); + EXPECT_EQ(value, g_variant_get_int64(v)); +} + +TEST(TestGLibVariant, ConstructUInt64) +{ + uint64_t value = g_random_int(); + Variant v(value); + EXPECT_EQ(value, g_variant_get_uint64(v)); +} + +TEST(TestGLibVariant, ConstructBool) +{ + bool value = g_random_int(); + Variant v(value); + EXPECT_EQ(value, g_variant_get_boolean(v)); +} + +TEST(TestGLibVariant, ConstructDouble) +{ + double value = g_random_int(); + Variant v(value); + EXPECT_DOUBLE_EQ(value, g_variant_get_double(v)); +} + +TEST(TestGLibVariant, ConstructFloat) +{ + float value = g_random_int(); + Variant v(value); + EXPECT_FLOAT_EQ(value, static_cast<float>(g_variant_get_double(v))); +} + +TEST(TestGLibVariant, ConstructNumericInt) +{ + Variant v0(0); + EXPECT_EQ(0, v0.GetInt32()); + + Variant v1(123456789); + EXPECT_EQ(123456789, v1.GetInt32()); +} + +TEST(TestGLibVariant, ConstructNumericDouble) +{ + Variant v0(0.0f); + EXPECT_EQ(0.0f, v0.GetDouble()); + + Variant v1(0.987654321); + EXPECT_EQ(0.987654321, v1.GetDouble()); +} + TEST(TestGLibVariant, Copy) { Variant v1 (g_variant_new_string ("bar")); @@ -108,6 +223,179 @@ TEST(TestGLibVariant, AssignSame) EXPECT_TRUE(ValuesEqual(v, raw_variant)); } +TEST(TestGLibVariant, ConstructHintsMap) +{ + Variant v({ + {"charstring-key", g_variant_new_string("charstring-value")}, + {"string-key", g_variant_new_string(std::string("string-value").c_str())}, + {"gint32-key", g_variant_new_int32(-1)}, + {"guint32-key", g_variant_new_uint32(2)}, + {"gint64-key", g_variant_new_int64(-3)}, + {"guint64-key", g_variant_new_uint64(4)}, + {"float-key", g_variant_new_double((float)1.1)}, + {"double-key", g_variant_new_double(2.2)}, + {"bool-key", g_variant_new_boolean(true)}, + {"variant-key", g_variant_new_int32(123)} + }); + + EXPECT_EQ("charstring-value", Variant(g_variant_lookup_value(v, "charstring-key", nullptr)).GetString()); + EXPECT_EQ("string-value", Variant(g_variant_lookup_value(v, "string-key", nullptr)).GetString()); + EXPECT_EQ(-1, Variant(g_variant_lookup_value(v, "gint32-key", nullptr)).GetInt32()); + EXPECT_EQ(2, Variant(g_variant_lookup_value(v, "guint32-key", nullptr)).GetUInt32()); + EXPECT_EQ(-3, Variant(g_variant_lookup_value(v, "gint64-key", nullptr)).GetInt64()); + EXPECT_EQ(4, Variant(g_variant_lookup_value(v, "guint64-key", nullptr)).GetUInt64()); + EXPECT_FLOAT_EQ(1.1, Variant(g_variant_lookup_value(v, "float-key", nullptr)).GetFloat()); + EXPECT_DOUBLE_EQ(2.2, Variant(g_variant_lookup_value(v, "double-key", nullptr)).GetDouble()); + EXPECT_EQ(true, Variant(g_variant_lookup_value(v, "bool-key", nullptr)).GetBool()); + EXPECT_EQ(123, Variant(g_variant_lookup_value(v, "variant-key", nullptr)).GetInt32()); +} + +TEST(TestGLibVariant, AssignString) +{ + std::string value = "UnityVariant"; + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_string(v, nullptr)); +} + +TEST(TestGLibVariant, AssignCharString) +{ + const char* value = "UnityVariantCharStr"; + Variant v; + v = value; + EXPECT_STREQ(value, g_variant_get_string(v, nullptr)); +} + +TEST(TestGLibVariant, AssignByte) +{ + unsigned char value = g_random_int_range(0, 256); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_byte(v)); +} + +TEST(TestGLibVariant, AssignInt16) +{ + int16_t value = g_random_int_range(G_MININT16, G_MAXINT16); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_int16(v)); +} + +TEST(TestGLibVariant, AssignUInt16) +{ + uint16_t value = g_random_int_range(0, G_MAXUINT16); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_uint16(v)); +} + +TEST(TestGLibVariant, AssignInt32) +{ + int32_t value = g_random_int_range(G_MININT32, G_MAXINT32); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_int32(v)); +} + +TEST(TestGLibVariant, AssignUInt32) +{ + uint32_t value = g_random_int(); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_uint32(v)); +} + +TEST(TestGLibVariant, AssignInt64) +{ + int64_t value = g_random_int_range(G_MININT, G_MAXINT); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_int64(v)); +} + +TEST(TestGLibVariant, AssignUInt64) +{ + uint64_t value = g_random_int(); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_uint64(v)); +} + +TEST(TestGLibVariant, AssignBool) +{ + bool value = g_random_int(); + Variant v; + v = value; + EXPECT_EQ(value, g_variant_get_boolean(v)); +} + +TEST(TestGLibVariant, AssignDouble) +{ + double value = g_random_int(); + Variant v; + v = value; + EXPECT_DOUBLE_EQ(value, g_variant_get_double(v)); +} + +TEST(TestGLibVariant, AssignFloat) +{ + float value = g_random_int(); + Variant v; + v = value; + EXPECT_FLOAT_EQ(value, static_cast<float>(g_variant_get_double(v))); +} + +TEST(TestGLibVariant, AssignNumericInt) +{ + Variant v0; + v0 = 0; + EXPECT_EQ(0, v0.GetInt32()); + + Variant v1; + v1 = 123456789; + EXPECT_EQ(123456789, v1.GetInt32()); +} + +TEST(TestGLibVariant, AssignNumericDouble) +{ + Variant v0; + v0 = 0.0f; + EXPECT_EQ(0.0f, v0.GetDouble()); + + Variant v1; + v1 = 0.987654321; + EXPECT_EQ(0.987654321, v1.GetDouble()); +} + +TEST(TestGLibVariant, AssignHintsMap) +{ + Variant v; + v = { + {"charstring-key", g_variant_new_string("charstring-value")}, + {"string-key", g_variant_new_string(std::string("string-value").c_str())}, + {"gint32-key", g_variant_new_int32(-1)}, + {"guint32-key", g_variant_new_uint32(2)}, + {"gint64-key", g_variant_new_int64(-3)}, + {"guint64-key", g_variant_new_uint64(4)}, + {"float-key", g_variant_new_double((float)1.1)}, + {"double-key", g_variant_new_double(2.2)}, + {"bool-key", g_variant_new_boolean(true)}, + {"variant-key", g_variant_new_int32(123)} + }; + + EXPECT_EQ("charstring-value", Variant(g_variant_lookup_value(v, "charstring-key", nullptr)).GetString()); + EXPECT_EQ("string-value", Variant(g_variant_lookup_value(v, "string-key", nullptr)).GetString()); + EXPECT_EQ(-1, Variant(g_variant_lookup_value(v, "gint32-key", nullptr)).GetInt32()); + EXPECT_EQ(2, Variant(g_variant_lookup_value(v, "guint32-key", nullptr)).GetUInt32()); + EXPECT_EQ(-3, Variant(g_variant_lookup_value(v, "gint64-key", nullptr)).GetInt64()); + EXPECT_EQ(4, Variant(g_variant_lookup_value(v, "guint64-key", nullptr)).GetUInt64()); + EXPECT_FLOAT_EQ(1.1, Variant(g_variant_lookup_value(v, "float-key", nullptr)).GetFloat()); + EXPECT_DOUBLE_EQ(2.2, Variant(g_variant_lookup_value(v, "double-key", nullptr)).GetDouble()); + EXPECT_EQ(true, Variant(g_variant_lookup_value(v, "bool-key", nullptr)).GetBool()); + EXPECT_EQ(123, Variant(g_variant_lookup_value(v, "variant-key", nullptr)).GetInt32()); +} + TEST(TestGLibVariant, KeepsRef) { GVariant *gv = g_variant_new_int32 (456); @@ -141,17 +429,16 @@ TEST(TestGLibVariant, HintsMap) GVariantBuilder b; g_variant_builder_init (&b, G_VARIANT_TYPE ("a{sv}")); - variant::BuilderWrapper bw (&b); - bw.add ("charstring-key", "charstring-value"); - bw.add ("string-key", std::string("string-value")); - bw.add ("gint32-key", (gint32)-1); - bw.add ("guint32-key", (guint32)-2); - bw.add ("gint64-key", (gint64)-3); - bw.add ("guint64-key", (guint64)-4); - bw.add ("float-key", (float)1.1); - bw.add ("double-key", (double)2.2); - bw.add ("bool-key", true); - bw.add ("variant-key", g_variant_new_int32(123)); + g_variant_builder_add(&b, "{sv}", "charstring-key", g_variant_new_string("charstring-value")); + g_variant_builder_add(&b, "{sv}", "string-key", g_variant_new_string(std::string("string-value").c_str())); + g_variant_builder_add(&b, "{sv}", "gint32-key", g_variant_new_int32(-1)); + g_variant_builder_add(&b, "{sv}", "guint32-key", g_variant_new_uint32(-2)); + g_variant_builder_add(&b, "{sv}", "gint64-key", g_variant_new_int64(-3)); + g_variant_builder_add(&b, "{sv}", "guint64-key", g_variant_new_uint64(-4)); + g_variant_builder_add(&b, "{sv}", "float-key", g_variant_new_double((float)1.1)); + g_variant_builder_add(&b, "{sv}", "double-key", g_variant_new_double(2.2)); + g_variant_builder_add(&b, "{sv}", "bool-key", g_variant_new_boolean(true)); + g_variant_builder_add(&b, "{sv}", "variant-key", g_variant_new_int32(123)); GVariant *dict_variant = g_variant_builder_end (&b); Variant dict (g_variant_new_tuple (&dict_variant, 1)); @@ -208,13 +495,76 @@ TEST(TestGLibVariant, GetString) EXPECT_EQ(v5.GetString(), "Yeah!!!"); } +TEST(TestGLibVariant, GetByte) +{ + guchar value = g_random_int_range(0, 256); + Variant v1(g_variant_new_byte(value)); + EXPECT_EQ(v1.GetByte(), value); + + value = g_random_int_range(0, 256); + Variant v2(g_variant_new("(y)", value)); + EXPECT_EQ(v2.GetByte(), value); + + Variant v3(g_variant_new("(ny)", value, "fooostring")); + EXPECT_EQ(v3.GetByte(), 0); + + Variant v4; + EXPECT_EQ(v4.GetByte(), 0); + + value = g_random_int_range(0, 256); + Variant v5(g_variant_new_variant(g_variant_new_byte(value))); + EXPECT_EQ(v5.GetByte(), value); +} + +TEST(TestGLibVariant, GetInt16) +{ + gint16 value = g_random_int_range(G_MININT16, G_MAXINT16); + Variant v1(g_variant_new_int16(value)); + EXPECT_EQ(v1.GetInt16(), value); + + value = g_random_int_range(G_MININT16, G_MAXINT16); + Variant v2(g_variant_new("(n)", value)); + EXPECT_EQ(v2.GetInt16(), value); + + Variant v3(g_variant_new("(ns)", value, "fooostring")); + EXPECT_EQ(v3.GetInt16(), 0); + + Variant v4; + EXPECT_EQ(v4.GetInt16(), 0); + + value = g_random_int_range(G_MININT16, G_MAXINT16); + Variant v5(g_variant_new_variant(g_variant_new_int16(value))); + EXPECT_EQ(v5.GetInt16(), value); +} + +TEST(TestGLibVariant, GetUInt16) +{ + guint16 value = g_random_int(); + Variant v1(g_variant_new_uint16(value)); + EXPECT_EQ(v1.GetUInt16(), value); + + value = g_random_int(); + Variant v2(g_variant_new("(q)", value)); + EXPECT_EQ(v2.GetUInt16(), value); + + Variant v3(g_variant_new("(qi)", value, G_MAXINT16)); + EXPECT_EQ(v3.GetUInt16(), 0); + + Variant v4; + EXPECT_EQ(v4.GetUInt16(), 0); + + value = g_random_int(); + Variant v5(g_variant_new_variant(g_variant_new_uint16(value))); + EXPECT_EQ(v5.GetUInt16(), value); +} + TEST(TestGLibVariant, GetInt32) { - gint32 value = g_random_int_range(G_MININT, G_MAXINT); + gint32 value = g_random_int_range(G_MININT32, G_MAXINT32); Variant v1(g_variant_new_int32(value)); EXPECT_EQ(v1.GetInt32(), value); - value = g_random_int_range(G_MININT, G_MAXINT); + value = g_random_int_range(G_MININT32, G_MAXINT32); Variant v2(g_variant_new("(i)", value)); EXPECT_EQ(v2.GetInt32(), value); @@ -224,7 +574,7 @@ TEST(TestGLibVariant, GetInt32) Variant v4; EXPECT_EQ(v4.GetInt32(), 0); - value = g_random_int_range(G_MININT, G_MAXINT); + value = g_random_int_range(G_MININT32, G_MAXINT32); Variant v5(g_variant_new_variant(g_variant_new_int32(value))); EXPECT_EQ(v5.GetInt32(), value); } @@ -239,7 +589,7 @@ TEST(TestGLibVariant, GetUInt32) Variant v2(g_variant_new("(u)", value)); EXPECT_EQ(v2.GetUInt32(), value); - Variant v3(g_variant_new("(ui)", value, G_MAXINT)); + Variant v3(g_variant_new("(ui)", value, G_MAXUINT32)); EXPECT_EQ(v3.GetUInt32(), 0); Variant v4; @@ -250,6 +600,48 @@ TEST(TestGLibVariant, GetUInt32) EXPECT_EQ(v5.GetUInt32(), value); } +TEST(TestGLibVariant, GetInt64) +{ + gint64 value = g_random_int_range(G_MININT, G_MAXINT); + Variant v1(g_variant_new_int64(value)); + EXPECT_EQ(v1.GetInt64(), value); + + value = g_random_int_range(G_MININT, G_MAXINT); + Variant v2(g_variant_new("(x)", value)); + EXPECT_EQ(v2.GetInt64(), value); + + Variant v3(g_variant_new("(xs)", value, "fooostring")); + EXPECT_EQ(v3.GetInt64(), 0); + + Variant v4; + EXPECT_EQ(v4.GetInt64(), 0); + + value = g_random_int_range(G_MININT, G_MAXINT); + Variant v5(g_variant_new_variant(g_variant_new_int64(value))); + EXPECT_EQ(v5.GetInt64(), value); +} + +TEST(TestGLibVariant, GetUInt64) +{ + guint64 value = g_random_int(); + Variant v1(g_variant_new_uint64(value)); + EXPECT_EQ(v1.GetUInt64(), value); + + value = g_random_int(); + Variant v2(g_variant_new("(t)", value)); + EXPECT_EQ(v2.GetUInt64(), value); + + Variant v3(g_variant_new("(ti)", value, G_MAXINT64)); + EXPECT_EQ(v3.GetUInt64(), 0); + + Variant v4; + EXPECT_EQ(v4.GetUInt64(), 0); + + value = g_random_int(); + Variant v5(g_variant_new_variant(g_variant_new_uint64(value))); + EXPECT_EQ(v5.GetUInt64(), value); +} + TEST(TestGLibVariant, GetBool) { gboolean value = (g_random_int() % 2) ? TRUE : FALSE; diff --git a/tests/test_panel_menu_view.cpp b/tests/test_panel_menu_view.cpp index e900e04cb..9bb9cbac5 100644 --- a/tests/test_panel_menu_view.cpp +++ b/tests/test_panel_menu_view.cpp @@ -81,7 +81,7 @@ TEST_F(TestPanelMenuView, Escaping) UBusManager ubus; ubus.SendMessage(UBUS_LAUNCHER_START_KEY_NAV); ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(escapedText)); + glib::Variant(escapedText)); Utils::WaitUntilMSec([this] {return menu_view.GetCurrentTitle() == escapedText;}); diff --git a/tests/test_results.cpp b/tests/test_results.cpp index 02336effd..428c46d22 100644 --- a/tests/test_results.cpp +++ b/tests/test_results.cpp @@ -279,8 +279,8 @@ TEST_F(TestResults, LocalResult_FromToVariant) local_result_1.comment = "comment"; local_result_1.dnd_uri = "dnd_uri"; - local_result_1.hints["key1"] = g_variant_new_string("value1"); - local_result_1.hints["key2"] = g_variant_new_string("value2"); + local_result_1.hints["key1"] = glib::Variant("value1"); + local_result_1.hints["key2"] = glib::Variant("value2"); glib::Variant variant_value = local_result_1.Variant(); LocalResult local_result_2 = LocalResult::FromVariant(variant_value); diff --git a/unity-shared/BackgroundEffectHelper.cpp b/unity-shared/BackgroundEffectHelper.cpp index d48aad978..0d86d3aba 100644 --- a/unity-shared/BackgroundEffectHelper.cpp +++ b/unity-shared/BackgroundEffectHelper.cpp @@ -74,7 +74,7 @@ void BackgroundEffectHelper::ProcessDamage(nux::Geometry const& geo) if (bg_effect_helper->cache_dirty || !bg_effect_helper->owner || !bg_effect_helper->enabled) continue; - if (!geo.Intersect(bg_effect_helper->blur_geometry_).IsNull()) + if (geo.IsIntersecting(bg_effect_helper->blur_geometry_)) { bg_effect_helper->DirtyCache(); } diff --git a/unity-shared/DebugDBusInterface.cpp b/unity-shared/DebugDBusInterface.cpp index 16dfa6795..b92a3bd36 100644 --- a/unity-shared/DebugDBusInterface.cpp +++ b/unity-shared/DebugDBusInterface.cpp @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2010 Canonical Ltd + * Copyright (C) 2010-2013 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -15,20 +15,16 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Alex Launi <alex.launi@canonical.com> + * Thomi Richards <thomi.richards@canonical.com> + * Marco Trevisan <marco.trevisan@canonical.com> */ -#include <queue> -#include <iostream> #include <fstream> #include <sstream> -#include <iostream> #include <boost/algorithm/string.hpp> -#include <boost/algorithm/string/split.hpp> -#include <boost/algorithm/string/classification.hpp> -#include <boost/bind.hpp> #include <NuxCore/Logger.h> #include <NuxCore/LoggingWriter.h> -#include <xpathselect/node.h> +#include <UnityCore/Variant.h> #include <xpathselect/xpathselect.h> #include <dlfcn.h> @@ -45,17 +41,25 @@ namespace { namespace local { + const std::string PROTOCOL_VERSION = "1.4"; + const std::string XPATH_SELECT_LIB = "libxpathselect.so.1.4"; + std::ofstream output_file; - void* xpathselect_driver_ = NULL; + void* xpathselect_driver_ = nullptr; - class IntrospectableAdapter: public xpathselect::Node + class IntrospectableAdapter : public std::enable_shared_from_this<IntrospectableAdapter>, public xpathselect::Node { public: - typedef std::shared_ptr<IntrospectableAdapter> Ptr; - IntrospectableAdapter(Introspectable* node, std::string const& parent_path) - : node_(node) + typedef std::shared_ptr<IntrospectableAdapter const> Ptr; + IntrospectableAdapter(Introspectable* node, IntrospectableAdapter::Ptr const& parent = nullptr) + : node_(node) + , parent_(parent) + , full_path_((parent_ ? parent_->GetPath() : "") + "/" + GetName()) + {} + + int32_t GetId() const { - full_path_ = parent_path + "/" + GetName(); + return node_->GetIntrospectionId(); } std::string GetName() const @@ -68,145 +72,124 @@ namespace local return full_path_; } - bool MatchProperty(const std::string& name, const std::string& value) const + Node::Ptr GetParent() const { - bool matches = false; + return parent_; + } + + bool MatchStringProperty(std::string const& name, std::string const& value) const + { + auto const& prop_value = GetPropertyValue(name); + + if (prop_value) + { + if (!g_variant_is_of_type(prop_value, G_VARIANT_TYPE_STRING)) + { + LOG_WARNING(logger) << "Unable to match '"<< name << "', it's not a string property."; + return false; + } + + return (prop_value.GetString() == value); + } - GVariantBuilder child_builder; - g_variant_builder_init(&child_builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&child_builder, "{sv}", "id", g_variant_new_uint64(node_->GetIntrospectionId())); - node_->AddProperties(&child_builder); - GVariant* prop_dict = g_variant_builder_end(&child_builder); - GVariant *prop_value = g_variant_lookup_value(prop_dict, name.c_str(), NULL); + return false; + } + + bool MatchBooleanProperty(std::string const& name, bool value) const + { + auto const& prop_value = GetPropertyValue(name); - if (prop_value != NULL) + if (prop_value) + { + if (!g_variant_is_of_type(prop_value, G_VARIANT_TYPE_BOOLEAN)) + { + LOG_WARNING(logger) << "Unable to match '"<< name << "', it's not a boolean property."; + return false; + } + + return (prop_value.GetBool() == value); + } + + return false; + } + + bool MatchIntegerProperty(std::string const& name, int32_t value) const + { + auto const& prop_value = GetPropertyValue(name); + + if (prop_value) { GVariantClass prop_val_type = g_variant_classify(prop_value); - // it'd be nice to be able to do all this with one method. However, the booleans need - // special treatment, and I can't figure out how to group all the integer types together - // without resorting to template functions.... and we all know what happens when you - // start doing that... + // it'd be nice to be able to do all this with one method. + // I can't figure out how to group all the integer types together switch (prop_val_type) { - case G_VARIANT_CLASS_STRING: - { - const gchar* prop_val = g_variant_get_string(prop_value, NULL); - if (g_strcmp0(prop_val, value.c_str()) == 0) - { - matches = true; - } - } - break; - case G_VARIANT_CLASS_BOOLEAN: - { - std::string value = boost::to_upper_copy(value); - bool p = value == "TRUE" || - value == "ON" || - value == "YES" || - value == "1"; - matches = (g_variant_get_boolean(prop_value) == p); - } - break; case G_VARIANT_CLASS_BYTE: - { - // It would be nice if I could do all the integer types together, but I couldn't see how... - std::stringstream stream(value); - int val; // changing this to guchar causes problems. - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_byte(prop_value); - } - break; + return static_cast<unsigned char>(value) == prop_value.GetByte(); case G_VARIANT_CLASS_INT16: - { - std::stringstream stream(value); - gint16 val; - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_int16(prop_value); - } - break; + return value == prop_value.GetInt16(); case G_VARIANT_CLASS_UINT16: - { - std::stringstream stream(value); - guint16 val; - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_uint16(prop_value); - } - break; + return static_cast<uint16_t>(value) == prop_value.GetUInt16(); case G_VARIANT_CLASS_INT32: - { - std::stringstream stream(value); - gint32 val; - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_int32(prop_value); - } - break; + return value == prop_value.GetInt32(); case G_VARIANT_CLASS_UINT32: - { - std::stringstream stream(value); - guint32 val; - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_uint32(prop_value); - } - break; + return static_cast<uint32_t>(value) == prop_value.GetUInt32(); case G_VARIANT_CLASS_INT64: - { - std::stringstream stream(value); - gint64 val; - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_int64(prop_value); - } - break; + return value == prop_value.GetInt64(); case G_VARIANT_CLASS_UINT64: - { - std::stringstream stream(value); - guint64 val; - stream >> val; - matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 && - val == g_variant_get_uint64(prop_value); - } - break; + return static_cast<uint64_t>(value) == prop_value.GetUInt64(); default: - LOG_WARNING(logger) << "Unable to match against property of unknown type."; + LOG_WARNING(logger) << "Unable to match '"<< name << "' against property of unknown integer type."; }; } - g_variant_unref(prop_value); - g_variant_unref(prop_dict); - return matches; + + return false; + } + + glib::Variant GetPropertyValue(std::string const& name) const + { + if (name == "id") + return glib::Variant(GetId()); + + GVariantBuilder properties_builder; + g_variant_builder_init(&properties_builder, G_VARIANT_TYPE("a{sv}")); + node_->AddProperties(&properties_builder); + glib::Variant props_dict(g_variant_builder_end(&properties_builder)); + return g_variant_lookup_value(props_dict, name.c_str(), nullptr); } std::vector<xpathselect::Node::Ptr> Children() const { std::vector<xpathselect::Node::Ptr> children; - for(auto child: node_->GetIntrospectableChildren()) - { - children.push_back(std::make_shared<IntrospectableAdapter>(child, GetPath() )); - } + auto const& this_ptr = shared_from_this(); + + for(auto const& child: node_->GetIntrospectableChildren()) + children.push_back(std::make_shared<IntrospectableAdapter>(child, this_ptr)); + return children; + } + Introspectable* Node() const + { + return node_; } - Introspectable* node_; private: + Introspectable* node_; + IntrospectableAdapter::Ptr parent_; std::string full_path_; }; - xpathselect::NodeList select_nodes(local::IntrospectableAdapter::Ptr root, - std::string const& query) + xpathselect::NodeVector select_nodes(IntrospectableAdapter::Ptr const& root, std::string const& query) { - if (xpathselect_driver_ == NULL) - xpathselect_driver_ = dlopen("libxpathselect.so.1.3", RTLD_LAZY); + if (!xpathselect_driver_) + xpathselect_driver_ = dlopen(XPATH_SELECT_LIB.c_str(), RTLD_LAZY); if (xpathselect_driver_) { - typedef decltype(&xpathselect::SelectNodes) entry_t; + typedef decltype(&xpathselect::SelectNodes) select_nodes_t; dlerror(); - entry_t entry_point = (entry_t) dlsym(xpathselect_driver_, "SelectNodes"); + auto SelectNodes = reinterpret_cast<select_nodes_t>(dlsym(xpathselect_driver_, "SelectNodes")); const char* err = dlerror(); if (err) { @@ -214,7 +197,7 @@ namespace local } else { - return entry_point(root, query); + return SelectNodes(root, query); } } else @@ -223,7 +206,7 @@ namespace local } // Fallen through here as we've hit an error - return xpathselect::NodeList(); + return xpathselect::NodeVector(); } // This needs to be called at destruction to cleanup the dlopen @@ -240,10 +223,8 @@ bool TryLoadXPathImplementation(); GVariant* GetState(std::string const& query); void StartLogToFile(std::string const& file_path); void ResetLogging(); -void SetLogSeverity(std::string const& log_component, - std::string const& severity); -void LogMessage(std::string const& severity, - std::string const& message); +void SetLogSeverity(std::string const& log_component, std::string const& severity); +void LogMessage(std::string const& severity, std::string const& message); namespace dbus { @@ -317,7 +298,7 @@ GVariant* DebugDBusInterface::HandleDBusMethodCall(std::string const& method, GV } else if (method == "GetVersion") { - return g_variant_new("(s)", "1.3"); + return g_variant_new("(s)", local::PROTOCOL_VERSION.c_str()); } else if (method == "StartLogToFile") { @@ -352,16 +333,15 @@ GVariant* DebugDBusInterface::HandleDBusMethodCall(std::string const& method, GV GVariant* GetState(std::string const& query) { - GVariantBuilder builder; + GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("a(sv)")); - local::IntrospectableAdapter::Ptr root_node = std::make_shared<local::IntrospectableAdapter>(_parent_introspectable, std::string()); - auto nodes = local::select_nodes(root_node, query); - for (auto n : nodes) + auto root_node = std::make_shared<local::IntrospectableAdapter>(_parent_introspectable); + for (auto const& n : local::select_nodes(root_node, query)) { - auto p = std::static_pointer_cast<local::IntrospectableAdapter>(n); + auto p = std::static_pointer_cast<local::IntrospectableAdapter const>(n); if (p) - g_variant_builder_add(&builder, "(sv)", p->GetPath().c_str(), p->node_->Introspect()); + g_variant_builder_add(&builder, "(sv)", p->GetPath().c_str(), p->Node()->Introspect()); } return g_variant_new("(a(sv))", &builder); diff --git a/unity-shared/Introspectable.cpp b/unity-shared/Introspectable.cpp index 9e3d8b920..ed932587f 100644 --- a/unity-shared/Introspectable.cpp +++ b/unity-shared/Introspectable.cpp @@ -17,6 +17,7 @@ * Authored by: Alex Launi <alex.launi@canonical.com> */ +#include <UnityCore/Variant.h> #include "Introspectable.h" namespace unity @@ -24,88 +25,85 @@ namespace unity namespace debug { +const std::string CHILDREN_NAME = "Children"; + Introspectable::Introspectable() { - static guint64 unique_id=0; - _id = unique_id++; + static int32_t unique_id_ = 0; + id_ = unique_id_++; } Introspectable::~Introspectable() { - for (auto parent : _parents) - parent->_children.remove(this); - for (auto child : _children) - child->_parents.remove(this); + for (auto parent : parents_) + parent->children_.remove(this); + for (auto child : children_) + child->parents_.remove(this); } Introspectable::IntrospectableList Introspectable::GetIntrospectableChildren() { - return _children; + return children_; } GVariant* Introspectable::Introspect() { - GVariantBuilder builder; - GVariantBuilder child_builder; - gint n_children = 0; + GVariantBuilder builder; + GVariantBuilder child_builder; + bool has_valid_children = false; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, "{sv}", "id", g_variant_new_uint64(_id)); - + variant::BuilderWrapper build_wrapper(&builder); + build_wrapper.add("id", id_); AddProperties(&builder); g_variant_builder_init(&child_builder, G_VARIANT_TYPE("as")); - auto children = GetIntrospectableChildren(); - for (auto it = children.begin(); it != children.end(); it++) + for (auto const& child : GetIntrospectableChildren()) { - if ((*it)->GetName() != "") + auto const& child_name = child->GetName(); + + if (!child_name.empty()) { - g_variant_builder_add(&child_builder, "s", (*it)->GetName().c_str()); - n_children++; + g_variant_builder_add(&child_builder, "s", child_name.c_str()); + has_valid_children = true; } } - GVariant* child_results = g_variant_builder_end(&child_builder); + glib::Variant child_results(g_variant_builder_end(&child_builder)); + + if (has_valid_children) + build_wrapper.add(CHILDREN_NAME, child_results); - if (n_children > 0) - g_variant_builder_add(&builder, "{sv}", GetChildsName().c_str(), child_results); return g_variant_builder_end(&builder); } void Introspectable::AddChild(Introspectable* child) { - _children.push_back(child); - child->_parents.push_back(this); + children_.push_back(child); + child->parents_.push_back(this); } void Introspectable::RemoveChild(Introspectable* child) { - _children.remove(child); - child->_parents.remove(this); -} - -std::string -Introspectable::GetChildsName() const -{ - return "Children"; + children_.remove(child); + child->parents_.remove(this); } -guint64 Introspectable::GetIntrospectionId() const +int32_t Introspectable::GetIntrospectionId() const { - return _id; + return id_; } void Introspectable::RemoveAllChildren() { - for (auto child : _children) - { - child->_parents.remove(this); - } - _children.clear(); + for (auto child : children_) + child->parents_.remove(this); + + children_.clear(); } } diff --git a/unity-shared/Introspectable.h b/unity-shared/Introspectable.h index 245ec7b84..af7c0dd84 100644 --- a/unity-shared/Introspectable.h +++ b/unity-shared/Introspectable.h @@ -41,13 +41,9 @@ public: void RemoveChild(Introspectable* child); virtual void AddProperties(GVariantBuilder* builder) = 0; virtual IntrospectableList GetIntrospectableChildren(); - guint64 GetIntrospectionId() const; + int32_t GetIntrospectionId() const; protected: - /// Please don't override this unless you really need to. The only valid reason - /// is if you have a property that simply *must* be called 'Children'. - virtual std::string GetChildsName() const; - void RemoveAllChildren(); /* @@ -61,9 +57,9 @@ protected: */ private: - std::list<Introspectable*> _children; - std::list<Introspectable*> _parents; - guint64 _id; + std::list<Introspectable*> children_; + std::list<Introspectable*> parents_; + int32_t id_; }; } } diff --git a/unity-shared/PlacesOverlayVScrollBar.cpp b/unity-shared/PlacesOverlayVScrollBar.cpp index fc5d2daac..e16f4b848 100644 --- a/unity-shared/PlacesOverlayVScrollBar.cpp +++ b/unity-shared/PlacesOverlayVScrollBar.cpp @@ -209,9 +209,8 @@ void PlacesOverlayVScrollBar::CheckIfThumbIsInsideSlider() { nux::Geometry const& slider_geo = _slider->GetAbsoluteGeometry(); nux::Geometry const& thumb_geo = overlay_window_->GetThumbGeometry(); - nux::Geometry const& intersection = (thumb_geo.Intersect(slider_geo)); - if (!intersection.IsNull()) + if (thumb_geo.IsIntersecting(slider_geo)) { ResetConnector(); overlay_window_->ThumbInsideSlider(); diff --git a/unity-shared/PluginAdapter.cpp b/unity-shared/PluginAdapter.cpp index b233f3067..34bead63d 100644 --- a/unity-shared/PluginAdapter.cpp +++ b/unity-shared/PluginAdapter.cpp @@ -573,7 +573,7 @@ bool PluginAdapter::IsWindowObscured(Window window_id) const && sibling->isMapped() && sibling->isViewable() && (sibling->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE - && !GetWindowGeometry(sibling->id()).Intersect(win_geo).IsNull()) + && GetWindowGeometry(sibling->id()).IsIntersecting(win_geo)) { return true; } diff --git a/unity-shared/SearchBar.cpp b/unity-shared/SearchBar.cpp index 11974736b..3f300e91c 100644 --- a/unity-shared/SearchBar.cpp +++ b/unity-shared/SearchBar.cpp @@ -617,6 +617,7 @@ void SearchBar::AddProperties(GVariantBuilder* builder) .add("filter-label-y", show_filters_->GetAbsoluteY()) .add("filter-label-width", show_filters_->GetAbsoluteWidth()) .add("filter-label-height", show_filters_->GetAbsoluteHeight()) + .add("filter-label-geo", show_filters_->GetAbsoluteGeometry()) .add("im_active", pango_entry_->im_active()); } |
