diff options
| author | Nick Dedekind <nicholas.dedekind@gmail.com> | 2012-08-02 16:44:07 +0100 |
|---|---|---|
| committer | Nick Dedekind <nicholas.dedekind@gmail.com> | 2012-08-02 16:44:07 +0100 |
| commit | 9183c4472b00c749244a432b4821a1baedddc137 (patch) | |
| tree | efa2b8ad695082cf03696e4864d5a212fbb2a5c0 /unity-shared | |
| parent | d860e6560df8e70b2a614ae476c6be1c50cc8b39 (diff) | |
| parent | fde2f5ce406aeb7c1b9753393a152c0f313db457 (diff) | |
Thumbnail Generation for previews.
(bzr r2419.5.2)
Diffstat (limited to 'unity-shared')
| -rw-r--r-- | unity-shared/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | unity-shared/CoverArt.cpp | 301 | ||||
| -rw-r--r-- | unity-shared/CoverArt.h | 25 | ||||
| -rw-r--r-- | unity-shared/DashStyle.cpp | 8 | ||||
| -rw-r--r-- | unity-shared/DefaultThumbnailProvider.cpp | 78 | ||||
| -rw-r--r-- | unity-shared/DefaultThumbnailProvider.h | 38 | ||||
| -rw-r--r-- | unity-shared/IconRenderer.cpp | 6 | ||||
| -rw-r--r-- | unity-shared/KeyboardUtil.cpp | 17 | ||||
| -rw-r--r-- | unity-shared/KeyboardUtil.h | 2 | ||||
| -rw-r--r-- | unity-shared/TextureThumbnailProvider.cpp | 168 | ||||
| -rw-r--r-- | unity-shared/TextureThumbnailProvider.h | 38 | ||||
| -rw-r--r-- | unity-shared/ThumbnailGenerator.cpp | 506 | ||||
| -rw-r--r-- | unity-shared/ThumbnailGenerator.h | 65 | ||||
| -rw-r--r-- | unity-shared/UScreen.cpp | 7 | ||||
| -rw-r--r-- | unity-shared/UScreen.h | 7 |
15 files changed, 1230 insertions, 39 deletions
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt index 96cb50ffe..c1927cb65 100644 --- a/unity-shared/CMakeLists.txt +++ b/unity-shared/CMakeLists.txt @@ -35,6 +35,7 @@ set (UNITY_SHARED_SOURCES CoverArt.cpp BackgroundEffectHelper.cpp DashStyle.cpp + DefaultThumbnailProvider.cpp FontSettings.cpp KeyboardUtil.cpp IMTextEntry.cpp @@ -55,6 +56,8 @@ set (UNITY_SHARED_SOURCES SearchBarSpinner.cpp StaticCairoText.cpp TextureCache.cpp + TextureThumbnailProvider.cpp + ThumbnailGenerator.cpp Timer.cpp UBusWrapper.cpp UScreen.cpp diff --git a/unity-shared/CoverArt.cpp b/unity-shared/CoverArt.cpp index c5c2caa53..010f86f02 100644 --- a/unity-shared/CoverArt.cpp +++ b/unity-shared/CoverArt.cpp @@ -25,6 +25,9 @@ #include "unity-shared/IntrospectableWrappers.h" #include <NuxCore/Logger.h> #include <Nux/VLayout.h> +#include "ThumbnailGenerator.h" +#include "DashStyle.h" +#include "IconLoader.h" namespace unity { @@ -43,30 +46,189 @@ 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(); + + ThumbnailGenerator::Instance().ready.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailGenerated)); + ThumbnailGenerator::Instance().error.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailError)); } CoverArt::~CoverArt() { if (overlay_text_) overlay_text_->UnReference(); + + if (slot_handle_ > 0) + { + IconLoader::GetDefault().DisconnectHandle(slot_handle_); + slot_handle_ = 0; + } } void CoverArt::SetImage(std::string const& image_hint) { - if (overlay_text_ && GetLayout()) + if (slot_handle_ > 0) + { + IconLoader::GetDefault().DisconnectHandle(slot_handle_); + slot_handle_ = 0; + } + + if (GetLayout()) GetLayout()->RemoveChildObject(overlay_text_); - texture_screenshot_.Adopt(nux::CreateTexture2DFromFile(image_hint.c_str(), -1, true)); + GIcon* icon = g_icon_new_for_string(image_hint.c_str(), NULL); - if (!texture_screenshot_ && GetLayout()) + if (g_strrstr(image_hint.c_str(), "://")) { - GetLayout()->AddView(overlay_text_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL, 100.0, nux::LayoutPosition(1)); + // for files on disk, we stretch to maximum aspect ratio. + stretch_image_ = true; + spinner_timeout_.reset(); + waiting_ = false; + + GFileInputStream *stream; + GError *error = NULL; + GFile *file; + + /* try to open the source file for reading */ + file = g_file_new_for_uri (image_hint.c_str()); + stream = g_file_read (file, NULL, &error); + g_object_unref (file); + + if (error != NULL) + { + g_error_free (error); + QueueDraw(); + return; + } + + /* stream image into pixel-buffer. */ + glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error)); + g_object_unref (stream); + + texture_screenshot_.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true)); + g_object_unref(pixbuf); + + if (!texture_screenshot_ && GetLayout()) + { + GetLayout()->AddView(overlay_text_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL, 100.0, nux::LayoutPosition(1)); + ComputeContentSize(); + } + QueueDraw(); + } + else + { + GFile *file = g_file_new_for_path (image_hint.c_str()); + if (g_file_query_exists(file, NULL)) + { + // for files on disk, we stretch to maximum aspect ratio. + stretch_image_ = true; + spinner_timeout_.reset(); + waiting_ = false; + + GFileInputStream *stream; + GError *error = NULL; + + /* try to open the source file for reading */ + stream = g_file_read (file, NULL, &error); + g_object_unref (file); + + if (error != NULL) + { + g_error_free (error); + QueueDraw(); + return; + } + + /* stream image into pixel-buffer. */ + glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error)); + g_object_unref (stream); + + texture_screenshot_.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true)); + + if (!texture_screenshot_ && GetLayout()) + { + GetLayout()->AddView(overlay_text_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL, 100.0, nux::LayoutPosition(1)); + ComputeContentSize(); + } + QueueDraw(); + } + else if (G_IS_ICON(icon)) + { + StartWaiting(); + slot_handle_ = IconLoader::GetDefault().LoadFromGIconString(image_hint, 128, sigc::mem_fun(this, &CoverArt::IconLoaded)); + } + else + { + StartWaiting(); + slot_handle_ = IconLoader::GetDefault().LoadFromIconName(image_hint, 128, sigc::mem_fun(this, &CoverArt::IconLoaded)); + } } + + if (icon != NULL) + g_object_unref(icon); +} + +void CoverArt::GenerateImage(std::string const& uri) +{ + StartWaiting(); + thumb_handle_ = ThumbnailGenerator::Instance().GetThumbnail(uri, 512); +} + +void CoverArt::StartWaiting() +{ + waiting_ = true; + + rotate_matrix_.Rotate_z(0.0f); + rotation_ = 0.0f; + + spinner_timeout_.reset(new glib::TimeoutSeconds(5, [&] + { + texture_screenshot_.Release(); + waiting_ = false; + + 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(); + return false; + })); + QueueDraw(); } +void CoverArt::IconLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf) +{ + if (GetLayout()) + GetLayout()->RemoveChildObject(overlay_text_); + + slot_handle_ = 0; + stretch_image_ = false; + texture_screenshot_.Release(); + waiting_ = false; + spinner_timeout_.reset(); + + if (pixbuf) + { + texture_screenshot_.Adopt(nux::CreateTextureFromPixbuf(pixbuf)); + + QueueDraw(); + } + else if (GetLayout()) + { + GetLayout()->AddView(overlay_text_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL, 100.0, nux::LayoutPosition(1)); + ComputeContentSize(); + } +} + void CoverArt::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw) { nux::Geometry const& base = GetGeometry(); @@ -79,26 +241,32 @@ void CoverArt::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw) nux::Geometry imageDest = base; nux::TexCoordXForm texxform; - 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()); - } - - int border_width = 1; - gfx_engine.QRP_Color(base.x, base.y, base.GetWidth(), base.GetHeight(), nux::Color(0.03f, 0.03f, 0.03f, 0.0f)); + 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); @@ -108,8 +276,9 @@ void CoverArt::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw) texxform.u1 = imageDest.width; texxform.v1 = imageDest.height; - gfx_engine.QRP_1Tex(imageDest.x + (float(base.GetWidth() - imageDest.GetWidth()) / 2) + border_width, - imageDest.y + (float(base.GetHeight() - imageDest.GetHeight()) / 2) + border_width, + int border_width = 1; + gfx_engine.QRP_1Tex(base.x + (float(base.GetWidth() - imageDest.GetWidth()) / 2) + border_width, + base.y + (float(base.GetHeight() - imageDest.GetHeight()) / 2) + border_width, imageDest.width - (border_width * 2), imageDest.height - (border_width * 2), texture_screenshot_.GetPointer()->GetDeviceTexture(), @@ -135,6 +304,48 @@ void CoverArt::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw) base.GetHeight(), nux::Color(0.5f, 0.5, 0.5, 0.15f)); + 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); } @@ -170,6 +381,13 @@ void CoverArt::SetupViews() 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) @@ -177,6 +395,49 @@ void CoverArt::SetFont(std::string const& font) overlay_text_->SetFont(font); } +void CoverArt::OnThumbnailGenerated(unsigned int thumb_handle, std::string const& uri) +{ + if (thumb_handle_ != thumb_handle) + return; + + SetImage(uri); +} + +void CoverArt::OnThumbnailError(unsigned int thumb_handle, std::string const& error_hint) +{ + if (thumb_handle_ != thumb_handle) + return; + + 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(); +} + + +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 index dad9969ae..792655a8f 100644 --- a/unity-shared/CoverArt.h +++ b/unity-shared/CoverArt.h @@ -27,6 +27,7 @@ #include <Nux/Nux.h> #include <Nux/View.h> #include <UnityCore/ApplicationPreview.h> +#include <UnityCore/GLibSource.h> #include "unity-shared/StaticCairoText.h" #include <NuxCore/ObjectPtr.h> @@ -46,7 +47,10 @@ public: 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; @@ -59,9 +63,30 @@ protected: void SetupViews(); + void OnThumbnailGenerated(unsigned int thumb_handle, std::string const& uri); + void OnThumbnailError(unsigned int thumb_handle, std::string const& error_hint); + bool OnFrameTimeout(); + + void IconLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf); + + void StartWaiting(); + 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_; + + // Spinner + bool waiting_; + nux::BaseTexture* spin_; + glib::Source::UniquePtr spinner_timeout_; + glib::Source::UniquePtr frame_timeout_; + nux::Matrix4 rotate_matrix_; + float rotation_; }; } diff --git a/unity-shared/DashStyle.cpp b/unity-shared/DashStyle.cpp index 2b323a531..4676b02a6 100644 --- a/unity-shared/DashStyle.cpp +++ b/unity-shared/DashStyle.cpp @@ -1363,10 +1363,6 @@ void Style::Impl::Text(cairo_t* cr, PangoWeight weight; switch (regular_text_weight_) { - case FontWeight::REGULAR: - weight = PANGO_WEIGHT_NORMAL; - break; - case FontWeight::LIGHT: weight = PANGO_WEIGHT_LIGHT; break; @@ -1374,6 +1370,10 @@ void Style::Impl::Text(cairo_t* cr, case FontWeight::BOLD: weight = PANGO_WEIGHT_BOLD; break; + + case FontWeight::REGULAR: + default: + weight = PANGO_WEIGHT_NORMAL; } pango_font_description_set_weight(desc, weight); diff --git a/unity-shared/DefaultThumbnailProvider.cpp b/unity-shared/DefaultThumbnailProvider.cpp new file mode 100644 index 000000000..2c6210f66 --- /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 ""; + } + + glib::Object<GIcon> icon(g_file_info_get_icon(file_info)); + 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/IconRenderer.cpp b/unity-shared/IconRenderer.cpp index 7e87f9425..f8bbbba66 100644 --- a/unity-shared/IconRenderer.cpp +++ b/unity-shared/IconRenderer.cpp @@ -760,9 +760,9 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, int TextureObjectLocation; int VertexLocation; int TextureCoord0Location; - int FragmentColor; - int ColorifyColor; - int DesatFactor; + int FragmentColor = 0; + int ColorifyColor = 0; + int DesatFactor = 0; if (nux::GetWindowThread()->GetGraphicsEngine().UsingGLSLCodePath()) { diff --git a/unity-shared/KeyboardUtil.cpp b/unity-shared/KeyboardUtil.cpp index b65fbc15a..90806d5e0 100644 --- a/unity-shared/KeyboardUtil.cpp +++ b/unity-shared/KeyboardUtil.cpp @@ -25,17 +25,18 @@ namespace unity { namespace ui { +namespace { + const unsigned int FETCH_MASK = XkbGBN_KeyNamesMask | XkbGBN_ClientSymbolsMask | XkbGBN_GeometryMask; +} KeyboardUtil::KeyboardUtil(Display *display) : display_(display) -{ - unsigned int fetch_mask = XkbGBN_KeyNamesMask | XkbGBN_ClientSymbolsMask | XkbGBN_GeometryMask; - keyboard_ = XkbGetKeyboard (display, fetch_mask, XkbUseCoreKbd); -} + , keyboard_(XkbGetKeyboard(display_, FETCH_MASK, XkbUseCoreKbd)) +{} KeyboardUtil::~KeyboardUtil() { - XkbFreeKeyboard (keyboard_, 0, True); + XkbFreeKeyboard(keyboard_, 0, True); } bool KeyboardUtil::FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& res_section, XkbBoundsRec& res_bounds) const @@ -86,6 +87,9 @@ bool KeyboardUtil::CompareOffsets(int current_x, int current_y, int best_x, int guint KeyboardUtil::ConvertKeyToKeycode(XkbKeyPtr key) const { + if (!keyboard_) + return 0; + int min_code = keyboard_->min_key_code; int max_code = keyboard_->max_key_code; @@ -94,6 +98,7 @@ guint KeyboardUtil::ConvertKeyToKeycode(XkbKeyPtr key) const if (!strncmp(key->name.name, keyboard_->names->keys[i].name, XkbKeyNameLength)) return i; } + return 0; } @@ -186,7 +191,7 @@ guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol) const int code = XKeysymToKeycode(display_, key_symbol); - if (!code) + if (!code || !keyboard_) return result; if (keyboard_->min_key_code > code || keyboard_->max_key_code < code) diff --git a/unity-shared/KeyboardUtil.h b/unity-shared/KeyboardUtil.h index 0df116299..b5ee98146 100644 --- a/unity-shared/KeyboardUtil.h +++ b/unity-shared/KeyboardUtil.h @@ -51,8 +51,8 @@ private: XkbBoundsRec GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, XkbSectionPtr section, XkbGeometryPtr geo) const; - XkbDescPtr keyboard_; Display *display_; + XkbDescPtr keyboard_; }; } diff --git a/unity-shared/TextureThumbnailProvider.cpp b/unity-shared/TextureThumbnailProvider.cpp new file mode 100644 index 000000000..a32b8cd92 --- /dev/null +++ b/unity-shared/TextureThumbnailProvider.cpp @@ -0,0 +1,168 @@ +/* + * 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 (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..04a502c6e --- /dev/null +++ b/unity-shared/ThumbnailGenerator.cpp @@ -0,0 +1,506 @@ +/* + * 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/GLibWrapper.h" +#include "ThumbnailGenerator.h" +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include "TextureThumbnailProvider.h" +#include "DefaultThumbnailProvider.h" + +namespace unity +{ + +namespace +{ + nux::logging::Logger logger("unity.thumbnailgenerator"); + ThumbnailGenerator* thumbnail_instance = nullptr; + static unsigned int last_handle = 1; + + class ThumbnailerProcess : public Thumbnailer + { + public: + ThumbnailerProcess(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); + }; + static std::map<std::string, std::string> thumbnail_content_map; + static std::map<std::string, Thumbnailer::Ptr> thumbnailers_; + static bool all_thumbnailers_initialized = false; + + pthread_mutex_t thumbnailers_mutex_ = PTHREAD_MUTEX_INITIALIZER; +} + +class Thumbnail +{ +public: + typedef std::shared_ptr<Thumbnail> Ptr; + + Thumbnail(std::string const& uri, unsigned int size); + + virtual ~Thumbnail(); + + std::string Generate(std::string& error_hint); + + unsigned int GetHandle() const; + +protected: + std::string const uri_; + unsigned int size_; + const unsigned int handle_; +}; + +class ThumbnailGeneratorImpl +{ +public: + ThumbnailGeneratorImpl(ThumbnailGenerator* parent) + : parent_(parent) + , thumbnails_mutex_(PTHREAD_MUTEX_INITIALIZER) + , thumbnail_thread_is_running_(false) + {} + + ~ThumbnailGeneratorImpl() + { + pthread_join(thumbnail_thread_, NULL); + } + + void Run_(); + + unsigned int GetThumbnail(std::string const& uri, int size); + + bool OnThumbnailComplete(); + + static void LoadThumbnailers(); + static Thumbnailer::Ptr GetThumbnailer(std::string const& content_type, std::string& error_hint); + +protected: + ThumbnailGenerator* parent_; + + glib::Source::UniquePtr idle_; + glib::Source::UniquePtr idle_return_; + + /* 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_; + + std::queue<Thumbnail::Ptr> thumbnails_; + + struct CompleteThumbnail + { + unsigned int handle; + std::string thubnail_uri; + std::string error_hint; + }; + std::list<CompleteThumbnail> complete_thumbnails_; +}; + +static void* +thumbnail_thread_start (void* data) +{ + ((ThumbnailGeneratorImpl*)data)->Run_(); + return NULL; +} + +unsigned int ThumbnailGeneratorImpl::GetThumbnail(std::string const& uri, int size) +{ + pthread_mutex_lock (&thumbnails_mutex_); + /********************************* + * MUTEX LOCKED + *********************************/ + + if (!idle_ && thumbnail_thread_is_running_ == false) + { + idle_.reset(new glib::Idle([&]() + { + + thumbnail_thread_is_running_ = true; + pthread_create (&thumbnail_thread_, NULL, thumbnail_thread_start, this); + idle_.reset(); + return false; + }, glib::Source::Priority::LOW)); + } + + Thumbnail::Ptr thumb(new Thumbnail(uri, size)); + thumbnails_.push(thumb); + unsigned int handle = thumb->GetHandle(); + + pthread_mutex_unlock (&thumbnails_mutex_); + /********************************* + * MUTEX UNLOCKED + *********************************/ + return handle; +} + + +void ThumbnailGeneratorImpl::Run_() +{ + for (;;) + { + /********************************* + * MUTEX LOCKED + *********************************/ + pthread_mutex_lock (&thumbnails_mutex_); + + if (thumbnails_.size() == 0) + { + thumbnail_thread_is_running_ = FALSE; + pthread_mutex_unlock (&thumbnails_mutex_); + pthread_exit (NULL); + } + + pthread_mutex_unlock (&thumbnails_mutex_); + /********************************* + * MUTEX UNLOCKED + *********************************/ + + Thumbnail::Ptr thumb(thumbnails_.front()); + std::string error_hint; + std::string uri_result = thumb->Generate(error_hint); + thumbnails_.pop(); + + + /********************************* + * MUTEX LOCKED + *********************************/ + pthread_mutex_lock (&thumbnails_mutex_); + + CompleteThumbnail complete_thumb; + complete_thumb.handle = thumb->GetHandle(); + complete_thumb.thubnail_uri = uri_result; + complete_thumb.error_hint = error_hint; + + complete_thumbnails_.push_back(complete_thumb); + + if (!idle_return_) + { + idle_return_.reset(new glib::Idle(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_.size() == 0) + { + idle_return_.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.error_hint == "") + parent_->ready.emit(complete_thumbnail.handle, complete_thumbnail.thubnail_uri); + else + parent_->error.emit(complete_thumbnail.handle, complete_thumbnail.error_hint); + } + return false; +} + +void ThumbnailGeneratorImpl::LoadThumbnailers() +{ + if (all_thumbnailers_initialized) + return; + + 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; + + pthread_mutex_lock (&thumbnailers_mutex_); + // Already have this one? + if (thumbnailers_.find(file_name) != thumbnailers_.end()) + { + pthread_mutex_unlock (&thumbnailers_mutex_); + continue; + } + pthread_mutex_unlock (&thumbnailers_mutex_); + + /********************************* + * 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 ThumbnailerProcess(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); + } + + all_thumbnailers_initialized = true; + g_dir_close(thumbnailer_dir); +} + +Thumbnailer::Ptr ThumbnailGeneratorImpl::GetThumbnailer(std::string const& content_type, std::string& error_hint) +{ + LoadThumbnailers(); + + 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 iter_content = thumbnail_content_map.find(ss_content_type.str()); + if (iter_content != thumbnail_content_map.end()) + { + pthread_mutex_unlock (&thumbnailers_mutex_); + + // find the thumbnailer. + auto iter_tumbnailers = thumbnailers_.find(iter_content->second); + if (iter_tumbnailers != thumbnailers_.end()) + return iter_tumbnailers->second; + } + pthread_mutex_unlock (&thumbnailers_mutex_); + } + + error_hint = "thumbnailer not found."; + return NULL; +} + +ThumbnailGenerator::ThumbnailGenerator() +: pimpl(new ThumbnailGeneratorImpl(this)) +{ + if (thumbnail_instance) + { + LOG_ERROR(logger) << "More than one thumbnail generator created."; + } + else + { + thumbnail_instance = this; + + TextureThumbnailProvider::Initialise(); + DefaultThumbnailProvider::Initialise(); + } + +} + +ThumbnailGenerator::~ThumbnailGenerator() +{ + +} + +ThumbnailGenerator& ThumbnailGenerator::Instance() +{ + if (!thumbnail_instance) + { + LOG_ERROR(logger) << "No panel::Style created yet."; + } + + return *thumbnail_instance; +} + +unsigned int 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[mime_type] = thumbnailer->GetName(); + } + + pthread_mutex_unlock (&thumbnailers_mutex_); +} + +Thumbnail::Thumbnail(std::string const& uri, unsigned int size) +: uri_(uri) +, size_(size) +, handle_(last_handle++) +{ +} + +Thumbnail::~Thumbnail() +{ +} + +std::string Thumbnail::Generate(std::string& error_hint) +{ + std::string output_file; + + 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) + { + error_hint = err->message; + g_error_free (err); + return ""; + } + + std::string file_type = g_file_info_get_attribute_string(file_info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); + + Thumbnailer::Ptr thumbnailer = ThumbnailGeneratorImpl::GetThumbnailer(file_type, error_hint); + if (!thumbnailer) + return ""; + + std::hash<std::string> hash_fn; + std::stringstream ss_output; ss_output << "/home/nick/test_thumbnails/" << hash_fn(uri_) << ".png"; + output_file = ss_output.str(); + + if (!thumbnailer->Run(size_, uri_, output_file, error_hint)) + { + return ""; + } + + return output_file; +} + +unsigned int Thumbnail::GetHandle() const +{ + return handle_; +} + +bool ThumbnailerProcess::Run(int size, std::string const& input_file, std::string& output_file, std::string& error_hint) +{ + std::string tmp_command_line = command_line; + + 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()); } + + pos = tmp_command_line.find("%u"); + if (pos != std::string::npos) { tmp_command_line.replace(pos, 2, input_file); } + + 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; + } + + return true; +} + +} // namespace unity \ No newline at end of file diff --git a/unity-shared/ThumbnailGenerator.h b/unity-shared/ThumbnailGenerator.h new file mode 100644 index 000000000..7ea5c348e --- /dev/null +++ b/unity-shared/ThumbnailGenerator.h @@ -0,0 +1,65 @@ +/* + * 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> + +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 ThumbnailGeneratorImpl; +class ThumbnailGenerator +{ +public: + ThumbnailGenerator(); + virtual ~ThumbnailGenerator(); + + static ThumbnailGenerator& Instance(); + + static void RegisterThumbnailer(std::list<std::string> mime_types, Thumbnailer::Ptr thumbnailer); + + unsigned int GetThumbnail(std::string const& uri, int size); + + sigc::signal<void, unsigned int, std::string> ready; + sigc::signal<void, unsigned int, std::string> error; + +protected: + std::unique_ptr<ThumbnailGeneratorImpl> pimpl; + + friend class Thumbnail; +}; + +} // namespace unity + +#endif // UNITYSHARED_THUMBNAILGENERATOR_H + diff --git a/unity-shared/UScreen.cpp b/unity-shared/UScreen.cpp index e33508e30..3b643382d 100644 --- a/unity-shared/UScreen.cpp +++ b/unity-shared/UScreen.cpp @@ -24,17 +24,18 @@ namespace unity namespace { -static UScreen* default_screen_ = nullptr; nux::logging::Logger logger("unity.screen"); } +UScreen* UScreen::default_screen_ = nullptr; + UScreen::UScreen() - : screen_(gdk_screen_get_default(), glib::AddRef()) + : primary_(0) + , screen_(gdk_screen_get_default(), glib::AddRef()) , proxy_("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", G_BUS_TYPE_SYSTEM) - , primary_(0) { size_changed_signal_.Connect(screen_, "size-changed", sigc::mem_fun(this, &UScreen::Changed)); monitors_changed_signal_.Connect(screen_, "monitors-changed", sigc::mem_fun(this, &UScreen::Changed)); diff --git a/unity-shared/UScreen.h b/unity-shared/UScreen.h index 3e44dfeea..f66e07d7a 100644 --- a/unity-shared/UScreen.h +++ b/unity-shared/UScreen.h @@ -55,14 +55,17 @@ private: void Changed(GdkScreen* screen); void Refresh(); -private: +protected: + static UScreen* default_screen_; std::vector<nux::Geometry> monitors_; + int primary_; + +private: glib::Object<GdkScreen> screen_; glib::DBusProxy proxy_; glib::Signal<void, GdkScreen*> size_changed_signal_; glib::Signal<void, GdkScreen*> monitors_changed_signal_; glib::Source::UniquePtr refresh_idle_; - int primary_; }; } // Namespace |
