Skip to content

Commit c5460c6

Browse files
committed
keep extra refs to imageui
to stop unref on stack_remove
1 parent f1730e2 commit c5460c6

File tree

3 files changed

+66
-66
lines changed

3 files changed

+66
-66
lines changed

README.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,6 @@ On success, merge to master.
230230

231231
## TODO
232232

233-
- get `object_unref: assertion 'G_IS_OBJECT (object)' failed` during free of
234-
stack ... seems to be a harmless minor glib bug with `g_clear_object()`
235-
failing with a crit for a null value
236-
237-
maybe check glib master and file a bug report
238-
239233
- PDF page change does not change image size if pages vary in size
240234

241235
- ^C during a slow load leaves a file in /tmp, can we improve this?

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
project(
22
'vipsdisp', 'c',
3-
version: '3.0.0',
3+
version: '3.0.1',
44
license: 'MIT',
55
meson_version: '>=0.56',
66
default_options: [

src/imagewindow.c

Lines changed: 65 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@
44

55
#include "vipsdisp.h"
66

7-
/* We have a number of active imageui (open images) and look them up via a
8-
* filename. Use this to flip back to an open image.
7+
/* We have a number of active imageui (open images) and look them up via the
8+
* tile_source filename or image pointer.
9+
*
10+
* Use these to flip back to an already open image.
911
*/
1012
typedef struct _Active {
1113
ImageWindow *win;
12-
const char *filename;
14+
15+
/* This is a ref ... we can't just use the ref in the widget hierarchy or
16+
* it'll be freed during gtk_stack_remove() and cause chaos.
17+
*
18+
* Fetch active
19+
*/
1320
Imageui *imageui;
1421

1522
/* A timestamp we update on every action -- we throw away the oldest views
@@ -60,7 +67,7 @@ struct _ImageWindow {
6067
/* The set of active images in the stack right now. These are not
6168
* references.
6269
*/
63-
GHashTable *active_hash;
70+
GSList *active;
6471

6572
GSettings *settings;
6673
};
@@ -138,80 +145,80 @@ image_window_error_hide(ImageWindow *win)
138145
*/
139146

140147
static Active *
141-
image_window_active_lookup(ImageWindow *win, const char *filename)
142-
{
143-
return g_hash_table_lookup(win->active_hash, (gpointer) filename);
144-
}
145-
146-
static void
147-
image_window_active_touch(ImageWindow *win, const char *filename)
148+
image_window_active_lookup_by_filename(ImageWindow *win, const char *filename)
148149
{
149-
static int serial = 0;
150+
for (GSList *p = win->active; p; p = p->next) {
151+
Active *active = (Active *) p->data;
152+
TileSource *tile_source = imageui_get_tile_source(active->imageui);
150153

151-
Active *active = image_window_active_lookup(win, filename);
154+
if (tile_source->filename &&
155+
g_str_equal(tile_source->filename, filename))
156+
return active;
157+
}
152158

153-
active->timestamp = serial++;
159+
return NULL;
154160
}
155161

156162
static void
157-
active_imageui_active_oldest(gpointer key, gpointer value, gpointer user_data)
163+
image_window_active_touch(ImageWindow *win, Active *active)
158164
{
159-
Active *this = (Active *) value;
160-
const char **oldest = (const char **) user_data;
161-
Active *prev = (*oldest) ?
162-
image_window_active_lookup(this->win, *oldest) : NULL;
165+
static int serial = 0;
163166

164-
if (!prev ||
165-
this->timestamp < prev->timestamp)
166-
*oldest = this->filename;
167+
active->timestamp = serial++;
167168
}
168169

169170
static void
170-
image_window_active_remove(ImageWindow *win, const char *filename)
171+
image_window_active_remove(ImageWindow *win, Active *active)
171172
{
172-
Active *active = image_window_active_lookup(win, filename);
173+
gtk_stack_remove(GTK_STACK(win->stack), GTK_WIDGET(active->imageui));
173174

174175
if (active->imageui == win->imageui)
175176
win->imageui = NULL;
176177

177-
// many version of gtk hate removing a widget which has focus
178-
gtk_widget_grab_focus(win->gears);
178+
VIPS_UNREF(active->imageui);
179179

180-
gtk_stack_remove(GTK_STACK(win->stack), GTK_WIDGET(active->imageui));
181-
g_hash_table_remove(win->active_hash, filename);
180+
win->active = g_slist_remove(win->active, active);
181+
182+
g_free(active);
182183
}
183184

184185
static void
185186
image_window_active_remove_all(ImageWindow *win)
186187
{
187-
g_autofree const char **filenames =
188-
(const char **) g_hash_table_get_keys_as_array(win->active_hash, NULL);
188+
while (win->active) {
189+
Active *active = (Active *) win->active->data;
189190

190-
for (const char **p = filenames; *p; p++)
191-
image_window_active_remove(win, *p);
191+
image_window_active_remove(win, active);
192+
}
192193
}
193194

194195
static void
195-
image_window_active_add(ImageWindow *win,
196-
const char *filename, Imageui *imageui)
196+
image_window_active_add(ImageWindow *win, Imageui *imageui)
197197
{
198-
g_assert(!image_window_active_lookup(win, filename));
199-
200198
Active *active = VIPS_NEW(NULL, Active);
201199
active->win = win;
202-
active->filename = filename;
203200
active->imageui = imageui;
204-
g_hash_table_insert(win->active_hash, (gpointer) filename, active);
205-
image_window_active_touch(win, filename);
206201

207-
if (g_hash_table_size(win->active_hash) > 3) {
208-
const char *oldest = NULL;
202+
// we hold a true reference
203+
g_object_ref(imageui);
204+
205+
win->active = g_slist_prepend(win->active, active);
209206

210-
g_hash_table_foreach(win->active_hash,
211-
active_imageui_active_oldest, &oldest);
207+
image_window_active_touch(win, active);
208+
209+
while (g_slist_length(win->active) > 3) {
210+
Active *oldest;
211+
212+
oldest = NULL;
213+
for (GSList *p = win->active; p; p = p->next) {
214+
Active *active = (Active *) p->data;
215+
216+
if (!oldest ||
217+
active->timestamp < oldest->timestamp)
218+
oldest = active;
219+
}
212220

213-
if (oldest)
214-
image_window_active_remove(win, oldest);
221+
image_window_active_remove(win, oldest);
215222
}
216223
}
217224

@@ -544,7 +551,7 @@ image_window_imageui_changed(Imageui *imageui, ImageWindow *win)
544551
/* Add an imageui to the stack.
545552
*/
546553
static void
547-
image_window_imageui_add(ImageWindow *win, Imageui *imageui)
554+
image_window_imageui_add(ImageWindow *win, Imageui *imageui)
548555
{
549556
TileSource *tile_source = imageui_get_tile_source(imageui);
550557

@@ -563,6 +570,8 @@ image_window_imageui_add(ImageWindow *win, Imageui *imageui)
563570

564571
gtk_stack_add_child(GTK_STACK(win->stack), GTK_WIDGET(imageui));
565572

573+
image_window_active_add(win, imageui);
574+
566575
// now it's in the UI, trigger a load
567576
tile_source_background_load(tile_source);
568577
}
@@ -580,9 +589,10 @@ image_window_imageui_set_visible(ImageWindow *win,
580589
VipsImage *image;
581590
char *title;
582591

583-
g_object_set(old_tile_source,
584-
"visible", FALSE,
585-
NULL);
592+
if (old_tile_source)
593+
g_object_set(old_tile_source,
594+
"visible", FALSE,
595+
NULL);
586596

587597
g_object_set(win->properties,
588598
"tile-source", new_tile_source,
@@ -657,8 +667,8 @@ image_window_open_current_file(ImageWindow *win,
657667
image_window_imageui_set_visible(win, NULL, transition);
658668
else {
659669
char *filename = win->files[win->current_file];
660-
g_autoptr(Imageui) imageui = NULL;
661670

671+
Imageui *imageui;
662672
Active *active;
663673

664674
#ifdef DEBUG
@@ -667,10 +677,9 @@ image_window_open_current_file(ImageWindow *win,
667677

668678
/* An old image selected again?
669679
*/
670-
if ((active = image_window_active_lookup(win, filename))) {
680+
imageui = NULL;
681+
if ((active = image_window_active_lookup_by_filename(win, filename)))
671682
imageui = active->imageui;
672-
g_object_ref(imageui);
673-
}
674683
else {
675684
/* FIXME ... we only want to revalidate if eg. the timestamp has
676685
* changed, or perhaps on F5?
@@ -696,8 +705,6 @@ image_window_open_current_file(ImageWindow *win,
696705
}
697706

698707
image_window_imageui_add(win, imageui);
699-
700-
image_window_active_add(win, filename, imageui);
701708
}
702709

703710
image_window_imageui_set_visible(win, imageui, transition);
@@ -713,11 +720,12 @@ image_window_dispose(GObject *object)
713720
printf("image_window_dispose:\n");
714721
#endif /*DEBUG*/
715722

723+
image_window_files_free(win);
724+
716725
VIPS_UNREF(win->save_folder);
717726
VIPS_UNREF(win->load_folder);
718727
VIPS_FREEF(gtk_widget_unparent, win->right_click_menu);
719728
VIPS_FREEF(g_timer_destroy, win->progress_timer);
720-
image_window_files_free(win);
721729

722730
G_OBJECT_CLASS(image_window_parent_class)->dispose(object);
723731
}
@@ -1508,8 +1516,6 @@ image_window_init(ImageWindow *win)
15081516
win->save_folder = g_file_new_for_path(cwd);
15091517
win->load_folder = g_file_new_for_path(cwd);
15101518
g_free(cwd);
1511-
win->active_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1512-
NULL, g_free);
15131519

15141520
gtk_widget_init_template(GTK_WIDGET(win));
15151521

@@ -1714,7 +1720,7 @@ image_window_open_image(ImageWindow *win, VipsImage *image)
17141720
return;
17151721
}
17161722

1717-
g_autoptr(Imageui) imageui = imageui_new(tile_source);
1723+
Imageui *imageui = imageui_new(tile_source);
17181724
if (!imageui) {
17191725
image_window_error(win);
17201726
return;

0 commit comments

Comments
 (0)