Merge lp:~3v1n0/unity/fix-load-icon-crash-926658 into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Rejected
Rejected by: Marco Trevisan (Treviño)
Proposed branch: lp:~3v1n0/unity/fix-load-icon-crash-926658
Merge into: lp:unity
Prerequisite: lp:~3v1n0/unity/barrier-timeout
Diff against target: 641 lines (+150/-144)
7 files modified
UnityCore/ModelRowAdaptor.h (+1/-1)
dash/LensView.cpp (+40/-5)
dash/LensView.h (+4/-0)
dash/ResultRendererTile.cpp (+80/-98)
dash/ResultRendererTile.h (+1/-2)
dash/ResultView.cpp (+21/-32)
dash/ResultView.h (+3/-6)
To merge this branch: bzr merge lp:~3v1n0/unity/fix-load-icon-crash-926658
Reviewer Review Type Date Requested Status
Michal Hruby (community) Needs Fixing
Francis Ginther Abstain
jenkins (community) continuous-integration Needs Fixing
Review via email: mp+116091@code.launchpad.net

This proposal supersedes a proposal from 2012-07-20.

Commit message

ResultRendererTile: don't crash in LoadIcon if row.renderer<TextureContainer*>() is null

Description of the change

In ResultRendererTile::LoadIcon we assumed that row.renderer<TextureContainer*>() is always not null; even if this should not happen because it has already just set into ResultRendererTile::Preload it looks like that there are cases that when doing row.set_renderer(new TextureContainer()); in the subsequent row.renderer<TextureContainer*>() returns null.
The implementation of that depends on dee_model_{set,get}_tag (it's basically like doing dee_model_set_tag and dee_model_get_tag), so it seems like that is failing. I've not been able to get a failure in stress tests, btw.

So, at this point, even if it would not the best solution, it's better to add a safety check to prevent crashes.

To post a comment you must log in.
Revision history for this message
Michal Hruby (mhr3) wrote :

Sorry, but I don't like this one bit, dee_model_get_tag can crash if the passed model is not valid (already unreferenced). IMO guarding against null is not going to help, you'll just push the crash to a different place (in the better case, in worse you'll mask the underlying problem completely and there'll be even more random crashes).

review: Needs Fixing
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Yes, that's true... But according to the stacktraces I got (attached to the bug), the crash is not happening because dee_model_get_tag returns an unreferenced pointer, but because it's returning a null one...

I'm wondering if that could happen that could be happen this:

ResultRendererTile::Preload()
ResultRendererTile::Unload()
ResultRendererTile::LoadIcon()

But it would be weird as all seems done in the same thread...

Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

As you alone said in the comment, the renderer is set in Preload(), so the only explanation is that the model is already invalid at that point, but dee notices that and ignores the call (while logging a critical), doing dee_model_get_tag([invalid], tag) will then return NULL of course.

Other times dee doesn't notice that the model is invalid, and crashes inside itself.

Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Well, it's the same I thought, but I'm not getting that on the stacktrace...
However, protecting us from possible invalid pointers is something we should do in any case.

Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

I've reffed the model in ModelRowAdaptor... As you said it's not the full solution, but it's something we can safely do anyway. Let me know if this is better for you.

Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

> I've reffed the model in ModelRowAdaptor... As you said it's not the full
> solution, but it's something we can safely do anyway. Let me know if this is
> better for you.

As mentioned on IRC, I'd rather see a *single* weak ref on the model in LensView? than this. (since adding a reference for each model row isn't a good idea)

review: Needs Fixing
Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Francis Ginther (fginther) wrote :

Review was claimed by accident, please ignore.

review: Abstain
Revision history for this message
Michal Hruby (mhr3) wrote :

Discussed on IRC, but so make sure it doesn't get lost:

