diff options
| author | Jason Smith <jason.smith@canonical.com> | 2012-08-20 11:26:14 -0400 |
|---|---|---|
| committer | Jason Smith <jason.smith@canonical.com> | 2012-08-20 11:26:14 -0400 |
| commit | 4bb9e17841c65d17c5f4a7d973689a6efede35d4 (patch) | |
| tree | 530bb53767c4d426a88d7c95439a21015407d97e /unity-shared | |
| parent | ac0e9588ff9ecde3d8d7df79b416db5a7d1411b0 (diff) | |
| parent | 02be480ef0d93ecd84b80283d800e3177cbc3b30 (diff) | |
merge trunk
(bzr r2542.1.3)
Diffstat (limited to 'unity-shared')
34 files changed, 3050 insertions, 160 deletions
diff --git a/unity-shared/BGHash.cpp b/unity-shared/BGHash.cpp index 767c8f377..fc299bc98 100644 --- a/unity-shared/BGHash.cpp +++ b/unity-shared/BGHash.cpp @@ -31,14 +31,12 @@ namespace unity { BGHash::BGHash() - : transition_animator_(500) - , current_color_(unity::colors::Aubergine) - , new_color_(unity::colors::Aubergine) - , old_color_(unity::colors::Aubergine) + : current_color_(unity::colors::Aubergine) { + transition_animator_.SetDuration(500); override_color_.alpha = 0.0f; - transition_animator_.animation_updated.connect(sigc::mem_fun(this, &BGHash::OnTransitionUpdated)); + transition_animator_.updated.connect(sigc::mem_fun(this, &BGHash::OnTransitionUpdated)); ubus_manager_.RegisterInterest(UBUS_BACKGROUND_REQUEST_COLOUR_EMIT, [&](GVariant *) { DoUbusColorEmit(); } ); RefreshColor(); @@ -100,14 +98,6 @@ void BGHash::RefreshColor() } } -nux::Color BGHash::InterpolateColor(nux::Color const& colora, nux::Color const& colorb, float value) const -{ - // takes two colours, transitions between them, we can do it linearly or whatever - // i don't think it will matter that much - // it doesn't happen too often - return colora + ((colorb - colora) * value); -} - void BGHash::TransitionToNewColor(nux::color::Color const& new_color) { if (new_color == current_color_) @@ -115,16 +105,15 @@ void BGHash::TransitionToNewColor(nux::color::Color const& new_color) LOG_DEBUG(logger) << "transitioning from: " << current_color_.red << " to " << new_color.red; - old_color_ = current_color_; - new_color_ = new_color; - + transition_animator_.SetStartValue(current_color_); + transition_animator_.SetFinishValue(new_color); transition_animator_.Stop(); transition_animator_.Start(); } -void BGHash::OnTransitionUpdated(double progress) +void BGHash::OnTransitionUpdated(nux::Color const& new_color) { - current_color_ = InterpolateColor(old_color_, new_color_, progress); + current_color_ = new_color; DoUbusColorEmit(); } diff --git a/unity-shared/BGHash.h b/unity-shared/BGHash.h index 7cbb7d4f6..b32ec1c64 100644 --- a/unity-shared/BGHash.h +++ b/unity-shared/BGHash.h @@ -19,8 +19,8 @@ #ifndef BGHASH_H #define BGHASH_H +#include <NuxCore/Animation.h> #include <Nux/Nux.h> -#include "Animator.h" #include "UBusWrapper.h" namespace unity { @@ -41,18 +41,15 @@ namespace unity void OverrideColor(nux::Color const& color); private: - void OnTransitionUpdated(double progress); + void OnTransitionUpdated(nux::Color const& new_color); void DoUbusColorEmit(); void TransitionToNewColor(nux::Color const& new_color); - nux::Color InterpolateColor(nux::Color const& colora, nux::Color const& colorb, float value) const; nux::Color MatchColor(nux::Color const& base_color) const; private: - Animator transition_animator_; + nux::animation::AnimateValue<nux::Color> transition_animator_; nux::Color current_color_; // the current colour, including steps in transitions - nux::Color new_color_; // in transitions, the next colour, otherwise the current colour - nux::Color old_color_; // the last colour chosen, used for transitions nux::Color override_color_; UBusManager ubus_manager_; diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt index 46603fce7..d1b06f000 100644 --- a/unity-shared/CMakeLists.txt +++ b/unity-shared/CMakeLists.txt @@ -32,8 +32,10 @@ set (UNITY_SHARED_SOURCES AbstractSeparator.cpp Animator.cpp BGHash.cpp + CoverArt.cpp BackgroundEffectHelper.cpp DashStyle.cpp + DefaultThumbnailProvider.cpp FontSettings.cpp KeyboardUtil.cpp IMTextEntry.cpp @@ -47,16 +49,22 @@ set (UNITY_SHARED_SOURCES LineSeparator.cpp OverlayRenderer.cpp PanelStyle.cpp + PlacesVScrollBar.cpp + PreviewStyle.cpp + RatingsButton.cpp SearchBar.cpp SearchBarSpinner.cpp StaticCairoText.cpp TextureCache.cpp + TextureThumbnailProvider.cpp + ThumbnailGenerator.cpp Timer.cpp UBusWrapper.cpp UScreen.cpp UnitySettings.cpp UnityWindowStyle.cpp UnityWindowView.cpp + UserThumbnailProvider.cpp WindowManager.cpp ubus-server.cpp ) diff --git a/unity-shared/CoverArt.cpp b/unity-shared/CoverArt.cpp new file mode 100644 index 000000000..c6949d499 --- /dev/null +++ b/unity-shared/CoverArt.cpp @@ -0,0 +1,460 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Andrea Cimitan <andrea.cimitan@canonical.com> + * Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#include "CoverArt.h" +#include "unity-shared/IntrospectableWrappers.h" +#include "unity-shared/CairoTexture.h" +#include <NuxCore/Logger.h> +#include <Nux/VLayout.h> +#include "DashStyle.h" +#include "IconLoader.h" + +namespace unity +{ +namespace dash +{ +namespace previews +{ + +namespace +{ +nux::logging::Logger logger("unity.dash.previews.coverart"); + +const int icon_width = 256; +} + +NUX_IMPLEMENT_OBJECT_TYPE(CoverArt); + +CoverArt::CoverArt() + : View(NUX_TRACKER_LOCATION) + , overlay_text_(nullptr) + , thumb_handle_(0) + , slot_handle_(0) + , stretch_image_(false) + , waiting_(false) + , rotation_(0.0) +{ + SetupViews(); +} + +CoverArt::~CoverArt() +{ + if (overlay_text_) + overlay_text_->UnReference(); + + if (slot_handle_ > 0) + { + IconLoader::GetDefault().DisconnectHandle(slot_handle_); + slot_handle_ = 0; + } + + if (notifier_) + notifier_->Cancel(); +} + +void CoverArt::SetImage(std::string const& image_hint) +{ + spinner_timeout_.reset(); + frame_timeout_.reset(); + waiting_ = false; + + if (slot_handle_ > 0) + { + IconLoader::GetDefault().DisconnectHandle(slot_handle_); + slot_handle_ = 0; + } + + GIcon* icon = g_icon_new_for_string(image_hint.c_str(), NULL); + + bool bLoadTexture = false; + bLoadTexture |= g_strrstr(image_hint.c_str(), "://") != NULL; + if (!bLoadTexture && !image_hint.empty()) + { + bLoadTexture |= image_hint[0] == '/' && image_hint.size() > 1; + } + + // texture from file. + if (bLoadTexture) + { + StartWaiting(); + slot_handle_ = IconLoader::GetDefault().LoadFromGIconString(image_hint, ~0, sigc::mem_fun(this, &CoverArt::TextureLoaded)); + } + else if (!image_hint.empty()) + { + if (GetLayout()) + GetLayout()->RemoveChildObject(overlay_text_); + + if (G_IS_ICON(icon)) + { + StartWaiting(); + slot_handle_ = IconLoader::GetDefault().LoadFromGIconString(image_hint, icon_width, sigc::mem_fun(this, &CoverArt::IconLoaded)); + } + else + { + StartWaiting(); + slot_handle_ = IconLoader::GetDefault().LoadFromIconName(image_hint, icon_width, sigc::mem_fun(this, &CoverArt::IconLoaded)); + } + } + else + { + SetNoImageAvailable(); + } + + if (icon != NULL) + g_object_unref(icon); +} + +void CoverArt::GenerateImage(std::string const& uri) +{ + StartWaiting(); + notifier_ = ThumbnailGenerator::Instance().GetThumbnail(uri, 512); + + notifier_->ready.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailGenerated)); + notifier_->error.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailError)); +} + +void CoverArt::StartWaiting() +{ + if (waiting_) + return; + + waiting_ = true; + + rotate_matrix_.Rotate_z(0.0f); + rotation_ = 0.0f; + + spinner_timeout_.reset(new glib::TimeoutSeconds(5, [&] + { + texture_screenshot_.Release(); + waiting_ = false; + + SetNoImageAvailable(); + return false; + })); + + QueueDraw(); +} + +void CoverArt::SetNoImageAvailable() +{ + if (GetLayout()) + { + GetLayout()->RemoveChildObject(overlay_text_); + GetLayout()->AddView(overlay_text_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL, 100.0, nux::LayoutPosition(1)); + ComputeContentSize(); + + QueueDraw(); + } +} + +void CoverArt::IconLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf) +{ + // Finished waiting + spinner_timeout_.reset(); + frame_timeout_.reset(); + waiting_ = false; + stretch_image_ = false; + + if (!pixbuf) + { + SetNoImageAvailable(); + return; + } + + int height = size; + + int pixbuf_width, pixbuf_height; + pixbuf_width = gdk_pixbuf_get_width(pixbuf); + pixbuf_height = gdk_pixbuf_get_height(pixbuf); + if (G_UNLIKELY(!pixbuf_height || !pixbuf_width)) + { + pixbuf_width = (pixbuf_width) ? pixbuf_width : 1; // no zeros please + pixbuf_height = (pixbuf_height) ? pixbuf_height: 1; // no zeros please + } + + if (pixbuf_width == pixbuf_height) + { + // quick path for square icons + texture_screenshot_.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true)); + QueueDraw(); + } + else + { + // slow path for non square icons that must be resized to fit in the square + // texture + + float aspect = static_cast<float>(pixbuf_height) / pixbuf_width; // already sanitized width/height so can not be 0.0 + if (aspect < 1.0f) + { + pixbuf_width = icon_width; + pixbuf_height = pixbuf_width * aspect; + + if (pixbuf_height > height) + { + // scaled too big, scale down + pixbuf_height = height; + pixbuf_width = pixbuf_height / aspect; + } + } + else + { + pixbuf_height = height; + pixbuf_width = pixbuf_height / aspect; + } + + if (gdk_pixbuf_get_height(pixbuf) == pixbuf_height) + { + // we changed our mind, fast path is good + texture_screenshot_.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true)); + QueueDraw(); + return; + } + + nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, pixbuf_width, pixbuf_height); + cairo_t* cr = cairo_graphics.GetInternalContext(); + + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + cairo_paint(cr); + + float scale = float(pixbuf_height) / gdk_pixbuf_get_height(pixbuf); + cairo_scale(cr, scale, scale); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); + cairo_paint(cr); + + texture_screenshot_.Adopt(texture_from_cairo_graphics(cairo_graphics)); + QueueDraw(); + } +} + +void CoverArt::TextureLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf) +{ + // Finished waiting + spinner_timeout_.reset(); + frame_timeout_.reset(); + waiting_ = false; + stretch_image_ = true; + + if (!pixbuf) + { + SetNoImageAvailable(); + return; + } + texture_screenshot_.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true)); +} + +void CoverArt::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw) +{ + nux::Geometry const& base = GetGeometry(); + + gfx_engine.PushClippingRectangle(base); + nux::GetPainter().PaintBackground(gfx_engine, base); + + unsigned int alpha, src, dest = 0; + gfx_engine.GetRenderStates().GetBlend(alpha, src, dest); + gfx_engine.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + gfx_engine.QRP_Color(base.x, + base.y, + base.GetWidth(), + base.GetHeight(), + nux::Color(0.03f, 0.03f, 0.03f, 0.0f)); + + if (texture_screenshot_) + { + nux::Geometry imageDest = base; + nux::TexCoordXForm texxform; + + if (stretch_image_ || base.GetWidth() < texture_screenshot_->GetWidth() || base.height < texture_screenshot_->GetHeight()) + { + float base_apsect = float(base.GetWidth()) / base.GetHeight(); + float image_aspect = float(texture_screenshot_->GetWidth()) / texture_screenshot_->GetHeight(); + + if (image_aspect > base_apsect) + { + imageDest.SetHeight(float(imageDest.GetWidth()) / image_aspect); + } + if (image_aspect < base_apsect) + { + imageDest.SetWidth(image_aspect * imageDest.GetHeight()); + } + } + else + { + imageDest = nux::Geometry(0, 0, texture_screenshot_->GetWidth(), texture_screenshot_->GetHeight()); + } + + + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_SCALE_COORD); + texxform.SetWrap(nux::TEXWRAP_CLAMP_TO_BORDER, nux::TEXWRAP_CLAMP_TO_BORDER); + texxform.SetFilter(nux::TEXFILTER_LINEAR, nux::TEXFILTER_LINEAR); + + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = imageDest.width; + texxform.v1 = imageDest.height; + + gfx_engine.QRP_1Tex(base.x + (float(base.GetWidth() - imageDest.GetWidth()) / 2), + base.y + (float(base.GetHeight() - imageDest.GetHeight()) / 2), + imageDest.width, + imageDest.height, + texture_screenshot_.GetPointer()->GetDeviceTexture(), + texxform, + nux::color::White); + } + else + { + if (waiting_) + { + nux::TexCoordXForm texxform; + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); + texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT); + texxform.min_filter = nux::TEXFILTER_LINEAR; + texxform.mag_filter = nux::TEXFILTER_LINEAR; + + nux::Geometry spin_geo(base.x + ((base.width - spin_->GetWidth()) / 2), + base.y + ((base.height - spin_->GetHeight()) / 2), + spin_->GetWidth(), + spin_->GetHeight()); + // Geometry (== Rect) uses integers which were rounded above, + // hence an extra 0.5 offset for odd sizes is needed + // because pure floating point is not being used. + int spin_offset_w = !(base.width % 2) ? 0 : 1; + int spin_offset_h = !(base.height % 2) ? 0 : 1; + + gfx_engine.PushModelViewMatrix(nux::Matrix4::TRANSLATE(-spin_geo.x - (spin_geo.width + spin_offset_w) / 2.0f, + -spin_geo.y - (spin_geo.height + spin_offset_h) / 2.0f, 0)); + gfx_engine.PushModelViewMatrix(rotate_matrix_); + gfx_engine.PushModelViewMatrix(nux::Matrix4::TRANSLATE(spin_geo.x + (spin_geo.width + spin_offset_w) / 2.0f, + spin_geo.y + (spin_geo.height + spin_offset_h) / 2.0f, 0)); + + gfx_engine.QRP_1Tex(spin_geo.x, + spin_geo.y, + spin_geo.width, + spin_geo.height, + spin_->GetDeviceTexture(), + texxform, + nux::color::White); + + gfx_engine.PopModelViewMatrix(); + gfx_engine.PopModelViewMatrix(); + gfx_engine.PopModelViewMatrix(); + + if (!frame_timeout_) + { + frame_timeout_.reset(new glib::Timeout(22, sigc::mem_fun(this, &CoverArt::OnFrameTimeout))); + } + } + } + + gfx_engine.GetRenderStates().SetBlend(alpha, src, dest); + + gfx_engine.PopClippingRectangle(); +} + +void CoverArt::DrawContent(nux::GraphicsEngine& gfx_engine, bool force_draw) +{ + nux::Geometry const& base = GetGeometry(); + gfx_engine.PushClippingRectangle(base); + + if (GetLayout()) + GetLayout()->ProcessDraw(gfx_engine, force_draw); + + gfx_engine.PopClippingRectangle(); +} + +std::string CoverArt::GetName() const +{ + return "CoverArt"; +} + +void CoverArt::SetupViews() +{ + nux::VLayout* layout = new nux::VLayout(); + layout->AddSpace(0, 1); + layout->AddSpace(0, 1); + SetLayout(layout); + + overlay_text_ = new nux::StaticCairoText("", NUX_TRACKER_LOCATION); + overlay_text_->Reference(); + overlay_text_->SetTextAlignment(nux::StaticCairoText::NUX_ALIGN_CENTRE); + overlay_text_->SetFont("Ubuntu 14"); + overlay_text_->SetLines(-3); + overlay_text_->SetText("No Image Available"); + + dash::Style& style = dash::Style::Instance(); + spin_ = style.GetSearchSpinIcon(); + + rotate_matrix_.Identity(); + rotate_matrix_.Rotate_z(0.0); + +} + +void CoverArt::SetFont(std::string const& font) +{ + overlay_text_->SetFont(font); +} + +void CoverArt::OnThumbnailGenerated(std::string const& uri) +{ + SetImage(uri); + notifier_.Release(); +} + +void CoverArt::OnThumbnailError(std::string const& error_hint) +{ + LOG_WARNING(logger) << "Failed to generate thumbnail: " << error_hint; + spinner_timeout_.reset(); + frame_timeout_.reset(); + waiting_ = false; + + texture_screenshot_.Release(); + if (GetLayout()) + { + GetLayout()->RemoveChildObject(overlay_text_); + GetLayout()->AddView(overlay_text_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL, 100.0, nux::LayoutPosition(1)); + ComputeContentSize(); + } + QueueDraw(); + notifier_.Release(); +} + + +bool CoverArt::OnFrameTimeout() +{ + rotation_ += 0.1f; + + if (rotation_ >= 360.0f) + rotation_ = 0.0f; + + rotate_matrix_.Rotate_z(rotation_); + QueueDraw(); + + frame_timeout_.reset(); + return false; +} + +} +} +} \ No newline at end of file diff --git a/unity-shared/CoverArt.h b/unity-shared/CoverArt.h new file mode 100644 index 000000000..dd5a666fe --- /dev/null +++ b/unity-shared/CoverArt.h @@ -0,0 +1,100 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Andrea Cimitan <andrea.cimitan@canonical.com> + * Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#ifndef COVERART_H +#define COVERART_H + +#include <Nux/Nux.h> +#include <Nux/View.h> +#include <UnityCore/ApplicationPreview.h> +#include <UnityCore/GLibSource.h> +#include <NuxCore/ObjectPtr.h> +#include "unity-shared/StaticCairoText.h" +#include "ThumbnailGenerator.h" + +namespace unity +{ +namespace dash +{ +namespace previews +{ + +class CoverArt : public nux::View +{ +public: + typedef nux::ObjectPtr<CoverArt> Ptr; + NUX_DECLARE_OBJECT_TYPE(CoverArt, nux::View); + + CoverArt(); + virtual ~CoverArt(); + + // Use for setting an image which is already an image (path to iamge, gicon). + void SetImage(std::string const& image_hint); + // Use for generating an image for a uri which is not necessarily an image. + void GenerateImage(std::string const& uri); + + // From debug::Introspectable + std::string GetName() const; + + void SetFont(std::string const& font); + +protected: + virtual void Draw(nux::GraphicsEngine& gfx_engine, bool force_draw); + virtual void DrawContent(nux::GraphicsEngine& gfx_engine, bool force_draw); + + void SetupViews(); + + void OnThumbnailGenerated(std::string const& uri); + void OnThumbnailError(std::string const& error_hint); + bool OnFrameTimeout(); + + void IconLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf); + void TextureLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf); + + void StartWaiting(); + void SetNoImageAvailable(); + +private: + nux::ObjectPtr<nux::BaseTexture> texture_screenshot_; + nux::StaticCairoText* overlay_text_; + + std::string image_hint_; + unsigned int thumb_handle_; + int slot_handle_; + bool stretch_image_; + ThumbnailNotifier::Ptr notifier_; + + // Spinner + bool waiting_; + nux::BaseTexture* spin_; + glib::Source::UniquePtr spinner_timeout_; + glib::Source::UniquePtr frame_timeout_; + nux::Matrix4 rotate_matrix_; + float rotation_; +}; + +} +} +} + +#endif // APPLICATIONSCREENSHOT_H \ No newline at end of file diff --git a/unity-shared/DashStyle.cpp b/unity-shared/DashStyle.cpp index a8f197375..226930c50 100644 --- a/unity-shared/DashStyle.cpp +++ b/unity-shared/DashStyle.cpp @@ -123,7 +123,7 @@ public: void Text(cairo_t* cr, nux::Color const& color, std::string const& label, - int font_size = -1, + int font_size, double horizMargin = 4.0, Alignment alignment = Alignment::CENTER); @@ -1360,6 +1360,10 @@ void Style::Impl::Text(cairo_t* cr, { pango_font_description_set_absolute_size(desc, text_size * PANGO_SCALE); } + else if (desc) + { + text_size = pango_font_description_get_size(desc) / PANGO_SCALE; + } PangoWeight weight; switch (regular_text_weight_) @@ -1632,7 +1636,6 @@ bool Style::SquareButton(cairo_t* cr, nux::ButtonVisualState state, int font_size, Alignment alignment, bool zeromargin) { - // sanity checks if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) return false; diff --git a/unity-shared/DefaultThumbnailProvider.cpp b/unity-shared/DefaultThumbnailProvider.cpp new file mode 100644 index 000000000..7545b21e5 --- /dev/null +++ b/unity-shared/DefaultThumbnailProvider.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#include <Nux/Nux.h> +#include "ThumbnailGenerator.h" +#include "UnityCore/GLibWrapper.h" +#include "DefaultThumbnailProvider.h" + +namespace unity +{ + +namespace DefaultThumbnailProvider +{ + +class DefaultThumbnailer : public Thumbnailer +{ +public: + DefaultThumbnailer(std::string const& name) + : name(name) + {} + + std::string name; + + virtual std::string GetName() const { return name; } + + virtual bool Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint); +}; + + +bool DefaultThumbnailer::Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint) +{ + glib::Object<GFile> file(::g_file_new_for_uri(input_file.c_str())); + + GError *err = NULL; + glib::Object<GFileInfo> file_info(g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_ICON, G_FILE_QUERY_INFO_NONE, NULL, &err)); + if (err != NULL) + { + error_hint = err->message; + g_error_free (err); + return ""; + } + + GIcon* icon = g_file_info_get_icon(file_info); // [transfer none] + output_file = g_icon_to_string(icon); + + return true; +} + +void Initialise() +{ + Thumbnailer::Ptr thumbnailer(new DefaultThumbnailer("default")); + std::list<std::string> mime_types; + mime_types.push_back("*"); + ThumbnailGenerator::RegisterThumbnailer(mime_types, thumbnailer); +} + +} // namespace DefaultThumbnailProvider +} // namespace unity + + diff --git a/unity-shared/DefaultThumbnailProvider.h b/unity-shared/DefaultThumbnailProvider.h new file mode 100644 index 000000000..3c7707b14 --- /dev/null +++ b/unity-shared/DefaultThumbnailProvider.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#ifndef UNITYSHARED_DEFAULTTHUMBNAILPROVIDER_H +#define UNITYSHARED_DEFAULTTHUMBNAILPROVIDER_H + +#include <Nux/Nux.h> + +namespace unity +{ + +namespace DefaultThumbnailProvider +{ + void Initialise(); +}; + +} // namespace unity + +#endif // UNITYSHARED_DEFAULTTHUMBNAILPROVIDER_H + diff --git a/unity-shared/FontSettings.cpp b/unity-shared/FontSettings.cpp index 1b115f8e1..4da0e9679 100644 --- a/unity-shared/FontSettings.cpp +++ b/unity-shared/FontSettings.cpp @@ -30,9 +30,9 @@ FontSettings::FontSettings() { GtkSettings* settings = gtk_settings_get_default(); - sig_man_.Add(new glib::Signal<void, GtkSettings*, GParamSpec*>(settings, "notify::gtk-xft-hintstyle", sigc::mem_fun(this, &FontSettings::Refresh))); - sig_man_.Add(new glib::Signal<void, GtkSettings*, GParamSpec*>(settings, "notify::gtk-xft-rgba", sigc::mem_fun(this, &FontSettings::Refresh))); - sig_man_.Add(new glib::Signal<void, GtkSettings*, GParamSpec*>(settings, "notify::gtk-xft-antialias", sigc::mem_fun(this, &FontSettings::Refresh))); + sig_man_.Add<void, GtkSettings*, GParamSpec*>(settings, "notify::gtk-xft-hintstyle", sigc::mem_fun(this, &FontSettings::Refresh)); + sig_man_.Add<void, GtkSettings*, GParamSpec*>(settings, "notify::gtk-xft-rgba", sigc::mem_fun(this, &FontSettings::Refresh)); + sig_man_.Add<void, GtkSettings*, GParamSpec*>(settings, "notify::gtk-xft-antialias", sigc::mem_fun(this, &FontSettings::Refresh)); Refresh(); } diff --git a/unity-shared/IconLoader.cpp b/unity-shared/IconLoader.cpp index 2627d914c..78c9e9ea9 100644 --- a/unity-shared/IconLoader.cpp +++ b/unity-shared/IconLoader.cpp @@ -268,12 +268,21 @@ private: glib::Object<GInputStream> stream( ::g_memory_input_stream_new_from_data(contents.Value(), length, nullptr)); - task->result = ::gdk_pixbuf_new_from_stream_at_scale(stream, - -1, - task->size, - TRUE, - canc, - &task->error); + if (task->size != static_cast<unsigned int>(~0)) + { + task->result = ::gdk_pixbuf_new_from_stream_at_scale(stream, + -1, + task->size, + TRUE, + canc, + &task->error); + } + else + { + task->result = ::gdk_pixbuf_new_from_stream(stream, + canc, + &task->error); + } ::g_input_stream_close(stream, canc, nullptr); } } diff --git a/unity-shared/IconRenderer.cpp b/unity-shared/IconRenderer.cpp index ed1fa65e6..2c37cc89c 100644 --- a/unity-shared/IconRenderer.cpp +++ b/unity-shared/IconRenderer.cpp @@ -757,8 +757,8 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); - int VertexLocation; - int TextureCoord0Location; + int VertexLocation = -1; + int TextureCoord0Location = -1; int FragmentColor = 0; int ColorifyColor = 0; int DesatFactor = 0; diff --git a/unity-shared/IconTexture.cpp b/unity-shared/IconTexture.cpp index f97e5eb43..c324a2e29 100644 --- a/unity-shared/IconTexture.cpp +++ b/unity-shared/IconTexture.cpp @@ -51,7 +51,8 @@ IconTexture::IconTexture(nux::BaseTexture* texture, guint width, guint height) _texture_size(width, height), _loading(false), _opacity(1.0f), - _handle(0) + _handle(0), + _draw_mode(DrawMode::NORMAL) { SetMinMaxSize(width, height); } @@ -63,7 +64,8 @@ IconTexture::IconTexture(std::string const& icon_name, unsigned int size, bool d _size(size), _loading(false), _opacity(1.0f), - _handle(0) + _handle(0), + _draw_mode(DrawMode::NORMAL) { if (!icon_name.empty () && !defer_icon_loading) LoadIcon(); @@ -187,16 +189,60 @@ void IconTexture::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) { nux::Color col(1.0f * _opacity, 1.0f * _opacity, 1.0f * _opacity, _opacity); nux::TexCoordXForm texxform; - texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - texxform.SetWrap(nux::TEXWRAP_CLAMP_TO_BORDER, nux::TEXWRAP_CLAMP_TO_BORDER); - - GfxContext.QRP_1Tex(geo.x + ((geo.width - _texture_size.width) / 2), - geo.y + ((geo.height - _texture_size.height) / 2), - _texture_size.width, - _texture_size.height, - _texture_cached->GetDeviceTexture(), - texxform, - col); + + if (_draw_mode == DrawMode::STRETCH_WITH_ASPECT) + { + nux::Geometry imageDest = geo; + + float geo_apsect = float(geo.GetWidth()) / geo.GetHeight(); + float image_aspect = float(_texture_cached->GetWidth()) / _texture_cached->GetHeight(); + + if (image_aspect > geo_apsect) + { + imageDest.SetHeight(float(imageDest.GetWidth()) / image_aspect); + } + if (image_aspect < geo_apsect) + { + imageDest.SetWidth(image_aspect * imageDest.GetHeight()); + } + else + { + imageDest = nux::Geometry(0, 0, _texture_cached->GetWidth(), _texture_cached->GetHeight()); + } + + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_SCALE_COORD); + texxform.SetWrap(nux::TEXWRAP_CLAMP_TO_BORDER, nux::TEXWRAP_CLAMP_TO_BORDER); + texxform.SetFilter(nux::TEXFILTER_LINEAR, nux::TEXFILTER_LINEAR); + + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = imageDest.width; + texxform.v1 = imageDest.height; + + int border_width = 1; + GfxContext.QRP_1Tex(geo.x + (float(geo.GetWidth() - imageDest.GetWidth()) / 2) + border_width, + geo.y + (float(geo.GetHeight() - imageDest.GetHeight()) / 2) + border_width, + imageDest.width - (border_width * 2), + imageDest.height - (border_width * 2), + _texture_cached.GetPointer()->GetDeviceTexture(), + texxform, + nux::color::White); + } + else + { + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); + texxform.SetWrap(nux::TEXWRAP_CLAMP_TO_BORDER, nux::TEXWRAP_CLAMP_TO_BORDER); + + GfxContext.QRP_1Tex(geo.x + ((geo.width - _texture_size.width) / 2), + geo.y + ((geo.height - _texture_size.height) / 2), + _texture_size.width, + _texture_size.height, + _texture_cached->GetDeviceTexture(), + texxform, + col); + } + + } GfxContext.PopClippingRectangle(); @@ -259,4 +305,9 @@ bool IconTexture::AcceptKeyNavFocus() return _accept_key_nav_focus; } +void IconTexture::SetDrawMode(DrawMode mode) +{ + _draw_mode = mode; + QueueDraw(); +} } diff --git a/unity-shared/IconTexture.h b/unity-shared/IconTexture.h index 88428733c..83364a1f7 100644 --- a/unity-shared/IconTexture.h +++ b/unity-shared/IconTexture.h @@ -54,6 +54,13 @@ public: nux::BaseTexture* texture(); + enum class DrawMode + { + NORMAL, + STRETCH_WITH_ASPECT + }; + void SetDrawMode(DrawMode mode); + sigc::signal<void, nux::BaseTexture*> texture_updated; protected: @@ -83,6 +90,7 @@ private: bool _loading; float _opacity; int _handle; + DrawMode _draw_mode; }; } diff --git a/unity-shared/PlacesVScrollBar.cpp b/unity-shared/PlacesVScrollBar.cpp new file mode 100644 index 000000000..0f8619fcc --- /dev/null +++ b/unity-shared/PlacesVScrollBar.cpp @@ -0,0 +1,142 @@ +// -*- 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: Mirco Müller <mirco.mueller@canonical.com> + */ + +#include <Nux/Nux.h> + +#include "unity-shared/CairoTexture.h" +#include "PlacesVScrollBar.h" + +using unity::texture_from_cairo_graphics; + +namespace unity +{ +namespace dash +{ + +PlacesVScrollBar::PlacesVScrollBar(NUX_FILE_LINE_DECL) + : VScrollBar(NUX_FILE_LINE_PARAM), + _slider_texture(NULL) +{ + _scroll_up_button->SetMaximumHeight(15); + _scroll_up_button->SetMinimumHeight(15); + + _scroll_down_button->SetMaximumHeight(15); + _scroll_down_button->SetMinimumHeight(15); + + _slider->SetMinimumWidth(3); + _slider->SetMaximumWidth(3); + SetMinimumWidth(3); + SetMaximumWidth(3); +} + +PlacesVScrollBar::~PlacesVScrollBar() +{ + if (_slider_texture) + _slider_texture->UnReference(); +} + +void +PlacesVScrollBar::PreLayoutManagement() +{ + nux::VScrollBar::PreLayoutManagement(); +} + +long +PlacesVScrollBar::PostLayoutManagement(long LayoutResult) +{ + long ret = nux::VScrollBar::PostLayoutManagement(LayoutResult); + + UpdateTexture(); + return ret; +} + +void +PlacesVScrollBar::Draw(nux::GraphicsEngine& gfxContext, bool force_draw) +{ + nux::Color color = nux::color::White; + nux::Geometry const& base = GetGeometry(); + nux::TexCoordXForm texxform; + + gfxContext.PushClippingRectangle(base); + + nux::GetPainter().PaintBackground(gfxContext, base); + + // check if textures have been computed... if they haven't, exit function + if (!_slider_texture) + return; + + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_SCALE_COORD); + + gfxContext.GetRenderStates().SetBlend(true); + gfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); + + if (content_height_ > container_height_) + { + nux::Geometry const& slider_geo = _slider->GetGeometry(); + + gfxContext.QRP_1Tex(slider_geo.x, + slider_geo.y, + slider_geo.width, + slider_geo.height, + _slider_texture->GetDeviceTexture(), + texxform, + color); + } + + gfxContext.GetRenderStates().SetBlend(false); + gfxContext.PopClippingRectangle(); + gfxContext.GetRenderStates().SetBlend(true); +} + +void PlacesVScrollBar::UpdateTexture() +{ + nux::CairoGraphics* cairoGraphics = NULL; + cairo_t* cr = NULL; + + // update texture of slider + int width = _slider->GetBaseWidth(); + int height = _slider->GetBaseHeight(); + cairoGraphics = new nux::CairoGraphics(CAIRO_FORMAT_ARGB32, width, height); + cr = cairoGraphics->GetContext(); + + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + cairo_paint(cr); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f); + cairoGraphics->DrawRoundedRectangle(cr, + 1.0f, + 0.0, + 0.0, + 1.5, + 3.0, + (double) height - 3.0); + cairo_fill(cr); + + if (_slider_texture) + _slider_texture->UnReference(); + _slider_texture = texture_from_cairo_graphics(*cairoGraphics); + + cairo_destroy(cr); + delete cairoGraphics; +} + +} // namespace dash +} // namespace unity + diff --git a/unity-shared/PlacesVScrollBar.h b/unity-shared/PlacesVScrollBar.h new file mode 100644 index 000000000..de9a9dca7 --- /dev/null +++ b/unity-shared/PlacesVScrollBar.h @@ -0,0 +1,58 @@ +// -*- 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: Mirco Müller <mirco.mueller@canonical.com> + */ + +#ifndef PLACES_VSCROLLBAR_H +#define PLACES_VSCROLLBAR_H + +#include <Nux/Nux.h> +#include <Nux/View.h> +#include <Nux/ScrollView.h> +#include <Nux/BaseWindow.h> +#include <Nux/VScrollBar.h> +#include <NuxGraphics/CairoGraphics.h> + +namespace unity +{ +namespace dash +{ + +class PlacesVScrollBar : public nux::VScrollBar +{ +public: + PlacesVScrollBar(NUX_FILE_LINE_PROTO); + ~PlacesVScrollBar(); + +protected: + virtual void PreLayoutManagement(); + virtual long PostLayoutManagement(long LayoutResult); + + void Draw(nux::GraphicsEngine& gfxContext, + bool forceDraw); + +private: + void UpdateTexture(); + +private: + nux::BaseTexture* _slider_texture; +}; + +} // namespace dash +} // namespace unity + +#endif // PLACES_VSCROLLBAR_H diff --git a/unity-shared/PluginAdapter.h b/unity-shared/PluginAdapter.h index 70d5e433c..8c9882bd1 100644 --- a/unity-shared/PluginAdapter.h +++ b/unity-shared/PluginAdapter.h @@ -92,11 +92,13 @@ public: void OnLeaveDesktop (); void TerminateScale(); - bool IsScaleActive(); - bool IsScaleActiveForGroup(); + bool IsScaleActive() const; + bool IsScaleActiveForGroup() const; void InitiateExpo(); - bool IsExpoActive(); + bool IsExpoActive() const; + + bool IsWallActive() const; void ShowGrabHandles(CompWindow* window, bool use_timer); void HideGrabHandles(CompWindow* window); @@ -109,22 +111,22 @@ public: void NotifyCompizEvent(const char* plugin, const char* event, CompOption::Vector& option); void NotifyNewDecorationState(guint32 xid); - guint32 GetActiveWindow(); + guint32 GetActiveWindow() const; void Decorate(guint32 xid); void Undecorate(guint32 xid); // WindowManager implementation - bool IsWindowMaximized(guint xid); + bool IsWindowMaximized(guint xid) const; bool IsWindowDecorated(guint xid); - bool IsWindowOnCurrentDesktop(guint xid); - bool IsWindowObscured(guint xid); - bool IsWindowMapped(guint xid); - bool IsWindowVisible(guint32 xid); - bool IsWindowOnTop(guint32 xid); - bool IsWindowClosable(guint32 xid); - bool IsWindowMinimizable(guint32 xid); - bool IsWindowMaximizable(guint32 xid); + bool IsWindowOnCurrentDesktop(guint xid) const; + bool IsWindowObscured(guint xid) const; + bool IsWindowMapped(guint xid) const; + bool IsWindowVisible(guint32 xid) const; + bool IsWindowOnTop(guint32 xid) const; + bool IsWindowClosable(guint32 xid) const; + bool IsWindowMinimizable(guint32 xid) const; + bool IsWindowMaximizable(guint32 xid) const; void Restore(guint32 xid); void RestoreAt(guint32 xid, int x, int y); @@ -140,12 +142,12 @@ public: void FocusWindowGroup(std::vector<Window> windows, FocusVisibility, int monitor = -1, bool only_top_win = true); bool ScaleWindowGroup(std::vector<Window> windows, int state, bool force); - bool IsScreenGrabbed(); - bool IsViewPortSwitchStarted(); + bool IsScreenGrabbed() const; + bool IsViewPortSwitchStarted() const; - unsigned long long GetWindowActiveNumber (guint32 xid); + unsigned long long GetWindowActiveNumber (guint32 xid) const; - bool MaximizeIfBigEnough(CompWindow* window); + bool MaximizeIfBigEnough(CompWindow* window) const; int GetWindowMonitor(guint32 xid) const; nux::Geometry GetWindowGeometry(guint32 xid) const; @@ -155,7 +157,7 @@ public: void CheckWindowIntersections(nux::Geometry const& region, bool &active, bool &any); - int WorkspaceCount(); + int WorkspaceCount() const; void SetCoverageAreaBeforeAutomaximize(float area); @@ -172,7 +174,7 @@ private: std::string MatchStringForXids(std::vector<Window> *windows); void InitiateScale(std::string const& match, int state = 0); - bool CheckWindowIntersection(nux::Geometry const& region, CompWindow* window); + bool CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) const; void SetMwmWindowHints(Window xid, MotifWmHints* new_hints); CompScreen* m_Screen; diff --git a/unity-shared/PluginAdapterCompiz.cpp b/unity-shared/PluginAdapterCompiz.cpp index 057ccea0c..1c67e9659 100644 --- a/unity-shared/PluginAdapterCompiz.cpp +++ b/unity-shared/PluginAdapterCompiz.cpp @@ -242,7 +242,7 @@ void MultiActionList::InitiateAll(CompOption::Vector& extraArgs, int state) { CompOption::Vector argument; - if (!m_ActionList.size()) + if (m_ActionList.empty()) return; argument.resize(1); @@ -269,7 +269,7 @@ MultiActionList::TerminateAll(CompOption::Vector& extraArgs) { CompOption::Vector argument; CompOption::Value value; - if (!m_ActionList.size()) + if (m_ActionList.empty()) return; argument.resize(1); @@ -298,7 +298,7 @@ MultiActionList::TerminateAll(CompOption::Vector& extraArgs) } unsigned long long -PluginAdapter::GetWindowActiveNumber (guint32 xid) +PluginAdapter::GetWindowActiveNumber (guint32 xid) const { Window win = xid; CompWindow* window; @@ -368,23 +368,29 @@ PluginAdapter::TerminateScale() } bool -PluginAdapter::IsScaleActive() +PluginAdapter::IsScaleActive() const { return m_Screen->grabExist("scale"); } bool -PluginAdapter::IsScaleActiveForGroup() +PluginAdapter::IsScaleActiveForGroup() const { return _spread_windows_state && m_Screen->grabExist("scale"); } bool -PluginAdapter::IsExpoActive() +PluginAdapter::IsExpoActive() const { return m_Screen->grabExist("expo"); } +bool +PluginAdapter::IsWallActive() const +{ + return m_Screen->grabExist("wall"); +} + void PluginAdapter::InitiateExpo() { @@ -395,13 +401,13 @@ PluginAdapter::InitiateExpo() // WindowManager implementation guint32 -PluginAdapter::GetActiveWindow() +PluginAdapter::GetActiveWindow() const { return m_Screen->activeWindow(); } bool -PluginAdapter::IsWindowMaximized(guint xid) +PluginAdapter::IsWindowMaximized(guint xid) const { Window win = xid; CompWindow* window; @@ -456,7 +462,7 @@ PluginAdapter::IsWindowDecorated(guint32 xid) } bool -PluginAdapter::IsWindowOnCurrentDesktop(guint32 xid) +PluginAdapter::IsWindowOnCurrentDesktop(guint32 xid) const { Window win = xid; CompWindow* window; @@ -472,7 +478,7 @@ PluginAdapter::IsWindowOnCurrentDesktop(guint32 xid) } bool -PluginAdapter::IsWindowObscured(guint32 xid) +PluginAdapter::IsWindowObscured(guint32 xid) const { Window win = xid; CompWindow* window; @@ -505,7 +511,7 @@ PluginAdapter::IsWindowObscured(guint32 xid) } bool -PluginAdapter::IsWindowMapped(guint32 xid) +PluginAdapter::IsWindowMapped(guint32 xid) const { Window win = xid; CompWindow* window; @@ -517,7 +523,7 @@ PluginAdapter::IsWindowMapped(guint32 xid) } bool -PluginAdapter::IsWindowVisible(guint32 xid) +PluginAdapter::IsWindowVisible(guint32 xid) const { Window win = xid; CompWindow* window; @@ -530,7 +536,7 @@ PluginAdapter::IsWindowVisible(guint32 xid) } bool -PluginAdapter::IsWindowOnTop(guint32 xid) +PluginAdapter::IsWindowOnTop(guint32 xid) const { Window win = xid; CompWindow* window = m_Screen->findWindow(win); @@ -569,7 +575,7 @@ PluginAdapter::IsWindowOnTop(guint32 xid) } bool -PluginAdapter::IsWindowClosable(guint32 xid) +PluginAdapter::IsWindowClosable(guint32 xid) const { Window win = xid; CompWindow* window; @@ -582,7 +588,7 @@ PluginAdapter::IsWindowClosable(guint32 xid) } bool -PluginAdapter::IsWindowMinimizable(guint32 xid) +PluginAdapter::IsWindowMinimizable(guint32 xid) const { Window win = xid; CompWindow* window; @@ -595,7 +601,7 @@ PluginAdapter::IsWindowMinimizable(guint32 xid) } bool -PluginAdapter::IsWindowMaximizable(guint32 xid) +PluginAdapter::IsWindowMaximizable(guint32 xid) const { Window win = xid; CompWindow* window; @@ -815,7 +821,8 @@ PluginAdapter::FocusWindowGroup(std::vector<Window> window_ids, FocusVisibility bool PluginAdapter::ScaleWindowGroup(std::vector<Window> windows, int state, bool force) { - if (windows.size() > 1 || (force && windows.size() > 0)) + std::size_t num_windows = windows.size(); + if (num_windows > 1 || (force && num_windows)) { std::string match = MatchStringForXids(&windows); InitiateScale(match, state); @@ -965,7 +972,7 @@ PluginAdapter::GetWorkAreaGeometry(guint32 xid) const } bool -PluginAdapter::CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) +PluginAdapter::CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) const { int intersect_types = CompWindowTypeNormalMask | CompWindowTypeDialogMask | CompWindowTypeModalDialogMask | CompWindowTypeUtilMask; @@ -1022,7 +1029,7 @@ PluginAdapter::CheckWindowIntersections (nux::Geometry const& region, bool &acti } int -PluginAdapter::WorkspaceCount() +PluginAdapter::WorkspaceCount() const { return m_Screen->vpSize().width() * m_Screen->vpSize().height(); } @@ -1105,19 +1112,19 @@ PluginAdapter::Undecorate(guint32 xid) } bool -PluginAdapter::IsScreenGrabbed() +PluginAdapter::IsScreenGrabbed() const { return m_Screen->grabbed(); } bool -PluginAdapter::IsViewPortSwitchStarted() +PluginAdapter::IsViewPortSwitchStarted() const { return _vp_switch_started; } /* Returns true if the window was maximized */ -bool PluginAdapter::MaximizeIfBigEnough(CompWindow* window) +bool PluginAdapter::MaximizeIfBigEnough(CompWindow* window) const { XClassHint classHint; Status status; diff --git a/unity-shared/PluginAdapterStandalone.cpp b/unity-shared/PluginAdapterStandalone.cpp index 45d0d5723..9ba893021 100644 --- a/unity-shared/PluginAdapterStandalone.cpp +++ b/unity-shared/PluginAdapterStandalone.cpp @@ -125,7 +125,7 @@ MultiActionList::TerminateAll(CompOption::Vector& extraArgs) } unsigned long long -PluginAdapter::GetWindowActiveNumber (guint32 xid) +PluginAdapter::GetWindowActiveNumber (guint32 xid) const { return 0; } @@ -157,19 +157,19 @@ PluginAdapter::TerminateScale() } bool -PluginAdapter::IsScaleActive() +PluginAdapter::IsScaleActive() const { return false; } bool -PluginAdapter::IsScaleActiveForGroup() +PluginAdapter::IsScaleActiveForGroup() const { return false; } bool -PluginAdapter::IsExpoActive() +PluginAdapter::IsExpoActive() const { return false; } @@ -179,15 +179,21 @@ PluginAdapter::InitiateExpo() { } +bool +PluginAdapter::IsWallActive() const +{ + return false; +} + // WindowManager implementation guint32 -PluginAdapter::GetActiveWindow() +PluginAdapter::GetActiveWindow() const { return 0; } bool -PluginAdapter::IsWindowMaximized(guint xid) +PluginAdapter::IsWindowMaximized(guint xid) const { return false; } @@ -199,49 +205,49 @@ PluginAdapter::IsWindowDecorated(guint32 xid) } bool -PluginAdapter::IsWindowOnCurrentDesktop(guint32 xid) +PluginAdapter::IsWindowOnCurrentDesktop(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowObscured(guint32 xid) +PluginAdapter::IsWindowObscured(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowMapped(guint32 xid) +PluginAdapter::IsWindowMapped(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowVisible(guint32 xid) +PluginAdapter::IsWindowVisible(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowOnTop(guint32 xid) +PluginAdapter::IsWindowOnTop(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowClosable(guint32 xid) +PluginAdapter::IsWindowClosable(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowMinimizable(guint32 xid) +PluginAdapter::IsWindowMinimizable(guint32 xid) const { return false; } bool -PluginAdapter::IsWindowMaximizable(guint32 xid) +PluginAdapter::IsWindowMaximizable(guint32 xid) const { return false; } @@ -347,7 +353,7 @@ PluginAdapter::GetWorkAreaGeometry(guint32 xid) const } bool -PluginAdapter::CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) +PluginAdapter::CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) const { return false; } @@ -358,7 +364,7 @@ PluginAdapter::CheckWindowIntersections (nux::Geometry const& region, bool &acti } int -PluginAdapter::WorkspaceCount() +PluginAdapter::WorkspaceCount() const { return 4; } @@ -379,19 +385,19 @@ PluginAdapter::Undecorate(guint32 xid) } bool -PluginAdapter::IsScreenGrabbed() +PluginAdapter::IsScreenGrabbed() const { return false; } bool -PluginAdapter::IsViewPortSwitchStarted() +PluginAdapter::IsViewPortSwitchStarted() const { return false; } /* Returns true if the window was maximized */ -bool PluginAdapter::MaximizeIfBigEnough(CompWindow* window) +bool PluginAdapter::MaximizeIfBigEnough(CompWindow* window) const { return true; } diff --git a/unity-shared/PreviewStyle.cpp b/unity-shared/PreviewStyle.cpp new file mode 100644 index 000000000..56e55bb4a --- /dev/null +++ b/unity-shared/PreviewStyle.cpp @@ -0,0 +1,361 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#include "PreviewStyle.h" +#include <NuxCore/Logger.h> + +#include <NuxGraphics/GLTextureResourceManager.h> +#include <UnityCore/GLibWrapper.h> +#include "config.h" + +namespace unity +{ +namespace dash +{ +namespace previews +{ +namespace +{ +Style* style_instance = nullptr; + +nux::logging::Logger logger("unity.dash.previews.style"); + +typedef nux::ObjectPtr<nux::BaseTexture> BaseTexturePtr; + +template <int default_size = 1> +class LazyLoadTexture +{ +public: + LazyLoadTexture(std::string const& filename) + : filename_(filename) {} + + nux::BaseTexture* texture(int size = default_size) + { + auto tex_iter = textures_.find(size); + if (tex_iter != textures_.end()) + return tex_iter->second.GetPointer(); + + return LoadTexture(size).GetPointer(); + } + +private: + BaseTexturePtr LoadTexture(int size) + { + BaseTexturePtr texture; + std::string full_path = PKGDATADIR + filename_; + glib::Object<GdkPixbuf> pixbuf; + glib::Error error; + + pixbuf = ::gdk_pixbuf_new_from_file_at_size(full_path.c_str(), size, size, &error); + if (error) + { + LOG_WARN(logger) << "Unable to texture " << full_path << " at size '" << size << "' : " << error; + } + else + { + texture.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true)); + } + textures_[size] = texture; + return texture; + } +private: + std::string filename_; + std::map<int, BaseTexturePtr> textures_; +}; + +} // namespace + + +class Style::Impl +{ +public: + Impl(Style* owner) + : owner_(owner) + , preview_nav_left_texture_("/preview_previous.svg") + , preview_nav_right_texture_("/preview_next.svg") + , preview_play_texture_("/preview_play.svg") + , preview_pause_texture_("/preview_pause.svg") + , preview_spin_texture_("/search_spin.svg") + { + } + ~Impl() {} + + Style* owner_; + + LazyLoadTexture<32> preview_nav_left_texture_; + LazyLoadTexture<32> preview_nav_right_texture_; + LazyLoadTexture<32> preview_play_texture_; + LazyLoadTexture<32> preview_pause_texture_; + LazyLoadTexture<32> preview_spin_texture_; +}; + + +Style::Style() +: pimpl(new Impl(this)) +{ + if (style_instance) + { + LOG_ERROR(logger) << "More than one previews::Style created."; + } + else + { + style_instance = this; + } +} + +Style::~Style() +{ + if (style_instance == this) + style_instance = nullptr; +} + +Style& Style::Instance() +{ + if (!style_instance) + { + LOG_ERROR(logger) << "No previews::Style created yet."; + } + + return *style_instance; +} + +int Style::GetNavigatorWidth() const +{ + return 42; +} + +int Style::GetNavigatorIconSize() const +{ + return 24; +} + +float Style::GetPreviewAspectRatio() const +{ + return static_cast<float>(796)/390; +} + +int Style::GetDetailsTopMargin() const +{ + return 5; +} + +int Style::GetDetailsBottomMargin() const +{ + return 10; +} + +int Style::GetDetailsRightMargin() const +{ + return 10; +} + +int Style::GetDetailsLeftMargin() const +{ + return 10; +} + +int Style::GetPanelSplitWidth() const +{ + return 16; +} + +int Style::GetAppIconAreaWidth() const +{ + return 105; +} + +int Style::GetSpaceBetweenTitleAndSubtitle() const +{ + return 6; +} + +int Style::GetSpaceBetweenIconAndDetails() const +{ + return 18; +} + +int Style::GetTrackHeight() const +{ + return 28; +} + +int Style::GetMusicDurationWidth() const +{ + return 40; +} + +int Style::GetActionButtonHeight() const +{ + return 36; +} + +int Style::GetActionButtonMaximumWidth() const +{ + return 190; +} + +int Style::GetSpaceBetweenActions() const +{ + return 10; +} + +int Style::GetTrackBarHeight() const +{ + return 25; +} + +float Style::GetAppImageAspectRatio() const +{ + return 1.0; +} + +int Style::GetDetailsPanelMinimumWidth() const +{ + return 300; +} + +int Style::GetInfoHintIconSizeWidth() const +{ + return 24; +} + +int Style::GetInfoHintNameMinimumWidth() const +{ + return 100; +} + +int Style::GetInfoHintNameMaximumWidth() const +{ + return 160; +} + +float Style::GetDescriptionLineSpacing() const +{ + return 2.0; +} + +int Style::GetDescriptionLineCount() const +{ + return 20; +} + +int Style::GetRatingWidgetHeight() const +{ + return 36; +} + +int Style::GetStatusIconSize() const +{ + return 12; +} + +float Style::GetVideoImageAspectRatio() const +{ + return float(540)/380; +} + +std::string Style::title_font() const +{ + return "Ubuntu 22"; +} + +std::string Style::subtitle_size_font() const +{ + return "Ubuntu 12.5"; +} + +std::string Style::description_font() const +{ + return "Ubuntu Light 10"; +} + +std::string Style::app_license_font() const +{ + return "Ubuntu Light 10"; +} + +std::string Style::app_last_update_font() const +{ + return "Ubuntu Light 10"; +} + +std::string Style::app_copywrite_font() const +{ + return "Ubuntu Light 10"; +} + +std::string Style::info_hint_font() const +{ + return "Ubuntu Light 10"; +} + +std::string Style::info_hint_bold_font() const +{ + return "Ubuntu Bold 10"; +} + +std::string Style::user_rating_font() const +{ + return "Ubuntu Light 10"; +} + +std::string Style::no_preview_image_font() const +{ + return "Ubuntu Light 16"; +} + +std::string Style::track_font() const +{ + return "Ubuntu Light 10"; +} + + + +nux::BaseTexture* Style::GetNavLeftIcon() +{ + return pimpl->preview_nav_left_texture_.texture(); +} + +nux::BaseTexture* Style::GetNavRightIcon() +{ + return pimpl->preview_nav_right_texture_.texture(); +} + +nux::BaseTexture* Style::GetPlayIcon() +{ + return pimpl->preview_play_texture_.texture(); +} + +nux::BaseTexture* Style::GetPauseIcon() +{ + return pimpl->preview_pause_texture_.texture(); +} + +nux::BaseTexture* Style::GetSearchSpinIcon(int size) +{ + return pimpl->preview_spin_texture_.texture(size); +} + + +} // namespace previews +} // namespace dash +} // namespace unity diff --git a/unity-shared/PreviewStyle.h b/unity-shared/PreviewStyle.h new file mode 100644 index 000000000..23c9ba2f8 --- /dev/null +++ b/unity-shared/PreviewStyle.h @@ -0,0 +1,139 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#ifndef PREVIEWSTYLE_H +#define PREVIEWSTYLE_H + +#include <Nux/Nux.h> +#include <Nux/View.h> + +#include <string> +#include <memory> + +namespace nux +{ + class BaseTexture; +} + +namespace unity +{ +namespace dash +{ +namespace previews +{ + +enum class Orientation { + UP, + DOWN, + LEFT, + RIGHT +}; + +class Style +{ +public: + Style(); + ~Style(); + + static Style& Instance(); + + int GetNavigatorWidth() const; + int GetNavigatorIconSize() const; + + float GetPreviewAspectRatio() const; + + int GetDetailsTopMargin() const; + int GetDetailsBottomMargin() const; + int GetDetailsRightMargin() const; + int GetDetailsLeftMargin() const; + int GetPanelSplitWidth() const; + + int GetSpaceBetweenTitleAndSubtitle() const; + + int GetActionButtonHeight() const; + int GetSpaceBetweenActions() const; + int GetActionButtonMaximumWidth() const; + + int GetDetailsPanelMinimumWidth() const; + + int GetInfoHintIconSizeWidth() const; + int GetInfoHintNameMinimumWidth() const; + int GetInfoHintNameMaximumWidth() const; + + float GetDescriptionLineSpacing() const; + int GetDescriptionLineCount() const; + + int GetRatingWidgetHeight() const; + + std::string title_font() const; + std::string subtitle_size_font() const; + std::string description_font() const; + + //////////////////////////////// + // Application Preview + std::string app_license_font() const; + std::string app_last_update_font() const; + std::string app_copywrite_font() const; + std::string info_hint_font() const; + std::string info_hint_bold_font() const; + std::string user_rating_font() const; + std::string no_preview_image_font() const; + + float GetAppImageAspectRatio() const; + + int GetAppIconAreaWidth() const; + int GetSpaceBetweenIconAndDetails() const; + //////////////////////////////// + + //////////////////////////////// + // Music Preview + std::string track_font() const; + + int GetTrackHeight() const; + //////////////////////////////// + + //////////////////////////////// + // Movie Preview + float GetVideoImageAspectRatio() const; + + int GetTrackBarHeight() const; + int GetMusicDurationWidth() const; + int GetStatusIconSize() const; + //////////////////////////////// + + nux::BaseTexture* GetNavLeftIcon(); + nux::BaseTexture* GetNavRightIcon(); + nux::BaseTexture* GetPlayIcon(); + nux::BaseTexture* GetPauseIcon(); + nux::BaseTexture* GetSearchSpinIcon(int size = -1); + +protected: + class Impl; + std::unique_ptr<Impl> pimpl; + +}; + +} +} +} + +#endif //PREVIEWSTYLE_H diff --git a/unity-shared/RatingsButton.cpp b/unity-shared/RatingsButton.cpp new file mode 100644 index 000000000..c479c65ff --- /dev/null +++ b/unity-shared/RatingsButton.cpp @@ -0,0 +1,278 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Gordon Allott <gord.allott@canonical.com> + * + */ + +#include <math.h> + +#include <Nux/Nux.h> +#include <NuxCore/Logger.h> + +#include "RatingsButton.h" +#include "DashStyle.h" + +namespace +{ +const int num_stars = 5; +} + +namespace unity +{ +RatingsButton::RatingsButton(int star_size, int star_gap, NUX_FILE_LINE_DECL) + : nux::ToggleButton(NUX_FILE_LINE_PARAM) + , editable_(true) + , rating_(0.0) + , focused_star_(-1) + , star_size_(star_size) + , star_gap_(star_gap) +{ + SetAcceptKeyNavFocusOnMouseDown(false); + SetAcceptKeyNavFocusOnMouseEnter(true); + + mouse_up.connect(sigc::mem_fun(this, &RatingsButton::RecvMouseUp)); + mouse_move.connect(sigc::mem_fun(this, &RatingsButton::RecvMouseMove)); + mouse_drag.connect(sigc::mem_fun(this, &RatingsButton::RecvMouseDrag)); + + key_nav_focus_change.connect([&](nux::Area* area, bool has_focus, nux::KeyNavDirection direction) + { + if (has_focus && direction != nux::KEY_NAV_NONE) + focused_star_ = 0; + else if (!has_focus) + focused_star_ = -1; + + QueueDraw(); + }); + key_nav_focus_activate.connect([&](nux::Area*) { SetRating(static_cast<float>(focused_star_+1)/num_stars); }); + key_down.connect(sigc::mem_fun(this, &RatingsButton::OnKeyDown)); +} + +RatingsButton::~RatingsButton() +{ +} + +void RatingsButton::SetEditable(bool editable) +{ + editable_ = editable; + if (!editable_) + focused_star_ = -1; + QueueDraw(); +} + +void RatingsButton::SetRating(float rating) +{ + rating_ = rating; + QueueDraw(); +} + +float RatingsButton::GetRating() const +{ + return rating_; +} + +void RatingsButton::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) +{ + int rating = static_cast<int>(rating_ * num_stars); + // FIXME: 9/26/2011 + // We should probably support an API for saying whether the ratings + // should or shouldn't support half stars...but our only consumer at + // the moment is the applications lens which according to design + // (Bug #839759) shouldn't. So for now just force rounding. + // int total_half_stars = rating % 2; + // int total_full_stars = rating / 2; + int total_full_stars = rating; + + nux::Geometry const& geo = GetGeometry(); + nux::Geometry geo_star(geo); + geo_star.width = star_size_; + geo_star.height = star_size_; + + gPainter.PaintBackground(GfxContext, geo); + // set up our texture mode + nux::TexCoordXForm texxform; + texxform.SetWrap(nux::TEXWRAP_CLAMP_TO_BORDER, nux::TEXWRAP_CLAMP_TO_BORDER); + texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_SCALE_COORD); + texxform.SetFilter(nux::TEXFILTER_LINEAR, nux::TEXFILTER_LINEAR); + + // clear what is behind us + unsigned int alpha = 0, src = 0, dest = 0; + + GfxContext.GetRenderStates().GetBlend(alpha, src, dest); + GfxContext.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + nux::Color col = nux::color::Black; + col.alpha = 0; + GfxContext.QRP_Color(geo.x, + geo.y, + geo.width, + geo.height, + col); + + for (int index = 0; index < num_stars; ++index) + { + dash::Style& style = dash::Style::Instance(); + nux::BaseTexture* texture = style.GetStarSelectedIcon(); + if (index < total_full_stars) + { + if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_NORMAL) + texture = style.GetStarSelectedIcon(); + else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT) + texture = style.GetStarSelectedIcon(); + else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRESSED) + texture = style.GetStarSelectedIcon(); + } + else + { + if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_NORMAL) + texture = style.GetStarDeselectedIcon(); + else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT) + texture = style.GetStarDeselectedIcon(); + else if (GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRESSED) + texture = style.GetStarDeselectedIcon(); + } + + GfxContext.QRP_1Tex(geo_star.x, + geo_star.y, + geo_star.width, + geo_star.height, + texture->GetDeviceTexture(), + texxform, + nux::Color(1.0f, 1.0f, 1.0f, 1.0f)); + + if (focused_star_ == index) + { + GfxContext.QRP_1Tex(geo_star.x, + geo_star.y, + geo_star.width, + geo_star.height, + style.GetStarHighlightIcon()->GetDeviceTexture(), + texxform, + nux::Color(1.0f, 1.0f, 1.0f, 0.5f)); + } + + geo_star.x += geo_star.width + star_gap_; + + } + + GfxContext.GetRenderStates().SetBlend(alpha, src, dest); + +} + +void RatingsButton::UpdateRatingToMouse(int x) +{ + int width = num_stars*star_size_ + (num_stars-1)*star_gap_; + float new_rating = (static_cast<float>(x) / width); + + // FIXME: change to * 2 once we decide to support also half-stars + new_rating = ceil((num_stars * 1) * new_rating) / (num_stars * 1); + new_rating = (new_rating > 1) ? 1 : ((new_rating < 0) ? 0 : new_rating); + + SetRating(new_rating); +} + +void RatingsButton::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags) +{ + if (!editable_) + return; + + UpdateRatingToMouse(x); +} + +void RatingsButton::RecvMouseDrag(int x, int y, int dx, int dy, + unsigned long button_flags, + unsigned long key_flags) +{ + if (!editable_) + return; + + UpdateRatingToMouse(x); +} + +void RatingsButton::RecvMouseMove(int x, int y, int dx, int dy, + unsigned long button_flags, + unsigned long key_flags) +{ + if (!editable_) + return; + + int width = num_stars*star_size_+ (num_stars-1)*star_gap_; + focused_star_ = std::max(0, std::min(static_cast<int>(ceil((static_cast<float>(x) / width) * num_stars) - 1), num_stars - 1)); + + if (!HasKeyFocus()) + nux::GetWindowCompositor().SetKeyFocusArea(this); + + QueueDraw(); +} + + +bool RatingsButton::InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character) +{ + nux::KeyNavDirection direction = nux::KEY_NAV_NONE; + + switch (keysym) + { + case NUX_VK_LEFT: + direction = nux::KeyNavDirection::KEY_NAV_LEFT; + break; + case NUX_VK_RIGHT: + direction = nux::KeyNavDirection::KEY_NAV_RIGHT; + break; + default: + direction = nux::KeyNavDirection::KEY_NAV_NONE; + break; + } + + if (direction == nux::KeyNavDirection::KEY_NAV_NONE) + return false; + else if (direction == nux::KEY_NAV_LEFT && (focused_star_ <= 0)) + return false; + else if (direction == nux::KEY_NAV_RIGHT && (focused_star_ >= num_stars - 1)) + return false; + else + return true; +} + + +void RatingsButton::OnKeyDown(unsigned long event_type, unsigned long event_keysym, + unsigned long event_state, const TCHAR* character, + unsigned short key_repeat_count) +{ + if (!editable_) + return; + + switch (event_keysym) + { + case NUX_VK_LEFT: + --focused_star_; + break; + case NUX_VK_RIGHT: + ++focused_star_; + break; + default: + return; + } + + QueueDraw(); +} + +bool RatingsButton::AcceptKeyNavFocus() +{ + return true; +} + +} // namespace unity diff --git a/unity-shared/RatingsButton.h b/unity-shared/RatingsButton.h new file mode 100644 index 000000000..9364c0f2c --- /dev/null +++ b/unity-shared/RatingsButton.h @@ -0,0 +1,74 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Gordon Allott <gord.allott@canonical.com> + * + */ + +#ifndef UNITYSHELL_RATINGSBUTTONWIDGET_H +#define UNITYSHELL_RATINGSBUTTONWIDGET_H + +#include <memory> + +#include <Nux/Nux.h> +#include <Nux/ToggleButton.h> + + + +namespace unity +{ + +class RatingsButton : public nux::ToggleButton +{ +public: + RatingsButton(int star_size, int star_gap, NUX_FILE_LINE_PROTO); + virtual ~RatingsButton(); + + void SetEditable(bool editable); + virtual void SetRating(float rating); + virtual float GetRating() const; + +protected: + virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); + + // Key-nav + virtual bool AcceptKeyNavFocus(); + virtual bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character); + +private: + void OnKeyDown(unsigned long event_type, unsigned long event_keysym, + unsigned long event_state, const TCHAR* character, + unsigned short key_repeat_count); + + void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags); + void RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); + void RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); + void UpdateRatingToMouse(int x); + + +protected: + bool editable_; + float rating_; + int focused_star_; + int star_size_; + int star_gap_; +}; + +} // namespace unity + +#endif // UNITYSHELL_RATINGSBUTTONWIDGET_H + diff --git a/unity-shared/SearchBar.cpp b/unity-shared/SearchBar.cpp index 31f69f100..0be1c8361 100644 --- a/unity-shared/SearchBar.cpp +++ b/unity-shared/SearchBar.cpp @@ -251,10 +251,8 @@ void SearchBar::Init() expand_icon_->mouse_click.connect(mouse_expand); } - sig_manager_.Add(new glib::Signal<void, GtkSettings*, GParamSpec*> - (gtk_settings_get_default(), - "notify::gtk-font-name", - sigc::mem_fun(this, &SearchBar::OnFontChanged))); + sig_manager_.Add<void, GtkSettings*, GParamSpec*>(gtk_settings_get_default(), "notify::gtk-font-name", + sigc::mem_fun(this, &SearchBar::OnFontChanged)); OnFontChanged(gtk_settings_get_default()); search_hint.changed.connect([&](std::string const& s) { OnSearchHintChanged(); }); diff --git a/unity-shared/StaticCairoText.cpp b/unity-shared/StaticCairoText.cpp index 7d9a3e2e9..0f51dfb14 100644 --- a/unity-shared/StaticCairoText.cpp +++ b/unity-shared/StaticCairoText.cpp @@ -58,7 +58,7 @@ struct StaticCairoText::Impl std::string GetEffectiveFont() const; Size GetTextExtents() const; - void DrawText(cairo_t* cr, int width, int height, Color const& color); + void DrawText(cairo_t* cr, int width, int height, int line_spacing, Color const& color); void UpdateTexture(); void OnFontChanged(); @@ -67,7 +67,7 @@ struct StaticCairoText::Impl StaticCairoText* parent_; bool accept_key_nav_focus_; - bool need_new_extent_cache_; + mutable bool need_new_extent_cache_; // The three following are all set in get text extents. mutable Size cached_extent_; mutable Size cached_base_; @@ -88,6 +88,7 @@ struct StaticCairoText::Impl int lines_; int actual_lines_; + float line_spacing_; }; StaticCairoText::Impl::Impl(StaticCairoText* parent, std::string const& text) @@ -104,6 +105,7 @@ StaticCairoText::Impl::Impl(StaticCairoText* parent, std::string const& text) // the desired height of the layout in Pango units if positive, or desired // number of lines if negative. , actual_lines_(0) + , line_spacing_(0.5) { GtkSettings* settings = gtk_settings_get_default(); // not ref'ed g_signal_connect(settings, "notify::gtk-font-name", @@ -190,6 +192,13 @@ void StaticCairoText::SetLines(int lines) QueueDraw(); } +void StaticCairoText::SetLineSpacing(float line_spacing) +{ + pimpl->line_spacing_ = line_spacing; + pimpl->UpdateTexture(); + QueueDraw(); +} + void StaticCairoText::PreLayoutManagement() { Geometry geo = GetGeometry(); @@ -300,6 +309,29 @@ void StaticCairoText::SetText(std::string const& text) } } +void StaticCairoText::SetMaximumSize(int w, int h) +{ + if (w != GetMaximumWidth()) + { + pimpl->need_new_extent_cache_ = true; + View::SetMaximumSize(w, h); + pimpl->UpdateTexture(); + return; + } + + View::SetMaximumSize(w, h); +} + +void StaticCairoText::SetMaximumWidth(int w) +{ + if (w != GetMaximumWidth()) + { + pimpl->need_new_extent_cache_ = true; + View::SetMaximumWidth(w); + pimpl->UpdateTexture(); + } +} + std::string StaticCairoText::GetText() const { return pimpl->text_; @@ -324,12 +356,15 @@ void StaticCairoText::SetTextColor(Color const& textColor) void StaticCairoText::SetFont(std::string const& font) { - pimpl->font_ = font; - pimpl->need_new_extent_cache_ = true; - Size s = GetTextExtents(); - SetMinimumHeight(s.height); - NeedRedraw(); - sigFontChanged.emit(this); + if (pimpl->font_ != font) + { + pimpl->font_ = font; + pimpl->need_new_extent_cache_ = true; + Size s = GetTextExtents(); + SetMinimumHeight(s.height); + NeedRedraw(); + sigFontChanged.emit(this); + } } int StaticCairoText::GetLineCount() const @@ -400,9 +435,10 @@ Size StaticCairoText::Impl::GetTextExtents() const pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_ellipsize(layout, GetPangoEllipsizeMode()); pango_layout_set_alignment(layout, GetPangoAlignment()); - pango_layout_set_markup(layout, text_.c_str(), -1); pango_layout_set_height(layout, lines_); pango_layout_set_width(layout, maxwidth * PANGO_SCALE); + pango_layout_set_markup(layout, text_.c_str(), -1); + pango_layout_set_spacing(layout, line_spacing_ * PANGO_SCALE); pangoCtx = pango_layout_get_context(layout); // is not ref'ed pango_cairo_context_set_font_options(pangoCtx, @@ -430,6 +466,7 @@ Size StaticCairoText::Impl::GetTextExtents() const result.height = std::ceil(static_cast<float>(logRect.height) / PANGO_SCALE); cached_extent_ = result; baseline_ = pango_layout_get_baseline(layout) / PANGO_SCALE; + need_new_extent_cache_ = false; // clean up pango_font_description_free(desc); @@ -442,6 +479,7 @@ Size StaticCairoText::Impl::GetTextExtents() const void StaticCairoText::Impl::DrawText(cairo_t* cr, int width, int height, + int line_spacing, Color const& color) { PangoLayout* layout = NULL; @@ -464,6 +502,7 @@ void StaticCairoText::Impl::DrawText(cairo_t* cr, pango_layout_set_markup(layout, text_.c_str(), -1); pango_layout_set_width(layout, width * PANGO_SCALE); pango_layout_set_height(layout, height * PANGO_SCALE); + pango_layout_set_spacing(layout, line_spacing * PANGO_SCALE); pango_layout_set_height(layout, lines_); pangoCtx = pango_layout_get_context(layout); // is not ref'ed @@ -510,7 +549,7 @@ void StaticCairoText::Impl::UpdateTexture() geo.width, geo.height); DrawText(cairo_graphics.GetInternalContext(), - geo.width, geo.height, text_color_); + geo.width, geo.height, line_spacing_, text_color_); texture2D_ = texture_ptr_from_cairo_graphics(cairo_graphics); } diff --git a/unity-shared/StaticCairoText.h b/unity-shared/StaticCairoText.h index 83580aeae..d3ddf1a8f 100644 --- a/unity-shared/StaticCairoText.h +++ b/unity-shared/StaticCairoText.h @@ -75,6 +75,7 @@ public: void SetTextVerticalAlignment(AlignState state); void SetFont(std::string const& font); void SetLines(int maximum_lines); + void SetLineSpacing(float line_spacing); std::string GetText() const; Color GetTextColor() const; @@ -91,6 +92,9 @@ public: void SetAcceptKeyNavFocus(bool accept); + void SetMaximumSize(int w, int h); + void SetMaximumWidth(int w); + protected: // Key navigation virtual bool AcceptKeyNavFocus(); diff --git a/unity-shared/TextureThumbnailProvider.cpp b/unity-shared/TextureThumbnailProvider.cpp new file mode 100644 index 000000000..128daf8bf --- /dev/null +++ b/unity-shared/TextureThumbnailProvider.cpp @@ -0,0 +1,175 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#include <Nux/Nux.h> +#include "ThumbnailGenerator.h" +#include "UnityCore/GLibWrapper.h" +#include "TextureThumbnailProvider.h" + +namespace unity +{ + +namespace TextureThumbnailProvider +{ + +class GdkTextureThumbnailer : public Thumbnailer +{ +public: + GdkTextureThumbnailer(std::string const& name) + : name(name) + {} + + std::string name; + + virtual std::string GetName() const { return name; } + + virtual bool Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint); +}; + + +bool GdkTextureThumbnailer::Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint) +{ + GFileInputStream *stream; + GError *error = NULL; + GFile *file; + + /* try to open the source file for reading */ + file = g_file_new_for_uri (input_file.c_str()); + stream = g_file_read (file, NULL, &error); + g_object_unref (file); + + if (error != NULL) + { + error_hint = error->message; + g_error_free (error); + return false; + } + + glib::Object<GdkPixbuf> source_pixbuf(::gdk_pixbuf_new_from_stream_at_scale(G_INPUT_STREAM (stream), + -1, + size, + TRUE, + NULL, + NULL)); + + // glib::Object<GdkPixbuf> source_pixbuf(gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), + // NULL, &error)); + g_object_unref (stream); + + if (error != NULL) + { + error_hint = error->message; + g_error_free (error); + return false; + } + + /************************** + * Generate Scaled buffer * + **************************/ + + gdouble hratio; + gdouble wratio; + gint dest_width = size; + gint dest_height = size; + gint source_width; + gint source_height; + + /* determine the source pixbuf dimensions */ + source_width = gdk_pixbuf_get_width (source_pixbuf); + source_height = gdk_pixbuf_get_height (source_pixbuf); + + /* return the same pixbuf if no scaling is required */ + if (source_width <= dest_width && source_height <= dest_height) + { + gdk_pixbuf_save(source_pixbuf, output_file.c_str(), "png", &error, NULL); + if (error != NULL) + { + error_hint = error->message; + g_error_free (error); + return false; + } + } + + /* determine which axis needs to be scaled down more */ + wratio = (gdouble) source_width / (gdouble) dest_width; + hratio = (gdouble) source_height / (gdouble) dest_height; + + /* adjust the other axis */ + if (hratio > wratio) + dest_width = rint (source_width / hratio); + else + dest_height = rint (source_height / wratio); + + + /* scale the pixbuf down to the desired size */ + glib::Object<GdkPixbuf> thumbnail_buffer(gdk_pixbuf_scale_simple (source_pixbuf, + MAX (dest_width, 1), MAX (dest_height, 1), + GDK_INTERP_BILINEAR)); + + gdk_pixbuf_save(thumbnail_buffer, output_file.c_str(), "png", &error, NULL); + if (error != NULL) + { + error_hint = error->message; + g_error_free (error); + return false; + } + return true; +} + +void Initialise() +{ + GSList *formats; + GSList *fp; + GStrv format_types; + guint n; + std::list<std::string> mime_types; + + /* get a list of all formats supported by GdkPixbuf */ + formats = gdk_pixbuf_get_formats (); + + /* iterate over all formats */ + for (fp = formats; fp != NULL; fp = fp->next) + { + /* ignore the disabled ones */ + if (!gdk_pixbuf_format_is_disabled ((GdkPixbufFormat*)fp->data)) + { + /* get a list of MIME types supported by this format */ + format_types = gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat*)fp->data); + + /* put them all in the unqiue MIME type hash table */ + for (n = 0; format_types != NULL && format_types[n] != NULL; ++n) + { + mime_types.push_back(format_types[n]); + } + + /* free the string array */ + g_strfreev (format_types); + } + } + + + Thumbnailer::Ptr thumbnailer(new GdkTextureThumbnailer("gdk_pixelbuffer")); + ThumbnailGenerator::RegisterThumbnailer(mime_types, thumbnailer); +} + +} // namespace TextureThumbnailProvider +} // namespace unity + diff --git a/unity-shared/TextureThumbnailProvider.h b/unity-shared/TextureThumbnailProvider.h new file mode 100644 index 000000000..3d16fddc0 --- /dev/null +++ b/unity-shared/TextureThumbnailProvider.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#ifndef UNITYSHARED_TEXTURETHUMBNAILPROVIDER_H +#define UNITYSHARED_TEXTURETHUMBNAILPROVIDER_H + +#include <Nux/Nux.h> + +namespace unity +{ + +namespace TextureThumbnailProvider +{ + void Initialise(); +}; + +} // namespace unity + +#endif // UNITYSHARED_TEXTURETHUMBNAILPROVIDER_H + diff --git a/unity-shared/ThumbnailGenerator.cpp b/unity-shared/ThumbnailGenerator.cpp new file mode 100644 index 000000000..c65f99ea0 --- /dev/null +++ b/unity-shared/ThumbnailGenerator.cpp @@ -0,0 +1,539 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#include <pthread.h> +#include <NuxCore/Logger.h> +#include "UnityCore/GLibSource.h" +#include "UnityCore/DesktopUtilities.h" +#include "ThumbnailGenerator.h" +#include <glib/gstdio.h> +#include <unordered_map> + +#include "TextureThumbnailProvider.h" +#include "DefaultThumbnailProvider.h" +#include "UserThumbnailProvider.h" +#include "config.h" + +namespace unity +{ + +namespace +{ + nux::logging::Logger logger("unity.thumbnailgenerator"); + ThumbnailGenerator* thumbnail_instance = nullptr; + + const unsigned int CLEANUP_DURATION = 60*1000; // 1 minute + const unsigned int CLEANUP_PREVIEW_AGE = 6*60*60*1000; // 6 hours + + static std::multimap<std::string, std::string> thumbnail_content_map; + static std::map<std::string, Thumbnailer::Ptr> thumbnailers_; + + pthread_mutex_t thumbnailers_mutex_ = PTHREAD_MUTEX_INITIALIZER; + + static std::string get_preview_dir() + { + return DesktopUtilities::GetUserDataDirectory().append("/previews"); + } +} + + +class Thumbnail +{ +public: + typedef std::shared_ptr<Thumbnail> Ptr; + + Thumbnail(std::string const& uri, unsigned int size, ThumbnailNotifier::Ptr notifier); + + virtual ~Thumbnail(); + + std::string Generate(std::string& error_hint); + + std::string const uri_; + unsigned int size_; + ThumbnailNotifier::Ptr notifier_; +}; + +NUX_IMPLEMENT_OBJECT_TYPE(ThumbnailNotifier); + +ThumbnailNotifier::ThumbnailNotifier() +: cancel_(g_cancellable_new()) +{ + +} + +void ThumbnailNotifier::Cancel() +{ + g_cancellable_cancel(cancel_); +} + +bool ThumbnailNotifier::IsCancelled() const +{ + return g_cancellable_is_cancelled(cancel_); +} + +class ThumbnailGeneratorImpl +{ +public: + ThumbnailGeneratorImpl(ThumbnailGenerator* parent) + : parent_(parent) + , thumbnails_mutex_(PTHREAD_MUTEX_INITIALIZER) + , thumbnail_thread_is_running_(false) + , thumbnail_thread_(0) + {} + + ~ThumbnailGeneratorImpl() + { + pthread_join(thumbnail_thread_, NULL); + } + + ThumbnailNotifier::Ptr GetThumbnail(std::string const& uri, int size); + void DoCleanup(); + + bool OnThumbnailComplete(); + + static std::list<Thumbnailer::Ptr> GetThumbnailers(std::string const& content_type, std::string& error_hint); + + void RunGenerate(); + void RunManagement(); + +private: + void StartCleanupTimer(); + +private: + ThumbnailGenerator* parent_; + + glib::Source::UniquePtr thread_create_timer_; + glib::Source::UniquePtr thread_return_timer_; + + /* Our mutex used when accessing data shared between the main thread and the + thumbnail thread, i.e. the thumbnail_thread_is_running flag and the + thumbnails_to_make list. */ + pthread_mutex_t thumbnails_mutex_; + + /* A flag to indicate whether a thumbnail thread is running, so we don't + start more than one. Lock thumbnails_mutex when accessing this. */ + volatile bool thumbnail_thread_is_running_; + pthread_t thumbnail_thread_; + + volatile bool management_thread_is_running_; + pthread_t management_thread_; + + glib::Source::UniquePtr cleanup_timer_; + + std::queue<Thumbnail::Ptr> thumbnails_; + + struct CompleteThumbnail + { + std::string thubnail_uri; + std::string error_hint; + ThumbnailNotifier::Ptr notifier; + }; + std::list<CompleteThumbnail> complete_thumbnails_; +}; + +static void* thumbnail_thread_start (void* data) +{ + ((ThumbnailGeneratorImpl*)data)->RunGenerate(); + return NULL; +} + +bool CheckCache(std::string const& uri_in, std::string& filename_out) +{ + // Check Cache. + std::hash<std::string> hash_fn; + std::stringstream ss_chache_thum; + ss_chache_thum << get_preview_dir() << "/" << hash_fn(uri_in) << ".png"; + filename_out = ss_chache_thum.str(); + + glib::Object<GFile> cache_file(g_file_new_for_path(filename_out.c_str())); + return g_file_query_exists(cache_file, NULL); +} + +ThumbnailNotifier::Ptr ThumbnailGeneratorImpl::GetThumbnail(std::string const& uri, int size) +{ + std::string cache_filename; + if (CheckCache(uri, cache_filename)) + { + pthread_mutex_lock (&thumbnails_mutex_); + + CompleteThumbnail complete_thumb; + complete_thumb.thubnail_uri = cache_filename; + complete_thumb.notifier = new ThumbnailNotifier(); + complete_thumbnails_.push_back(complete_thumb); + + // Delay the thumbnail update until after this method has returned with the notifier + if (!thread_return_timer_) + { + thread_return_timer_.reset(new glib::Timeout(0, sigc::mem_fun(this, &ThumbnailGeneratorImpl::OnThumbnailComplete), glib::Source::Priority::LOW)); + } + + pthread_mutex_unlock (&thumbnails_mutex_); + + StartCleanupTimer(); + + return complete_thumb.notifier; + } + + pthread_mutex_lock (&thumbnails_mutex_); + /********************************* + * MUTEX LOCKED + *********************************/ + + if (!thread_create_timer_ && thumbnail_thread_is_running_ == false) + { + thread_create_timer_.reset(new glib::Timeout(0, [&]() + { + thumbnail_thread_is_running_ = true; + pthread_create (&thumbnail_thread_, NULL, thumbnail_thread_start, this); + thread_create_timer_.reset(); + return false; + }, glib::Source::Priority::LOW)); + } + + ThumbnailNotifier::Ptr notifier(new ThumbnailNotifier()); + Thumbnail::Ptr thumb(new Thumbnail(uri, size, notifier)); + thumbnails_.push(thumb); + + pthread_mutex_unlock (&thumbnails_mutex_); + /********************************* + * MUTEX UNLOCKED + *********************************/ + + StartCleanupTimer(); + + + return notifier; +} + +void ThumbnailGeneratorImpl::StartCleanupTimer() +{ + if (!cleanup_timer_) + cleanup_timer_.reset(new glib::Timeout(CLEANUP_DURATION, [&]() { DoCleanup(); return false; })); +} + + +void ThumbnailGeneratorImpl::RunGenerate() +{ + for (;;) + { + /********************************* + * MUTEX LOCKED + *********************************/ + pthread_mutex_lock (&thumbnails_mutex_); + + if (thumbnails_.empty()) + { + thumbnail_thread_is_running_ = FALSE; + pthread_mutex_unlock (&thumbnails_mutex_); + pthread_exit (NULL); + } + + Thumbnail::Ptr thumb(thumbnails_.front()); + thumbnails_.pop(); + + pthread_mutex_unlock (&thumbnails_mutex_); + /********************************* + * MUTEX UNLOCKED + *********************************/ + + if (thumb->notifier_->IsCancelled()) + continue; + + std::string error_hint; + std::string uri_result = thumb->Generate(error_hint); + + /********************************* + * MUTEX LOCKED + *********************************/ + pthread_mutex_lock (&thumbnails_mutex_); + + CompleteThumbnail complete_thumb; + complete_thumb.thubnail_uri = uri_result; + complete_thumb.error_hint = error_hint; + complete_thumb.notifier = thumb->notifier_; + + complete_thumbnails_.push_back(complete_thumb); + + if (!thread_return_timer_) + { + thread_return_timer_.reset(new glib::Timeout(0, sigc::mem_fun(this, &ThumbnailGeneratorImpl::OnThumbnailComplete), glib::Source::Priority::LOW)); + } + + pthread_mutex_unlock (&thumbnails_mutex_); + /********************************* + * MUTEX UNLOCKED + *********************************/ + } +} + +bool ThumbnailGeneratorImpl::OnThumbnailComplete() +{ + for (;;) + { + pthread_mutex_lock (&thumbnails_mutex_); + + if (complete_thumbnails_.empty()) + { + thread_return_timer_.reset(); + pthread_mutex_unlock (&thumbnails_mutex_); + return false; + } + CompleteThumbnail complete_thumbnail = complete_thumbnails_.front(); + complete_thumbnails_.pop_front(); + + pthread_mutex_unlock (&thumbnails_mutex_); + + if (complete_thumbnail.notifier->IsCancelled()) + continue; + + if (complete_thumbnail.error_hint == "") + complete_thumbnail.notifier->ready.emit(complete_thumbnail.thubnail_uri); + else + complete_thumbnail.notifier->error.emit(complete_thumbnail.error_hint); + } + return false; +} + +std::list<Thumbnailer::Ptr> ThumbnailGeneratorImpl::GetThumbnailers(std::string const& content_type, std::string& error_hint) +{ + std::list<Thumbnailer::Ptr> thumbnailer_list; + + gchar** content_split = g_strsplit(content_type.c_str(), "/", -1); + + std::vector<std::string> content_list; + int i = 0; + while(content_split[i] != NULL) + { + if (g_strcmp0(content_split[i], "") != 0) + content_list.push_back(content_split[i]); + i++; + } + + unsigned int content_last = content_list.size(); + for (unsigned int i = 0; i < content_list.size()+1; ++i) + { + std::stringstream ss_content_type; + for (unsigned int j = 0; j < content_last; ++j) + { + ss_content_type << content_list[j]; + if (j < content_last-1) + ss_content_type << "/"; + } + + if (content_last == 0) + ss_content_type << "*"; + else if (content_last < content_list.size()) + ss_content_type << "/*"; + + content_last--; + + /********************************* + * FIND THUMBNAILER + *********************************/ + pthread_mutex_lock (&thumbnailers_mutex_); + + // have already got this content type? + auto range = thumbnail_content_map.equal_range(ss_content_type.str()); + + for (; range.first != range.second; range.first++) + { + // find the thumbnailer. + auto iter_tumbnailers = thumbnailers_.find(range.first->second); + if (iter_tumbnailers != thumbnailers_.end()) + { + thumbnailer_list.push_back(iter_tumbnailers->second); + } + } + pthread_mutex_unlock (&thumbnailers_mutex_); + } + + return thumbnailer_list; +} + +static void* management_thread_start (void* data) +{ + ((ThumbnailGeneratorImpl*)data)->RunManagement(); + return NULL; +} + +void ThumbnailGeneratorImpl::DoCleanup() +{ + cleanup_timer_.reset(); + + if (!management_thread_is_running_) + { + management_thread_is_running_ = true; + pthread_create (&management_thread_, NULL, management_thread_start, this); + } +} + +void ThumbnailGeneratorImpl::RunManagement() +{ + guint64 time = std::time(NULL) - CLEANUP_PREVIEW_AGE; + std::string thumbnail_folder_name = get_preview_dir(); + + GError* err = NULL; + GDir* thumbnailer_dir = g_dir_open(thumbnail_folder_name.c_str(), 0, &err); + if (err != NULL) + return; + + const gchar* file_basename = NULL;; + while ((file_basename = g_dir_read_name(thumbnailer_dir)) != NULL) + { + std::string filename = g_build_filename (thumbnail_folder_name.c_str(), file_basename, NULL); + + glib::Object<GFile> file(g_file_new_for_path(filename.c_str())); + + GError *err = NULL; + glib::Object<GFileInfo> file_info(g_file_query_info(file, G_FILE_ATTRIBUTE_TIME_CREATED, G_FILE_QUERY_INFO_NONE, NULL, &err)); + if (err != NULL) + { + g_error_free (err); + return; + } + + guint64 mtime = g_file_info_get_attribute_uint64(file_info, G_FILE_ATTRIBUTE_TIME_CREATED); + + if (mtime < time) + { + g_unlink(filename.c_str()); + } + } + + thumbnail_thread_is_running_ = false; +} + +ThumbnailGenerator::ThumbnailGenerator() +: pimpl(new ThumbnailGeneratorImpl(this)) +{ + if (thumbnail_instance) + { + LOG_ERROR(logger) << "More than one thumbnail generator created."; + } + else + { + thumbnail_instance = this; + + UserThumbnailProvider::Initialise(); + TextureThumbnailProvider::Initialise(); + DefaultThumbnailProvider::Initialise(); + } + +} + +ThumbnailGenerator::~ThumbnailGenerator() +{ + if (this == thumbnail_instance) + thumbnail_instance = NULL; +} + +ThumbnailGenerator& ThumbnailGenerator::Instance() +{ + if (!thumbnail_instance) + { + LOG_ERROR(logger) << "No thumbnail generator created yet."; + } + + return *thumbnail_instance; +} + +ThumbnailNotifier::Ptr ThumbnailGenerator::GetThumbnail(std::string const& uri, int size) +{ + return pimpl->GetThumbnail(uri, size); +} + +void ThumbnailGenerator::RegisterThumbnailer(std::list<std::string> mime_types, Thumbnailer::Ptr thumbnailer) +{ + pthread_mutex_lock (&thumbnailers_mutex_); + + thumbnailers_[thumbnailer->GetName()] = thumbnailer; + + for (std::string mime_type : mime_types) + { + thumbnail_content_map.insert(std::pair<std::string,std::string>(mime_type, thumbnailer->GetName())); + } + + pthread_mutex_unlock (&thumbnailers_mutex_); +} + +void ThumbnailGenerator::DoCleanup() +{ + pimpl->DoCleanup(); +} + +Thumbnail::Thumbnail(std::string const& uri, unsigned int size, ThumbnailNotifier::Ptr notifier) +: uri_(uri) +, size_(size) +, notifier_(notifier) +{ +} + +Thumbnail::~Thumbnail() +{ +} + +std::string Thumbnail::Generate(std::string& error_hint) +{ + glib::Object<GFile> file(::g_file_new_for_uri(uri_.c_str())); + + GError *err = NULL; + glib::Object<GFileInfo> file_info(g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, NULL, &err)); + if (err != NULL) + { + std::stringstream error_stream; + error_stream << "Could not retrieve file info for '" << uri_ << "'"; + error_hint = error_stream.str(); + g_error_free (err); + return ""; + } + + mkdir(get_preview_dir().c_str(), S_IRWXU); + + std::string file_type = g_file_info_get_attribute_string(file_info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); + + std::list<Thumbnailer::Ptr> thumbnailers = ThumbnailGeneratorImpl::GetThumbnailers(file_type, error_hint); + + std::hash<std::string> hash_fn; + std::stringstream ss_output; + ss_output << get_preview_dir() << "/"; + ss_output << hash_fn(uri_) << ".png"; + + std::string output_file; + for (Thumbnailer::Ptr const& thumbnailer : thumbnailers) + { + output_file = ss_output.str(); + + LOG_TRACE(logger) << "Attempting to generate thumbnail using '" << thumbnailer->GetName() << "' thumbnail provider"; + + if (thumbnailer->Run(size_, uri_, output_file, error_hint)) + { + error_hint.clear(); + return output_file; + } + } + if (error_hint == "") + error_hint = "Could not find thumbnailer"; + return ""; +} + + + +} // namespace unity diff --git a/unity-shared/ThumbnailGenerator.h b/unity-shared/ThumbnailGenerator.h new file mode 100644 index 000000000..f786f3d22 --- /dev/null +++ b/unity-shared/ThumbnailGenerator.h @@ -0,0 +1,85 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#ifndef UNITYSHARED_THUMBNAILGENERATOR_H +#define UNITYSHARED_THUMBNAILGENERATOR_H + +#include <Nux/Nux.h> +#include "UnityCore/GLibWrapper.h" + +namespace unity +{ + +class Thumbnailer +{ +public: + typedef std::shared_ptr<Thumbnailer> Ptr; + + virtual std::string GetName() const = 0; + + virtual bool Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint) = 0; +}; + +class ThumbnailNotifier : public nux::Object +{ +public: + typedef nux::ObjectPtr<ThumbnailNotifier> Ptr; + NUX_DECLARE_OBJECT_TYPE(ThumbnailNotifier, Object); + + ThumbnailNotifier(); + + void Cancel(); + bool IsCancelled() const; + + sigc::signal<void, std::string> ready; + sigc::signal<void, std::string> error; + +private: + glib::Object<GCancellable> cancel_; +}; + + +class ThumbnailGeneratorImpl; + +class ThumbnailGenerator +{ +public: + ThumbnailGenerator(); + virtual ~ThumbnailGenerator(); + + static ThumbnailGenerator& Instance(); + + static void RegisterThumbnailer(std::list<std::string> mime_types, Thumbnailer::Ptr thumbnailer); + + ThumbnailNotifier::Ptr GetThumbnail(std::string const& uri, int size); + + void DoCleanup(); + +protected: + std::unique_ptr<ThumbnailGeneratorImpl> pimpl; + + friend class Thumbnail; +}; + +} // namespace unity + +#endif // UNITYSHARED_THUMBNAILGENERATOR_H + diff --git a/unity-shared/UBusMessages.h b/unity-shared/UBusMessages.h index 603baa19f..c83c92ea3 100644 --- a/unity-shared/UBusMessages.h +++ b/unity-shared/UBusMessages.h @@ -59,9 +59,6 @@ #define UBUS_LAUNCHER_ICON_START_DND "LAUNCHER_ICON_START_DND" #define UBUS_LAUNCHER_ICON_END_DND "LAUNCHER_ICON_END_DND" -// Signal to send on icon action and that you want to request hiding the launcher -#define UBUS_LAUNCHER_ACTION_DONE "LAUNCHER_ACTION_DONE" - // Signal to force the launcher into locked mode, (b) #define UBUS_LAUNCHER_LOCK_HIDE "LAUNCHER_LOCK_HIDE" @@ -82,6 +79,15 @@ // FIXME - fix the nux focus api so we don't need this #define UBUS_RESULT_VIEW_KEYNAV_CHANGED "RESULT_VIEW_KEYNAV_CHANGED" +// for communicating positions to the preview state machine (iii) +// (split y coord in absolute geometry, results to the left, results to the right) +#define UBUS_DASH_PREVIEW_INFO_PAYLOAD "DASH_PREVIEW_INFO_PAYLOAD" + +// called when previews wish to navigate left/right or close (is) +// -1 = left, 0 = close, 1 = right, +// string is the uri string that last result activated was +#define UBUS_DASH_PREVIEW_NAVIGATION_REQUEST "DASH_PREVIEW_NAVIGATION_REQUEST" + // Sends a string datatype containing the new icon name #define UBUS_HUD_ICON_CHANGED "HUD_ICON_CHANGED" #define UBUS_HUD_CLOSE_REQUEST "HUD_CLOSE_REQUEST" diff --git a/unity-shared/UserThumbnailProvider.cpp b/unity-shared/UserThumbnailProvider.cpp new file mode 100644 index 000000000..2b8511480 --- /dev/null +++ b/unity-shared/UserThumbnailProvider.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#include <Nux/Nux.h> +#include "UnityCore/GLibWrapper.h" +#include "UserThumbnailProvider.h" +#include "ThumbnailGenerator.h" + +namespace unity +{ + +namespace UserThumbnailProvider +{ + +class UserThumbnailer : public Thumbnailer +{ +public: + UserThumbnailer(std::string const& name, std::string const& command_line) + : name(name) + , command_line(command_line) + {} + + std::string name; + std::string command_line; + + virtual std::string GetName() const { return name; } + + virtual bool Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint); +}; + +bool UserThumbnailer::Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint) +{ + std::string tmp_command_line = command_line; + + // replace size + size_t pos = tmp_command_line.find("%s"); + std::stringstream ss; ss << size; + if (pos != std::string::npos) { tmp_command_line.replace(pos, 2, ss.str()); } + + // replace input file name + pos = tmp_command_line.find("%u"); + if (pos != std::string::npos) { tmp_command_line.replace(pos, 2, input_file); } + + // replace output file name + pos = tmp_command_line.find("%o"); + if (pos != std::string::npos) { tmp_command_line.replace(pos, 2, output_file); } + + gint exit_status = 0; + GError* err = NULL; + g_spawn_command_line_sync(tmp_command_line.c_str(), NULL, NULL, &exit_status, &err); + if (err != NULL) + { + error_hint = err->message; + g_error_free (err); + return false; + } + else if (exit_status != 0) + { + std::stringstream ss; + ss << "Failed to create thumbnail. Program exited with exit_status=" << exit_status; + error_hint = ss.str(); + return false; + } + + return true; +} + +void Initialise() +{ + GError* err = NULL; + GDir* thumbnailer_dir = g_dir_open("/usr/share/thumbnailers", 0, &err); + if (err != NULL) + return; + + const gchar* file; + while((file = g_dir_read_name(thumbnailer_dir)) != NULL) + { + std::string file_name(file); + if (file_name == "." || file_name == "..") + continue; + + /********************************* + * READ SETTINGS + *********************************/ + + GKeyFile* key_file = g_key_file_new(); + + err=NULL; + if (!g_key_file_load_from_file (key_file, (std::string("/usr/share/thumbnailers/") + file_name).c_str(), G_KEY_FILE_NONE, &err)) + { + g_key_file_free(key_file); + g_error_free(err); + continue; + } + + err=NULL; + glib::String command_line(g_key_file_get_string (key_file, "Thumbnailer Entry", "Exec", &err)); + if (err != NULL) + { + g_key_file_free(key_file); + g_error_free(err); + continue; + } + + err=NULL; + gsize mime_count = 0; + gchar** mime_types = g_key_file_get_string_list (key_file, "Thumbnailer Entry", "MimeType", &mime_count, &err); + if (err != NULL) + { + g_key_file_free(key_file); + g_error_free(err); + continue; + } + + Thumbnailer::Ptr thumbnailer(new UserThumbnailer(file_name, command_line.Value())); + std::list<std::string> mime_type_list; + for (gsize i = 0; i < mime_count && mime_types[i] != NULL; i++) + { + mime_type_list.push_front(mime_types[i]); + } + + ThumbnailGenerator::RegisterThumbnailer(mime_type_list, thumbnailer); + + g_strfreev(mime_types); + g_key_file_free(key_file); + } + + g_dir_close(thumbnailer_dir); +} + +} // namespace DefaultThumbnailProvider +} // namespace unity + + diff --git a/unity-shared/UserThumbnailProvider.h b/unity-shared/UserThumbnailProvider.h new file mode 100644 index 000000000..a3058307c --- /dev/null +++ b/unity-shared/UserThumbnailProvider.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the applicable version of the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of both the GNU Lesser General Public + * License version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + ** + * Authored by: Nick Dedekind <nick.dedekind@canonical.com> + * + */ + +#ifndef UNITYSHARED_USERTHUMBNAILPROVIDER_H +#define UNITYSHARED_USERTHUMBNAILPROVIDER_H + +#include <Nux/Nux.h> + +namespace unity +{ + +namespace UserThumbnailProvider +{ + void Initialise(); +}; + +} // namespace unity + +#endif // UNITYSHARED_USERTHUMBNAILPROVIDER_H + diff --git a/unity-shared/WindowManager.cpp b/unity-shared/WindowManager.cpp index 87d714477..5f5cd6519 100644 --- a/unity-shared/WindowManager.cpp +++ b/unity-shared/WindowManager.cpp @@ -23,22 +23,22 @@ static WindowManager* window_manager = NULL; class WindowManagerDummy : public WindowManager { - guint32 GetActiveWindow() + guint32 GetActiveWindow() const { return 0; } - unsigned long long GetWindowActiveNumber (guint32 xid) + unsigned long long GetWindowActiveNumber (guint32 xid) const { return 0; } - bool IsScreenGrabbed() + bool IsScreenGrabbed() const { return false; } - bool IsViewPortSwitchStarted() + bool IsViewPortSwitchStarted() const { return false; } @@ -48,7 +48,7 @@ class WindowManagerDummy : public WindowManager g_debug("%s", G_STRFUNC); } - bool IsWindowMaximized(guint32 xid) + bool IsWindowMaximized(guint32 xid) const { return false; } @@ -58,42 +58,42 @@ class WindowManagerDummy : public WindowManager return true; } - bool IsWindowOnCurrentDesktop(guint32 xid) + bool IsWindowOnCurrentDesktop(guint32 xid) const { return true; } - bool IsWindowObscured(guint32 xid) + bool IsWindowObscured(guint32 xid) const { return false; } - bool IsWindowMapped(guint32 xid) + bool IsWindowMapped(guint32 xid) const { return true; } - bool IsWindowVisible(guint32 xid) + bool IsWindowVisible(guint32 xid) const { return true; } - bool IsWindowOnTop(guint32 xid) + bool IsWindowOnTop(guint32 xid) const { return false; } - bool IsWindowClosable(guint32 xid) + bool IsWindowClosable(guint32 xid) const { return true; } - bool IsWindowMinimizable(guint32 xid) + bool IsWindowMinimizable(guint32 xid) const { return true; } - bool IsWindowMaximizable(guint32 xid) + bool IsWindowMaximizable(guint32 xid) const { return true; } @@ -182,7 +182,7 @@ class WindowManagerDummy : public WindowManager any = false; } - int WorkspaceCount () + int WorkspaceCount () const { return 1; } @@ -192,13 +192,13 @@ class WindowManagerDummy : public WindowManager g_debug("%s", G_STRFUNC); } - bool IsScaleActive() + bool IsScaleActive() const { g_debug("%s", G_STRFUNC); return false; } - bool IsScaleActiveForGroup() + bool IsScaleActiveForGroup() const { g_debug("%s", G_STRFUNC); return false; @@ -209,7 +209,13 @@ class WindowManagerDummy : public WindowManager g_debug("%s", G_STRFUNC); } - bool IsExpoActive() + bool IsExpoActive() const + { + g_debug("%s", G_STRFUNC); + return false; + } + + bool IsWallActive() const { g_debug("%s", G_STRFUNC); return false; diff --git a/unity-shared/WindowManager.h b/unity-shared/WindowManager.h index 1f828b45a..84ae82485 100644 --- a/unity-shared/WindowManager.h +++ b/unity-shared/WindowManager.h @@ -49,18 +49,18 @@ public: static WindowManager* Default(); static void SetDefault(WindowManager* manager); - virtual guint32 GetActiveWindow() = 0; + virtual guint32 GetActiveWindow() const = 0; - virtual bool IsWindowMaximized(guint32 xid) = 0; + virtual bool IsWindowMaximized(guint32 xid) const = 0; virtual bool IsWindowDecorated(guint32 xid) = 0; - virtual bool IsWindowOnCurrentDesktop(guint32 xid) = 0; - virtual bool IsWindowObscured(guint32 xid) = 0; - virtual bool IsWindowMapped(guint32 xid) = 0; - virtual bool IsWindowVisible(guint32 xid) = 0; - virtual bool IsWindowOnTop(guint32 xid) = 0; - virtual bool IsWindowClosable(guint32 xid) = 0; - virtual bool IsWindowMinimizable(guint32 xid) = 0; - virtual bool IsWindowMaximizable(guint32 xid) = 0; + virtual bool IsWindowOnCurrentDesktop(guint32 xid) const = 0; + virtual bool IsWindowObscured(guint32 xid) const = 0; + virtual bool IsWindowMapped(guint32 xid) const = 0; + virtual bool IsWindowVisible(guint32 xid) const = 0; + virtual bool IsWindowOnTop(guint32 xid) const = 0; + virtual bool IsWindowClosable(guint32 xid) const = 0; + virtual bool IsWindowMinimizable(guint32 xid) const = 0; + virtual bool IsWindowMaximizable(guint32 xid) const = 0; virtual void ShowDesktop() = 0; @@ -74,11 +74,13 @@ public: virtual void Lower(guint32 xid) = 0; virtual void TerminateScale() = 0; - virtual bool IsScaleActive() = 0; - virtual bool IsScaleActiveForGroup() = 0; + virtual bool IsScaleActive() const = 0; + virtual bool IsScaleActiveForGroup() const = 0; virtual void InitiateExpo() = 0; - virtual bool IsExpoActive() = 0; + virtual bool IsExpoActive() const = 0; + + virtual bool IsWallActive() const = 0; virtual void FocusWindowGroup(std::vector<Window> windows, FocusVisibility, int monitor = -1, bool only_top_win = true) = 0; virtual bool ScaleWindowGroup(std::vector<Window> windows, int state, bool force) = 0; @@ -86,8 +88,8 @@ public: virtual void Decorate(guint32 xid) {}; virtual void Undecorate(guint32 xid) {}; - virtual bool IsScreenGrabbed() = 0; - virtual bool IsViewPortSwitchStarted() = 0; + virtual bool IsScreenGrabbed() const = 0; + virtual bool IsViewPortSwitchStarted() const = 0; virtual void MoveResizeWindow(guint32 xid, nux::Geometry geometry) = 0; void StartMove(guint32 xid, int, int); @@ -98,13 +100,13 @@ public: virtual nux::Geometry GetScreenGeometry() const = 0; virtual nux::Geometry GetWorkAreaGeometry(guint32 xid = 0) const = 0; - virtual unsigned long long GetWindowActiveNumber(guint32 xid) = 0; + virtual unsigned long long GetWindowActiveNumber(guint32 xid) const = 0; virtual void SetWindowIconGeometry(Window window, nux::Geometry const& geo) = 0; virtual void CheckWindowIntersections (nux::Geometry const& region, bool &active, bool &any) = 0; - virtual int WorkspaceCount() = 0; + virtual int WorkspaceCount() const = 0; virtual bool saveInputFocus() = 0; virtual bool restoreInputFocus() = 0; |
