summaryrefslogtreecommitdiff
path: root/unity-shared
diff options
authorJason Smith <jason.smith@canonical.com>2012-08-20 11:26:14 -0400
committerJason Smith <jason.smith@canonical.com>2012-08-20 11:26:14 -0400
commit4bb9e17841c65d17c5f4a7d973689a6efede35d4 (patch)
tree530bb53767c4d426a88d7c95439a21015407d97e /unity-shared
parentac0e9588ff9ecde3d8d7df79b416db5a7d1411b0 (diff)
parent02be480ef0d93ecd84b80283d800e3177cbc3b30 (diff)
merge trunk
(bzr r2542.1.3)
Diffstat (limited to 'unity-shared')
-rw-r--r--unity-shared/BGHash.cpp25
-rw-r--r--unity-shared/BGHash.h9
-rw-r--r--unity-shared/CMakeLists.txt8
-rw-r--r--unity-shared/CoverArt.cpp460
-rw-r--r--unity-shared/CoverArt.h100
-rw-r--r--unity-shared/DashStyle.cpp7
-rw-r--r--unity-shared/DefaultThumbnailProvider.cpp78
-rw-r--r--unity-shared/DefaultThumbnailProvider.h38
-rw-r--r--unity-shared/FontSettings.cpp6
-rw-r--r--unity-shared/IconLoader.cpp21
-rw-r--r--unity-shared/IconRenderer.cpp4
-rw-r--r--unity-shared/IconTexture.cpp75
-rw-r--r--unity-shared/IconTexture.h8
-rw-r--r--unity-shared/PlacesVScrollBar.cpp142
-rw-r--r--unity-shared/PlacesVScrollBar.h58
-rw-r--r--unity-shared/PluginAdapter.h40
-rw-r--r--unity-shared/PluginAdapterCompiz.cpp51
-rw-r--r--unity-shared/PluginAdapterStandalone.cpp44
-rw-r--r--unity-shared/PreviewStyle.cpp361
-rw-r--r--unity-shared/PreviewStyle.h139
-rw-r--r--unity-shared/RatingsButton.cpp278
-rw-r--r--unity-shared/RatingsButton.h74
-rw-r--r--unity-shared/SearchBar.cpp6
-rw-r--r--unity-shared/StaticCairoText.cpp59
-rw-r--r--unity-shared/StaticCairoText.h4
-rw-r--r--unity-shared/TextureThumbnailProvider.cpp175
-rw-r--r--unity-shared/TextureThumbnailProvider.h38
-rw-r--r--unity-shared/ThumbnailGenerator.cpp539
-rw-r--r--unity-shared/ThumbnailGenerator.h85
-rw-r--r--unity-shared/UBusMessages.h12
-rw-r--r--unity-shared/UserThumbnailProvider.cpp152
-rw-r--r--unity-shared/UserThumbnailProvider.h38
-rw-r--r--unity-shared/WindowManager.cpp40
-rw-r--r--unity-shared/WindowManager.h36
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;