[gthumb] fixed possible crash when switch from the image viewer to another viewer
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] fixed possible crash when switch from the image viewer to another viewer
- Date: Mon, 3 Apr 2017 17:34:35 +0000 (UTC)
commit 43bddd1c6fdfa61b21cd3a43a882c4f8c9dca4dd
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon Apr 3 19:21:10 2017 +0200
fixed possible crash when switch from the image viewer to another viewer
check if the viewer is still available after a callback
extensions/image_viewer/gth-image-viewer-page.c | 102 ++++++++++++++------
gthumb/gth-image-dragger.c | 16 ++-
gthumb/gth-image-overview.c | 117 ++++++++++++++++-------
3 files changed, 162 insertions(+), 73 deletions(-)
---
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 8d418d6..a8c7af1 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -204,6 +204,44 @@ _gth_image_preloader_get_requested_size_for_current_image (GthImageViewerPage *s
static void
+_gth_image_viewer_page_load_with_preloader (GthImageViewerPage *self,
+ GthFileData *file_data,
+ int requested_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ if (self->priv->apply_icc_profile)
+ gth_image_preloader_set_out_profile (self->priv->preloader, gth_browser_get_screen_profile
(self->priv->browser));
+ else
+ gth_image_preloader_set_out_profile (self->priv->preloader, NULL);
+
+ g_object_ref (self);
+ gth_image_preloader_load (self->priv->preloader,
+ file_data,
+ requested_size,
+ cancellable,
+ callback,
+ user_data,
+ N_FORWARD_PRELOADERS + N_BACKWARD_PRELOADERS,
+ self->priv->next_file_data[0],
+ self->priv->next_file_data[1],
+ self->priv->prev_file_data[0],
+ self->priv->prev_file_data[1]);
+}
+
+
+static gboolean
+_gth_image_viewer_page_load_with_preloader_finish (GthImageViewerPage *self)
+{
+ gboolean active = self->priv->active;
+ g_object_unref (self);
+
+ return active;
+}
+
+
+static void
different_quality_ready_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
@@ -220,6 +258,9 @@ different_quality_ready_cb (GObject *source_object,
int w1, h1, w2, h2;
gboolean got_better_quality;
+ if (! _gth_image_viewer_page_load_with_preloader_finish (self))
+ return;
+
if (! gth_image_preloader_load_finish (GTH_IMAGE_PRELOADER (source_object),
result,
&requested,
@@ -291,33 +332,6 @@ _g_mime_type_can_load_different_quality (const char *mime_type)
}
-static void
-_gth_image_viewer_page_load_with_preloader (GthImageViewerPage *self,
- GthFileData *file_data,
- int requested_size,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- if (self->priv->apply_icc_profile)
- gth_image_preloader_set_out_profile (self->priv->preloader, gth_browser_get_screen_profile
(self->priv->browser));
- else
- gth_image_preloader_set_out_profile (self->priv->preloader, NULL);
-
- gth_image_preloader_load (self->priv->preloader,
- file_data,
- requested_size,
- cancellable,
- callback,
- user_data,
- N_FORWARD_PRELOADERS + N_BACKWARD_PRELOADERS,
- self->priv->next_file_data[0],
- self->priv->next_file_data[1],
- self->priv->prev_file_data[0],
- self->priv->prev_file_data[1]);
-}
-
-
static gboolean
update_quality_cb (gpointer user_data)
{
@@ -328,6 +342,12 @@ update_quality_cb (gpointer user_data)
self->priv->update_quality_id = 0;
}
+ if (! self->priv->active)
+ return FALSE;
+
+ if (self->priv->viewer == NULL)
+ return FALSE;
+
if (self->priv->loading_image)
return FALSE;
@@ -654,7 +674,7 @@ viewer_realize_cb (GtkWidget *widget,
GthImageViewerPage *self = user_data;
GtkClipboard *clipboard;
- clipboard = gtk_widget_get_clipboard (self->priv->viewer, GDK_SELECTION_CLIPBOARD);
+ clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
g_signal_connect (clipboard,
"owner_change",
G_CALLBACK (clipboard_owner_change_cb),
@@ -669,7 +689,7 @@ viewer_unrealize_cb (GtkWidget *widget,
GthImageViewerPage *self = user_data;
GtkClipboard *clipboard;
- clipboard = gtk_widget_get_clipboard (self->priv->viewer, GDK_SELECTION_CLIPBOARD);
+ clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
g_signal_handlers_disconnect_by_func (clipboard,
G_CALLBACK (clipboard_owner_change_cb),
self);
@@ -744,6 +764,9 @@ pref_zoom_quality_changed (GSettings *settings,
{
GthImageViewerPage *self = user_data;
+ if (! self->priv->active || (self->priv->viewer == NULL))
+ return;
+
gth_image_viewer_set_zoom_quality (GTH_IMAGE_VIEWER (self->priv->viewer),
g_settings_get_enum (self->priv->settings,
PREF_IMAGE_VIEWER_ZOOM_QUALITY));
gtk_widget_queue_draw (self->priv->viewer);
@@ -757,6 +780,9 @@ pref_zoom_change_changed (GSettings *settings,
{
GthImageViewerPage *self = user_data;
+ if (! self->priv->active || (self->priv->viewer == NULL))
+ return;
+
gth_image_viewer_set_zoom_change (GTH_IMAGE_VIEWER (self->priv->viewer),
g_settings_get_enum (self->priv->settings,
PREF_IMAGE_VIEWER_ZOOM_CHANGE));
gtk_widget_queue_draw (self->priv->viewer);
@@ -770,6 +796,9 @@ pref_reset_scrollbars_changed (GSettings *settings,
{
GthImageViewerPage *self = user_data;
+ if (! self->priv->active || (self->priv->viewer == NULL))
+ return;
+
gth_image_viewer_set_reset_scrollbars (GTH_IMAGE_VIEWER (self->priv->viewer),
g_settings_get_boolean (self->priv->settings,
PREF_IMAGE_VIEWER_RESET_SCROLLBARS));
}
@@ -1000,6 +1029,7 @@ gth_image_viewer_page_real_activate (GthViewerPage *base,
self->priv->preloader = gth_browser_get_image_preloader (browser);
self->priv->viewer = gth_image_viewer_new ();
+ g_object_add_weak_pointer (G_OBJECT (self->priv->viewer), &self->priv->viewer);
gtk_widget_add_events (self->priv->viewer, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
gth_image_viewer_page_reset_viewer_tool (self);
gtk_widget_show (self->priv->viewer);
@@ -1160,6 +1190,8 @@ preloader_load_ready_cb (GObject *source_object,
GError *error = NULL;
self->priv->loading_image = FALSE;
+ if (! _gth_image_viewer_page_load_with_preloader_finish (self))
+ return;
if (! gth_image_preloader_load_finish (GTH_IMAGE_PRELOADER (source_object),
result,
@@ -2050,6 +2082,7 @@ get_original_data_free (OriginalImageData *data)
if (data == NULL)
return;
+ _g_object_unref (data->viewer_page);
_g_object_unref (data->cancellable);
_g_object_unref (data->result);
g_free (data);
@@ -2062,8 +2095,13 @@ original_image_ready_cb (GObject *source_object,
gpointer user_data)
{
OriginalImageData *data = user_data;
- GthImage *image = NULL;
- GError *error = NULL;
+ GthImage *image = NULL;
+ GError *error = NULL;
+
+ if (! _gth_image_viewer_page_load_with_preloader_finish (data->viewer_page)) {
+ get_original_data_free (data);
+ return;
+ }
if (! gth_image_preloader_load_finish (GTH_IMAGE_PRELOADER (source_object),
result,
@@ -2095,7 +2133,7 @@ gth_image_viewer_page_get_original (GthImageViewerPage *self,
OriginalImageData *data;
data = get_original_data_new ();
- data->viewer_page = self;
+ data->viewer_page = g_object_ref (self);
data->result = g_simple_async_result_new (G_OBJECT (self),
ready_callback,
user_data,
diff --git a/gthumb/gth-image-dragger.c b/gthumb/gth-image-dragger.c
index f3a4168..d6b14d8 100644
--- a/gthumb/gth-image-dragger.c
+++ b/gthumb/gth-image-dragger.c
@@ -167,7 +167,9 @@ gth_image_dragger_set_viewer (GthImageViewerTool *base,
GthImageViewer *image_viewer)
{
GthImageDragger *self = GTH_IMAGE_DRAGGER (base);
+
self->priv->viewer = image_viewer;
+ g_object_add_weak_pointer (G_OBJECT (image_viewer), &self->priv->viewer);
if (self->priv->show_frame)
gth_image_viewer_show_frame (self->priv->viewer, FRAME_BORDER);
}
@@ -181,6 +183,7 @@ gth_image_dragger_unset_viewer (GthImageViewerTool *base,
if ((self->priv->viewer != NULL) && self->priv->show_frame)
gth_image_viewer_hide_frame (self->priv->viewer);
+ g_object_remove_weak_pointer (G_OBJECT (image_viewer), &self->priv->viewer);
self->priv->viewer = NULL;
}
@@ -405,6 +408,7 @@ scale_data_free (ScaleData *scale_data)
return;
cairo_surface_destroy (scale_data->image);
cairo_surface_destroy (scale_data->scaled);
+ g_object_unref (scale_data->dragger);
g_free (scale_data);
}
@@ -435,10 +439,12 @@ _gth_image_dragger_scale_after (GthAsyncTask *task,
if (error == NULL) {
GthImageDragger *dragger = scale_data->dragger;
- _cairo_clear_surface (&dragger->priv->scaled);
- dragger->priv->scaled = cairo_surface_reference (scale_data->scaled);
- if (dragger->priv->viewer != NULL)
- gtk_widget_queue_draw (GTK_WIDGET (dragger->priv->viewer));
+ if ((scale_data->scaled != NULL) && (dragger->priv->viewer != NULL)) {
+ _cairo_clear_surface (&dragger->priv->scaled);
+ dragger->priv->scaled = cairo_surface_reference (scale_data->scaled);
+ if (dragger->priv->viewer != NULL)
+ gtk_widget_queue_draw (GTK_WIDGET (dragger->priv->viewer));
+ }
if (GTH_TASK (task) == dragger->priv->scale_task)
dragger->priv->scale_task = NULL;
@@ -461,7 +467,7 @@ _gth_image_dragger_create_scaled_high_quality (GthImageDragger *self,
gth_task_cancel (self->priv->scale_task);
scale_data = g_new0 (ScaleData, 1);
- scale_data->dragger = self;
+ scale_data->dragger = g_object_ref (self);
scale_data->image = cairo_surface_reference (image);
scale_data->new_width = new_width;
scale_data->new_height = new_height;
diff --git a/gthumb/gth-image-overview.c b/gthumb/gth-image-overview.c
index 5803002..b91fc6b 100644
--- a/gthumb/gth-image-overview.c
+++ b/gthumb/gth-image-overview.c
@@ -23,6 +23,7 @@
#include <math.h>
#include <gdk/gdkkeysyms.h>
#include "cairo-scale.h"
+#include "cairo-utils.h"
#include "gth-image-overview.h"
#include "gth-image-utils.h"
#include "gth-image-viewer.h"
@@ -107,6 +108,11 @@ _gth_image_overviewer_disconnect_from_viewer (GthImageOverview *self)
g_signal_handler_disconnect (self->priv->viewer->hadj, self->priv->hadj_changed_id);
self->priv->hadj_changed_id = 0;
}
+
+ if (self->priv->viewer != NULL) {
+ g_object_remove_weak_pointer (G_OBJECT (self->priv->viewer), &self->priv->viewer);
+ self->priv->viewer = NULL;
+ }
}
@@ -128,33 +134,69 @@ gth_image_overview_finalize (GObject *object)
}
-static void
-_gth_image_overview_update_zoom_info (GthImageOverview *self)
+static gboolean
+_gth_image_overview_calc_preview_size (GthImageOverview *self,
+ int *out_width,
+ int *out_height,
+ double *out_zoom_factor)
+{
+ int width, height;
+ double zoom;
+ int preview_width, preview_height;
+
+ if (self->priv->viewer == NULL)
+ return FALSE;
+
+ gth_image_viewer_get_original_size (self->priv->viewer, &width, &height);
+ zoom = gth_image_viewer_get_zoom (self->priv->viewer);
+ width = width * zoom;
+ height = height * zoom;
+
+ preview_width = width;
+ preview_height = height;
+ scale_keeping_ratio (&preview_width, &preview_height, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE, TRUE);
+
+ if (out_width) *out_width = preview_width;
+ if (out_height) *out_height = preview_height;
+ if (out_zoom_factor) *out_zoom_factor = MIN ((double) (preview_width) / width,
+ (double) (preview_height) / height);
+
+ return TRUE;
+}
+
+
+static double
+_gth_image_overview_calc_quality_zoom (GthImageOverview *self)
{
cairo_surface_t *image;
int width, height;
- double zoom;
+
+ if (self->priv->viewer == NULL)
+ return 0.0;
image = gth_image_viewer_get_current_image (self->priv->viewer);
if (image == NULL)
- return;
+ return 0.0;
+
+ if (cairo_image_surface_get_width (image) == 0)
+ return 0.0;
gth_image_viewer_get_original_size (self->priv->viewer, &width, &height);
- self->priv->quality_zoom = (double) width / cairo_image_surface_get_width (image);
- zoom = gth_image_viewer_get_zoom (self->priv->viewer);
- width = width * zoom;
- height = height * zoom;
+ return (double) width / cairo_image_surface_get_width (image);
+}
- self->priv->preview_width = width;
- self->priv->preview_height = height;
- scale_keeping_ratio (&self->priv->preview_width,
- &self->priv->preview_height,
- MAX_IMAGE_SIZE,
- MAX_IMAGE_SIZE,
- TRUE);
- self->priv->zoom_factor = MIN ((double) (self->priv->preview_width) / width,
- (double) (self->priv->preview_height) / height);
+static void
+_gth_image_overview_update_zoom_info (GthImageOverview *self)
+{
+ self->priv->quality_zoom = _gth_image_overview_calc_quality_zoom (self);
+ if (self->priv->quality_zoom == 0.0)
+ return;
+
+ _gth_image_overview_calc_preview_size (self,
+ &self->priv->preview_width,
+ &self->priv->preview_height,
+ &self->priv->zoom_factor);
self->priv->preview_area.x = IMAGE_BORDER;
self->priv->preview_area.y = IMAGE_BORDER;
@@ -168,7 +210,10 @@ _gth_image_overview_update_zoom_info (GthImageOverview *self)
typedef struct {
GthImageOverview *overview;
+ cairo_surface_t *image;
cairo_surface_t *scaled;
+ int width;
+ int height;
} ScaleData;
@@ -178,6 +223,7 @@ scale_data_free (ScaleData *scale_data)
if (scale_data == NULL)
return;
cairo_surface_destroy (scale_data->scaled);
+ cairo_surface_destroy (scale_data->image);
g_object_unref (scale_data->overview);
g_free (scale_data);
}
@@ -187,18 +233,13 @@ static gpointer
_gth_image_overview_scale_exec (GthAsyncTask *task,
gpointer user_data)
{
- ScaleData *scale_data = user_data;
- GthImageOverview *overview = scale_data->overview;
- cairo_surface_t *image;
+ ScaleData *scale_data = user_data;
- _gth_image_overview_update_zoom_info (overview);
- image = gth_image_viewer_get_current_image (scale_data->overview->priv->viewer);
- if (image != NULL)
- scale_data->scaled = _cairo_image_surface_scale (image,
- overview->priv->preview_area.width,
- overview->priv->preview_area.height,
- SCALE_FILTER_GOOD,
- task);
+ scale_data->scaled = _cairo_image_surface_scale (scale_data->image,
+ scale_data->width,
+ scale_data->height,
+ SCALE_FILTER_GOOD,
+ task);
return NULL;
}
@@ -214,10 +255,13 @@ _gth_image_overview_scale_after (GthAsyncTask *task,
if (error == NULL) {
GthImageOverview *overview = scale_data->overview;
- _cairo_clear_surface (&overview->priv->preview);
- if (scale_data->scaled != NULL)
- overview->priv->preview = cairo_surface_reference (scale_data->scaled);
- gtk_widget_queue_resize (GTK_WIDGET (overview));
+ if (overview->priv->viewer != NULL) {
+ _gth_image_overview_update_zoom_info (overview);
+ _cairo_clear_surface (&overview->priv->preview);
+ if (scale_data->scaled != NULL)
+ overview->priv->preview = cairo_surface_reference (scale_data->scaled);
+ gtk_widget_queue_resize (GTK_WIDGET (overview));
+ }
if (GTH_TASK (task) == overview->priv->scale_task)
overview->priv->scale_task = NULL;
@@ -261,6 +305,11 @@ _gth_image_overview_update_preview (GthImageOverview *self)
scale_data = g_new0 (ScaleData, 1);
scale_data->overview = g_object_ref (self);
+ scale_data->image = cairo_surface_reference (image);
+ _gth_image_overview_calc_preview_size (self,
+ &scale_data->width,
+ &scale_data->height,
+ NULL);
self->priv->scale_task = gth_async_task_new (NULL,
_gth_image_overview_scale_exec,
@@ -347,10 +396,6 @@ _gth_image_overview_set_viewer (GthImageOverview *self,
return;
_gth_image_overviewer_disconnect_from_viewer (self);
- if (self->priv->viewer != NULL) {
- g_object_remove_weak_pointer (G_OBJECT (viewer), (gpointer*) &self->priv->viewer);
- self->priv->viewer = NULL;
- }
if (viewer == NULL)
return;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]