1) the model can change, you need to listen to changed signal
2) in the weak notify callback you're basically iterating over the model, which you can't since the model is already dead

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'UnityCore/ModelRowAdaptor.h'
--- UnityCore/ModelRowAdaptor.h 2012-06-19 16:47:56 +0000
+++ UnityCore/ModelRowAdaptor.h 2012-08-10 12:37:21 +0000
@@ -21,8 +21,8 @@
21#define UNITY_MODEL_ROW_H21#define UNITY_MODEL_ROW_H
2222
23#include <string>23#include <string>
24
25#include <dee.h>24#include <dee.h>
25#include "GLibWrapper.h"
2626
27namespace unity27namespace unity
28{28{
2929
=== modified file 'dash/LensView.cpp'
--- dash/LensView.cpp 2012-06-18 02:57:23 +0000
+++ dash/LensView.cpp 2012-08-10 12:37:21 +0000
@@ -123,6 +123,7 @@
123 , filters_expanded(false)123 , filters_expanded(false)
124 , can_refine_search(false)124 , can_refine_search(false)
125 , no_results_active_(false)125 , no_results_active_(false)
126 , results_model_(nullptr)
126{}127{}
127128
128LensView::LensView(Lens::Ptr lens, nux::Area* show_filters)129LensView::LensView(Lens::Ptr lens, nux::Area* show_filters)
@@ -132,6 +133,7 @@
132 , lens_(lens)133 , lens_(lens)
133 , initial_activation_(true)134 , initial_activation_(true)
134 , no_results_active_(false)135 , no_results_active_(false)
136 , results_model_(nullptr)
135{137{
136 SetupViews(show_filters);138 SetupViews(show_filters);
137 SetupCategories();139 SetupCategories();
@@ -175,6 +177,14 @@
175177
176}178}
177179
180LensView::~LensView()
181{
182 if (DEE_IS_MODEL(results_model_))
183 {
184 g_object_weak_unref(G_OBJECT(results_model_), (GWeakNotify)LensView::OnModelDestroyed, this);
185 }
186}
187
178void LensView::SetupViews(nux::Area* show_filters)188void LensView::SetupViews(nux::Area* show_filters)
179{189{
180 dash::Style& style = dash::Style::Instance();190 dash::Style& style = dash::Style::Instance();
@@ -231,12 +241,39 @@
231 OnCategoryAdded(categories->RowAtIndex(i));241 OnCategoryAdded(categories->RowAtIndex(i));
232}242}
233243
244void LensView::OnModelDestroyed(LensView* self, DeeModel* was_here)
245{
246 for (auto group : self->categories_)
247 {
248 auto grid = static_cast<ResultViewGrid*>(group->GetChildView());
249 self->counts_[group] -= grid->GetResultList().size();
250 grid->ClearResults();
251 self->UpdateCounts(group);
252 }
253}
254
234void LensView::SetupResults()255void LensView::SetupResults()
235{256{
236 Results::Ptr results = lens_->results;257 Results::Ptr results = lens_->results;
237 results->result_added.connect(sigc::mem_fun(this, &LensView::OnResultAdded));258 results->result_added.connect(sigc::mem_fun(this, &LensView::OnResultAdded));
238 results->result_removed.connect(sigc::mem_fun(this, &LensView::OnResultRemoved));259 results->result_removed.connect(sigc::mem_fun(this, &LensView::OnResultRemoved));
239260
261 results->model.changed.connect([this] (glib::Object<DeeModel> model)
262 {
263 if (DEE_IS_MODEL(results_model_))
264 {
265 g_object_weak_unref(G_OBJECT(results_model_), (GWeakNotify)LensView::OnModelDestroyed, this);
266 }
267
268 results_model_ = nullptr;
269
270 if (model.IsType(DEE_TYPE_MODEL))
271 {
272 results_model_ = model;
273 g_object_weak_ref(glib::object_cast<GObject>(model), (GWeakNotify)LensView::OnModelDestroyed, this);
274 }
275 });
276
240 for (unsigned int i = 0; i < results->count(); ++i)277 for (unsigned int i = 0; i < results->count(); ++i)
241 OnResultAdded(results->RowAtIndex(i));278 OnResultAdded(results->RowAtIndex(i));
242}279}
@@ -285,7 +322,7 @@
285 grid->SetModelRenderer(new ResultRendererHorizontalTile(NUX_TRACKER_LOCATION));322 grid->SetModelRenderer(new ResultRendererHorizontalTile(NUX_TRACKER_LOCATION));
286 grid->horizontal_spacing = CARD_VIEW_GAP_HORIZ;323 grid->horizontal_spacing = CARD_VIEW_GAP_HORIZ;
287 grid->vertical_spacing = CARD_VIEW_GAP_VERT;324 grid->vertical_spacing = CARD_VIEW_GAP_VERT;
288 } 325 }
289 else326 else
290 grid->SetModelRenderer(new ResultRendererTile(NUX_TRACKER_LOCATION));327 grid->SetModelRenderer(new ResultRendererTile(NUX_TRACKER_LOCATION));
291328
@@ -305,8 +342,7 @@
305 PlacesGroup* group = categories_.at(result.category_index);342 PlacesGroup* group = categories_.at(result.category_index);
306 ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView());343 ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView());
307344
308 std::string uri = result.uri;345 LOG_TRACE(logger) << "Result added: " << result.uri();
309 LOG_TRACE(logger) << "Result added: " << uri;
310346
311 grid->AddResult(const_cast<Result&>(result));347 grid->AddResult(const_cast<Result&>(result));
312 counts_[group]++;348 counts_[group]++;
@@ -329,8 +365,7 @@
329 PlacesGroup* group = categories_.at(result.category_index);365 PlacesGroup* group = categories_.at(result.category_index);
330 ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView());366 ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView());
331367
332 std::string uri = result.uri;368 LOG_TRACE(logger) << "Result removed: " << result.uri();
333 LOG_TRACE(logger) << "Result removed: " << uri;
334369
335 grid->RemoveResult(const_cast<Result&>(result));370 grid->RemoveResult(const_cast<Result&>(result));
336 counts_[group]--;371 counts_[group]--;
337372
=== modified file 'dash/LensView.h'
--- dash/LensView.h 2012-06-18 02:57:23 +0000
+++ dash/LensView.h 2012-08-10 12:37:21 +0000
@@ -52,6 +52,7 @@
52public:52public:
53 LensView();53 LensView();
54 LensView(Lens::Ptr lens, nux::Area* show_filters);54 LensView(Lens::Ptr lens, nux::Area* show_filters);
55 ~LensView();
5556
56 CategoryGroups& categories() { return categories_; }57 CategoryGroups& categories() { return categories_; }
57 FilterBar* filter_bar() const { return filter_bar_; }58 FilterBar* filter_bar() const { return filter_bar_; }
@@ -101,6 +102,8 @@
101102
102 std::string get_search_string() const;103 std::string get_search_string() const;
103104
105 static void OnModelDestroyed(LensView* self, DeeModel* was_here);
106
104private:107private:
105 Lens::Ptr lens_;108 Lens::Ptr lens_;
106 CategoryGroups categories_;109 CategoryGroups categories_;
@@ -116,6 +119,7 @@
116 nux::VLayout* fscroll_layout_;119 nux::VLayout* fscroll_layout_;
117 FilterBar* filter_bar_;120 FilterBar* filter_bar_;
118 nux::StaticCairoText* no_results_;121 nux::StaticCairoText* no_results_;
122 DeeModel* results_model_;
119123
120 UBusManager ubus_manager_;124 UBusManager ubus_manager_;
121 glib::Source::UniquePtr fix_rendering_idle_;125 glib::Source::UniquePtr fix_rendering_idle_;
122126
=== modified file 'dash/ResultRendererTile.cpp'
--- dash/ResultRendererTile.cpp 2012-06-18 02:57:23 +0000
+++ dash/ResultRendererTile.cpp 2012-08-10 12:37:21 +0000
@@ -21,14 +21,10 @@
21 */21 */
2222
2323
24#include <sstream> // for ostringstream
25#include "ResultRendererTile.h"24#include "ResultRendererTile.h"
2625
27#include <boost/algorithm/string.hpp>
28
29#include <pango/pango.h>26#include <pango/pango.h>
30#include <pango/pangocairo.h>27#include <pango/pangocairo.h>
31#include <gdk/gdk.h>
32#include <gtk/gtk.h>28#include <gtk/gtk.h>
3329
34#include <NuxCore/Logger.h>30#include <NuxCore/Logger.h>
@@ -40,19 +36,18 @@
40#include "unity-shared/IconTexture.h"36#include "unity-shared/IconTexture.h"
41#include "unity-shared/TextureCache.h"37#include "unity-shared/TextureCache.h"
4238
43
44namespace
45{
46 bool neko;
47}
48
49namespace unity39namespace unity
50{40{
51namespace41namespace
52{42{
53nux::logging::Logger logger("unity.dash.results");43nux::logging::Logger logger("unity.dash.results");
44const std::string DEFAULT_GICON = ". GThemedIcon text-x-preview";
5445
55const int FONT_SIZE = 10;46const int FONT_SIZE = 10;
47bool neko = false;
48const std::string neko_env = {0x55, 0x4e, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x45, 0x4b, 0x4f};
49const std::string neko_src = {0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6c, 0x61, 0x63,
50 0x65, 0x6b, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x2e, 0x63, 0x6f, 0x6d};
56}51}
5752
58namespace dash53namespace dash
@@ -69,11 +64,7 @@
69 dash::Style& style = dash::Style::Instance();64 dash::Style& style = dash::Style::Instance();
70 width = style.GetTileWidth();65 width = style.GetTileWidth();
71 height = style.GetTileHeight();66 height = style.GetTileHeight();
7267 neko = g_getenv(neko_env.c_str());
73 gsize tmp;
74 gchar* tmp1 = (gchar*)g_base64_decode("VU5JVFlfTkVLTw==", &tmp);
75 neko = (g_getenv(tmp1));
76 g_free (tmp1);
7768
78 // pre-load the highlight texture69 // pre-load the highlight texture
79 // try and get a texture from the texture cache70 // try and get a texture from the texture cache
@@ -84,10 +75,6 @@
84 sigc::mem_fun(this, &ResultRendererTile::DrawHighlight));75 sigc::mem_fun(this, &ResultRendererTile::DrawHighlight));
85}76}
8677
87ResultRendererTile::~ResultRendererTile()
88{
89}
90
91void ResultRendererTile::Render(nux::GraphicsEngine& GfxContext,78void ResultRendererTile::Render(nux::GraphicsEngine& GfxContext,
92 Result& row,79 Result& row,
93 ResultRendererState state,80 ResultRendererState state,
@@ -95,7 +82,8 @@
95 int x_offset, int y_offset)82 int x_offset, int y_offset)
96{83{
97 TextureContainer* container = row.renderer<TextureContainer*>();84 TextureContainer* container = row.renderer<TextureContainer*>();
98 if (container == nullptr)85
86 if (!container)
99 return;87 return;
10088
101 dash::Style& style = dash::Style::Instance();89 dash::Style& style = dash::Style::Instance();
@@ -105,7 +93,7 @@
105 nux::TexCoordXForm texxform;93 nux::TexCoordXForm texxform;
10694
107 int icon_width, icon_height;95 int icon_width, icon_height;
108 if (container->icon == nullptr)96 if (!container->icon)
109 {97 {
110 icon_width = icon_height = tile_icon_size;98 icon_width = icon_height = tile_icon_size;
111 }99 }
@@ -230,7 +218,7 @@
230218
231void ResultRendererTile::Preload(Result& row)219void ResultRendererTile::Preload(Result& row)
232{220{
233 if (row.renderer<TextureContainer*>() == nullptr)221 if (!row.renderer<TextureContainer*>())
234 {222 {
235 row.set_renderer(new TextureContainer());223 row.set_renderer(new TextureContainer());
236 LoadIcon(row);224 LoadIcon(row);
@@ -240,52 +228,53 @@
240228
241void ResultRendererTile::Unload(Result& row)229void ResultRendererTile::Unload(Result& row)
242{230{
243 TextureContainer *container = row.renderer<TextureContainer*>();231 delete row.renderer<TextureContainer*>();
244 delete container;
245 row.set_renderer<TextureContainer*>(nullptr);232 row.set_renderer<TextureContainer*>(nullptr);
246}233}
247234
248void ResultRendererTile::LoadIcon(Result& row)235void ResultRendererTile::LoadIcon(Result& row)
249{236{
250 Style& style = Style::Instance();237 auto container = row.renderer<TextureContainer*>();
251 std::string const& icon_hint = row.icon_hint;238
252#define DEFAULT_GICON ". GThemedIcon text-x-preview"239 if (!container)
253 std::string icon_name;240 {
254 if (G_UNLIKELY(neko))241 LOG_ERROR(logger) << "No valid container for Result " << row.name() << " with URI "
255 {242 << row.uri();
256 int tmp1 = style.GetTileIconSize() + (rand() % 16) - 8;243 return;
257 gsize tmp3;244 }
258 gchar* tmp2 = (gchar*)g_base64_decode("aHR0cDovL3BsYWNla2l0dGVuLmNvbS8laS8laS8=", &tmp3);245
259 gchar* tmp4 = g_strdup_printf(tmp2, tmp1, tmp1);246 int icon_size = Style::Instance().GetTileIconSize();
260 icon_name = tmp4;247 std::string icon_name = row.icon_hint();
261 g_free(tmp4);248
262 g_free(tmp2);249 if (neko)
263 }250 {
264 else251 auto tmp = std::to_string(icon_size + (rand() % 16) - 8);
265 {252 icon_name = neko_src + '/' + tmp + '/' + tmp;
266 icon_name = !icon_hint.empty() ? icon_hint : DEFAULT_GICON;253 }
267 }254 else if (icon_name.empty())
268255 {
269 GIcon* icon = g_icon_new_for_string(icon_name.c_str(), NULL);256 icon_name = DEFAULT_GICON;
270 TextureContainer* container = row.renderer<TextureContainer*>();257 }
271258
272 IconLoader::IconLoaderCallback slot = sigc::bind(sigc::mem_fun(this, &ResultRendererTile::IconLoaded), icon_hint, row);259 auto slot = sigc::bind(sigc::mem_fun(this, &ResultRendererTile::IconLoaded), row);
273260
274 if (g_strrstr(icon_name.c_str(), "://"))261 if (icon_name.find("://") != std::string::npos)
275 {262 {
276 container->slot_handle = IconLoader::GetDefault().LoadFromURI(icon_name, style.GetTileIconSize(), slot);263 container->slot_handle = IconLoader::GetDefault().LoadFromURI(icon_name, icon_size, slot);
277 }264 }
278 else if (G_IS_ICON(icon))265 else
279 {266 {
280 container->slot_handle = IconLoader::GetDefault().LoadFromGIconString(icon_name, style.GetTileIconSize(), slot);267 glib::Object<GIcon> icon(g_icon_new_for_string(icon_name.c_str(), nullptr));
281 }268
282 else269 if (icon.IsType(G_TYPE_ICON))
283 {270 {
284 container->slot_handle = IconLoader::GetDefault().LoadFromIconName(icon_name, style.GetTileIconSize(), slot);271 container->slot_handle = IconLoader::GetDefault().LoadFromGIconString(icon_name, icon_size, slot);
285 }272 }
286273 else
287 if (icon != NULL)274 {
288 g_object_unref(icon);275 container->slot_handle = IconLoader::GetDefault().LoadFromIconName(icon_name, icon_size, slot);
276 }
277 }
289}278}
290279
291nux::BaseTexture* ResultRendererTile::CreateTextureCallback(std::string const& texid,280nux::BaseTexture* ResultRendererTile::CreateTextureCallback(std::string const& texid,
@@ -405,20 +394,20 @@
405void ResultRendererTile::IconLoaded(std::string const& texid,394void ResultRendererTile::IconLoaded(std::string const& texid,
406 unsigned size,395 unsigned size,
407 glib::Object<GdkPixbuf> const& pixbuf,396 glib::Object<GdkPixbuf> const& pixbuf,
408 std::string icon_name,
409 Result& row)397 Result& row)
410{398{
411 TextureContainer *container = row.renderer<TextureContainer*>();399 TextureContainer *container = row.renderer<TextureContainer*>();
412 Style& style = Style::Instance();400 int icon_size = Style::Instance().GetTileIconSize();
413401
414 if (pixbuf && container)402 if (pixbuf && container)
415 {403 {
404 std::string const& icon_name = row.icon_hint();
416 TextureCache& cache = TextureCache::GetDefault();405 TextureCache& cache = TextureCache::GetDefault();
417 BaseTexturePtr texture(cache.FindTexture(icon_name, style.GetTileIconSize(), style.GetTileIconSize(),406 BaseTexturePtr texture(cache.FindTexture(icon_name, icon_size, icon_size,
418 sigc::bind(sigc::mem_fun(this, &ResultRendererTile::CreateTextureCallback), pixbuf)));407 sigc::bind(sigc::mem_fun(this, &ResultRendererTile::CreateTextureCallback), pixbuf)));
419408
420 std::string blur_texid = icon_name + "_blurred";409 std::string blur_texid = icon_name + "_blurred";
421 BaseTexturePtr texture_blurred(cache.FindTexture(blur_texid, style.GetTileIconSize(), style.GetTileIconSize(),410 BaseTexturePtr texture_blurred(cache.FindTexture(blur_texid, icon_size, icon_size,
422 sigc::bind(sigc::mem_fun(this, &ResultRendererTile::CreateBlurredTextureCallback), pixbuf)));411 sigc::bind(sigc::mem_fun(this, &ResultRendererTile::CreateBlurredTextureCallback), pixbuf)));
423412
424 BaseTexturePtr texture_prelight(cache.FindTexture("resultview_prelight", texture->GetWidth() + highlight_padding*2, texture->GetHeight() + highlight_padding*2, sigc::mem_fun(this, &ResultRendererTile::DrawHighlight)));413 BaseTexturePtr texture_prelight(cache.FindTexture("resultview_prelight", texture->GetWidth() + highlight_padding*2, texture->GetHeight() + highlight_padding*2, sigc::mem_fun(this, &ResultRendererTile::DrawHighlight)));
@@ -426,17 +415,15 @@
426 container->icon = texture;415 container->icon = texture;
427 container->blurred_icon = texture_blurred;416 container->blurred_icon = texture_blurred;
428 container->prelight = texture_prelight;417 container->prelight = texture_prelight;
418 container->slot_handle = 0;
429419
430 NeedsRedraw.emit();420 NeedsRedraw.emit();
431
432 if (container)
433 container->slot_handle = 0;
434 }421 }
435 else if (container)422 else if (container)
436 {423 {
437 // we need to load a missing icon424 // we need to load a missing icon
438 IconLoader::IconLoaderCallback slot = sigc::bind(sigc::mem_fun(this, &ResultRendererTile::IconLoaded), icon_name, row);425 IconLoader::IconLoaderCallback slot = sigc::bind(sigc::mem_fun(this, &ResultRendererTile::IconLoaded), row);
439 container->slot_handle = IconLoader::GetDefault().LoadFromGIconString(". GThemedIcon text-x-preview", style.GetTileIconSize(), slot);426 container->slot_handle = IconLoader::GetDefault().LoadFromGIconString(DEFAULT_GICON, icon_size, slot);
440 }427 }
441428
442}429}
@@ -444,29 +431,31 @@
444431
445void ResultRendererTile::LoadText(Result& row)432void ResultRendererTile::LoadText(Result& row)
446{433{
434 TextureContainer *container = row.renderer<TextureContainer*>();
435
436 if (!container)
437 return;
438
439 GdkScreen* screen = gdk_screen_get_default();
447 Style& style = Style::Instance();440 Style& style = Style::Instance();
448 nux::CairoGraphics _cairoGraphics(CAIRO_FORMAT_ARGB32,441 nux::CairoGraphics _cairoGraphics(CAIRO_FORMAT_ARGB32,
449 style.GetTileWidth() - (padding * 2),442 style.GetTileWidth() - (padding * 2),
450 style.GetTileHeight() - style.GetTileIconSize() - spacing);443 style.GetTileHeight() - style.GetTileIconSize() - spacing);
451444
445 glib::String font;
446 g_object_get(gtk_settings_get_default(), "gtk-font-name", &font, nullptr);
447
448 int dpi = -1;
449 g_object_get(gtk_settings_get_default(), "gtk-xft-dpi", &dpi, nullptr);
450
452 cairo_t* cr = _cairoGraphics.GetContext();451 cairo_t* cr = _cairoGraphics.GetContext();
453
454 PangoLayout* layout = NULL;
455 PangoFontDescription* desc = NULL;
456 PangoContext* pango_context = NULL;
457 GdkScreen* screen = gdk_screen_get_default(); // not ref'ed
458 glib::String font;
459 int dpi = -1;
460
461 g_object_get(gtk_settings_get_default(), "gtk-font-name", &font, NULL);
462 g_object_get(gtk_settings_get_default(), "gtk-xft-dpi", &dpi, NULL);
463
464 cairo_set_font_options(cr, gdk_screen_get_font_options(screen));452 cairo_set_font_options(cr, gdk_screen_get_font_options(screen));
465 layout = pango_cairo_create_layout(cr);453 glib::Object<PangoLayout> layout(pango_cairo_create_layout(cr));
466 desc = pango_font_description_from_string(font.Value());454 std::shared_ptr<PangoFontDescription> desc(pango_font_description_from_string(font),
467 pango_font_description_set_size (desc, FONT_SIZE * PANGO_SCALE);455 pango_font_description_free);
456 pango_font_description_set_size (desc.get(), FONT_SIZE * PANGO_SCALE);
468457
469 pango_layout_set_font_description(layout, desc);458 pango_layout_set_font_description(layout, desc.get());
470 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);459 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
471460
472 pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);461 pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
@@ -474,17 +463,14 @@
474 pango_layout_set_width(layout, (style.GetTileWidth() - (padding * 2))* PANGO_SCALE);463 pango_layout_set_width(layout, (style.GetTileWidth() - (padding * 2))* PANGO_SCALE);
475 pango_layout_set_height(layout, -2);464 pango_layout_set_height(layout, -2);
476465
477 char *escaped_text = g_markup_escape_text(row.name().c_str() , -1);466 glib::String escaped_text(g_markup_escape_text(row.name().c_str(), -1));
478
479 pango_layout_set_markup(layout, escaped_text, -1);467 pango_layout_set_markup(layout, escaped_text, -1);
480468
481 g_free (escaped_text);469 PangoContext* pango_context = pango_layout_get_context(layout); // is not ref'ed
482
483 pango_context = pango_layout_get_context(layout); // is not ref'ed
484 pango_cairo_context_set_font_options(pango_context,470 pango_cairo_context_set_font_options(pango_context,
485 gdk_screen_get_font_options(screen));471 gdk_screen_get_font_options(screen));
486 pango_cairo_context_set_resolution(pango_context,472 pango_cairo_context_set_resolution(pango_context,
487 dpi == -1 ? 96.0f : dpi/(float) PANGO_SCALE);473 dpi == -1 ? 96.0f : dpi/static_cast<float>(PANGO_SCALE));
488 pango_layout_context_changed(layout);474 pango_layout_context_changed(layout);
489475
490 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);476 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
@@ -497,13 +483,9 @@
497 pango_cairo_show_layout(cr, layout);483 pango_cairo_show_layout(cr, layout);
498484
499 // clean up485 // clean up
500 pango_font_description_free(desc);
501 g_object_unref(layout);
502 cairo_destroy(cr);486 cairo_destroy(cr);
503487
504 TextureContainer *container = row.renderer<TextureContainer*>();488 container->text = texture_ptr_from_cairo_graphics(_cairoGraphics);
505 if (container)
506 container->text = texture_ptr_from_cairo_graphics(_cairoGraphics);
507}489}
508490
509491
510492
=== modified file 'dash/ResultRendererTile.h'
--- dash/ResultRendererTile.h 2012-07-04 02:37:23 +0000
+++ dash/ResultRendererTile.h 2012-08-10 12:37:21 +0000
@@ -67,7 +67,6 @@
67 NUX_DECLARE_OBJECT_TYPE(ResultRendererTile, ResultRenderer);67 NUX_DECLARE_OBJECT_TYPE(ResultRendererTile, ResultRenderer);
6868
69 ResultRendererTile(NUX_FILE_LINE_PROTO);69 ResultRendererTile(NUX_FILE_LINE_PROTO);
70 ~ResultRendererTile();
7170
72 virtual void Render(nux::GraphicsEngine& GfxContext,71 virtual void Render(nux::GraphicsEngine& GfxContext,
73 Result& row,72 Result& row,
@@ -93,7 +92,7 @@
93 //icon loading callbacks92 //icon loading callbacks
94 void IconLoaded(std::string const& texid, unsigned size,93 void IconLoaded(std::string const& texid, unsigned size,
95 glib::Object<GdkPixbuf> const& pixbuf,94 glib::Object<GdkPixbuf> const& pixbuf,
96 std::string icon_name, Result& row);95 Result& row);
97 nux::BaseTexture* CreateTextureCallback(std::string const& texid,96 nux::BaseTexture* CreateTextureCallback(std::string const& texid,
98 int width, int height,97 int width, int height,
99 glib::Object<GdkPixbuf> const& pixbuf);98 glib::Object<GdkPixbuf> const& pixbuf);
10099
=== modified file 'dash/ResultView.cpp'
--- dash/ResultView.cpp 2012-07-30 16:22:53 +0000
+++ dash/ResultView.cpp 2012-08-10 12:37:21 +0000
@@ -24,9 +24,7 @@
24#include "ResultView.h"24#include "ResultView.h"
25#include "unity-shared/IntrospectableWrappers.h"25#include "unity-shared/IntrospectableWrappers.h"
26#include <UnityCore/Variant.h>26#include <UnityCore/Variant.h>
27#include <Nux/HLayout.h>27#include <Nux/Layout.h>
28#include <Nux/VLayout.h>
29#include <Nux/Button.h>
30#include <NuxCore/Logger.h>28#include <NuxCore/Logger.h>
3129
32namespace unity30namespace unity
@@ -43,12 +41,10 @@
43ResultView::ResultView(NUX_FILE_LINE_DECL)41ResultView::ResultView(NUX_FILE_LINE_DECL)
44 : View(NUX_FILE_LINE_PARAM)42 : View(NUX_FILE_LINE_PARAM)
45 , expanded(true)43 , expanded(true)
46 , renderer_(NULL)
47{44{
48 expanded.changed.connect([&](bool value)45 expanded.changed.connect([&](bool value)
49 {46 {
50 QueueRelayout();47 QueueRelayout();
51 NeedRedraw();
52 });48 });
53}49}
5450
@@ -60,28 +56,17 @@
60 {56 {
61 renderer_->Unload(result);57 renderer_->Unload(result);
62 }58 }
63
64 renderer_->UnReference();
65}59}
6660
67void ResultView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)61void ResultView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
68{62{}
69
70}
7163
72void ResultView::SetModelRenderer(ResultRenderer* renderer)64void ResultView::SetModelRenderer(ResultRenderer* renderer)
73{65{
74 if (renderer_ != NULL)
75 renderer_->UnReference();
76
77 renderer_ = renderer;66 renderer_ = renderer;
78 renderer->NeedsRedraw.connect([&]()67 renderer_->NeedsRedraw.connect(sigc::mem_fun(this, &ResultView::QueueDraw));
79 {
80 NeedRedraw();
81 });
82 renderer_->SinkReference();
8368
84 NeedRedraw();69 QueueDraw();
85}70}
8671
87void ResultView::AddResult(Result& result)72void ResultView::AddResult(Result& result)
@@ -89,40 +74,44 @@
89 results_.push_back(result);74 results_.push_back(result);
90 renderer_->Preload(result);75 renderer_->Preload(result);
9176
92 NeedRedraw();77 QueueDraw();
93}78}
9479
95void ResultView::RemoveResult(Result& result)80void ResultView::RemoveResult(Result& result)
96{81{
97 ResultList::iterator it;82 std::string const& uri = result.uri;
98 std::string uri = result.uri;
9983
100 for (it = results_.begin(); it != results_.end(); ++it)84 for (auto it = results_.begin(); it != results_.end(); ++it)
101 {85 {
102 if (result.uri == (*it).uri)86 if (it->uri == uri)
103 {87 {
104 results_.erase(it);88 results_.erase(it);
105 break;89 break;
106 }90 }
107 }91 }
92
108 renderer_->Unload(result);93 renderer_->Unload(result);
109}94}
11095
111ResultView::ResultList ResultView::GetResultList()96void ResultView::ClearResults()
97{
98 for (Result& result : results_)
99 {
100 renderer_->Unload(result);
101 }
102
103 results_.clear();
104}
105
106ResultView::ResultList const& ResultView::GetResultList() const
112{107{
113 return results_;108 return results_;
114}109}
115110
116111
117long ResultView::ComputeContentSize()
118{
119 return View::ComputeContentSize();
120}
121
122
123void ResultView::DrawContent(nux::GraphicsEngine& GfxContent, bool force_draw)112void ResultView::DrawContent(nux::GraphicsEngine& GfxContent, bool force_draw)
124{113{
125 nux::Geometry base = GetGeometry();114 nux::Geometry const& base = GetGeometry();
126 GfxContent.PushClippingRectangle(base);115 GfxContent.PushClippingRectangle(base);
127116
128 if (GetCompositionLayout())117 if (GetCompositionLayout())
129118
=== modified file 'dash/ResultView.h'
--- dash/ResultView.h 2012-07-04 02:37:23 +0000
+++ dash/ResultView.h 2012-08-10 12:37:21 +0000
@@ -25,9 +25,6 @@
2525
26#include <Nux/Nux.h>26#include <Nux/Nux.h>
27#include <Nux/View.h>27#include <Nux/View.h>
28#include <dee.h>
29
30#include <UnityCore/GLibSignal.h>
31#include <UnityCore/Results.h>28#include <UnityCore/Results.h>
3229
33#include "unity-shared/Introspectable.h"30#include "unity-shared/Introspectable.h"
@@ -51,8 +48,9 @@
5148
52 void AddResult(Result& result);49 void AddResult(Result& result);
53 void RemoveResult(Result& result);50 void RemoveResult(Result& result);
51 void ClearResults();
5452
55 ResultList GetResultList ();53 ResultList const& GetResultList() const;
5654
57 nux::Property<bool> expanded;55 nux::Property<bool> expanded;
58 nux::Property<int> results_per_row;56 nux::Property<int> results_per_row;
@@ -66,10 +64,9 @@
66protected:64protected:
67 virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);65 virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
68 virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);66 virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
69 virtual long ComputeContentSize();
7067
71 // properties68 // properties
72 ResultRenderer* renderer_;69 nux::ObjectPtr<ResultRenderer> renderer_;
73 ResultList results_;70 ResultList results_;
74 IntrospectableList introspectable_children_;71 IntrospectableList introspectable_children_;
7572