Revised thumbnail loading...
- Only load the thumbnails that are currently visible in the window - Unload thumbnails that are leaving the visible area - Much less memory needed, but scrolling is now slower - This also unintentionally fixes issue #86
This commit is contained in:
parent
52e56c8924
commit
eaa269b6cb
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
VERSION = git-20140911
|
VERSION = git-20140926
|
||||||
|
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
MANPREFIX = $(PREFIX)/share/man
|
MANPREFIX = $(PREFIX)/share/man
|
||||||
|
|
|
@ -470,7 +470,8 @@ bool ct_reload_all(arg_t a)
|
||||||
{
|
{
|
||||||
tns_free(&tns);
|
tns_free(&tns);
|
||||||
tns_init(&tns, files, filecnt, &fileidx, &win);
|
tns_init(&tns, files, filecnt, &fileidx, &win);
|
||||||
return false;
|
tns.dirty = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
31
main.c
31
main.c
|
@ -368,14 +368,13 @@ void update_info(void)
|
||||||
return;
|
return;
|
||||||
mark = files[fileidx].marked ? "+ " : "";
|
mark = files[fileidx].marked ? "+ " : "";
|
||||||
if (mode == MODE_THUMB) {
|
if (mode == MODE_THUMB) {
|
||||||
if (tns.loadnext >= filecnt) {
|
if (tns.loadnext < tns.end) {
|
||||||
n = snprintf(rt, rlen, "%s%0*d/%d", mark, fw, fileidx + 1, filecnt);
|
snprintf(lt, llen, "Loading... %0*d", fw, tns.loadnext);
|
||||||
ow_info = true;
|
|
||||||
} else {
|
|
||||||
snprintf(lt, llen, "Loading... %0*d/%d", fw, tns.loadnext, filecnt);
|
|
||||||
rt[0] = '\0';
|
|
||||||
ow_info = false;
|
ow_info = false;
|
||||||
|
} else {
|
||||||
|
ow_info = true;
|
||||||
}
|
}
|
||||||
|
n = snprintf(rt, rlen, "%s%0*d/%d", mark, fw, fileidx + 1, filecnt);
|
||||||
} else {
|
} else {
|
||||||
n = snprintf(rt, rlen, "%s", mark);
|
n = snprintf(rt, rlen, "%s", mark);
|
||||||
if (img.ss.on)
|
if (img.ss.on)
|
||||||
|
@ -439,7 +438,7 @@ void reset_cursor(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tns.loadnext < filecnt)
|
if (tns.loadnext < tns.end)
|
||||||
cursor = CURSOR_WATCH;
|
cursor = CURSOR_WATCH;
|
||||||
else
|
else
|
||||||
cursor = CURSOR_ARROW;
|
cursor = CURSOR_ARROW;
|
||||||
|
@ -531,7 +530,7 @@ void run_key_handler(const char *key, unsigned int mask)
|
||||||
memcmp(&oldst->st_mtime, &newst.st_mtime, sizeof(newst.st_mtime)) != 0)
|
memcmp(&oldst->st_mtime, &newst.st_mtime, sizeof(newst.st_mtime)) != 0)
|
||||||
{
|
{
|
||||||
if (tns.thumbs != NULL) {
|
if (tns.thumbs != NULL) {
|
||||||
tns.thumbs[finfo[i].fn].loaded = false;
|
tns_unload(&tns, finfo[i].fn);
|
||||||
tns.loadnext = MIN(tns.loadnext, finfo[i].fn);
|
tns.loadnext = MIN(tns.loadnext, finfo[i].fn);
|
||||||
}
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -669,29 +668,24 @@ void run(void)
|
||||||
int xfd;
|
int xfd;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
bool discard, reload, to_set;
|
bool discard, to_set;
|
||||||
XEvent ev, nextev;
|
XEvent ev, nextev;
|
||||||
|
|
||||||
set_timeout(redraw, 25, false);
|
set_timeout(redraw, 25, false);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
while (mode == MODE_THUMB && tns.loadnext < filecnt &&
|
while (mode == MODE_THUMB && tns.loadnext < tns.end &&
|
||||||
XPending(win.env.dpy) == 0)
|
XPending(win.env.dpy) == 0)
|
||||||
{
|
{
|
||||||
/* load thumbnails */
|
/* load thumbnails */
|
||||||
reload = tns.loadnext != tns.cnt;
|
|
||||||
set_timeout(redraw, TO_REDRAW_THUMBS, false);
|
set_timeout(redraw, TO_REDRAW_THUMBS, false);
|
||||||
if (tns_load(&tns, tns.loadnext, reload)) {
|
if (!tns_load(&tns, tns.loadnext, false)) {
|
||||||
if (!reload)
|
|
||||||
tns.cnt++;
|
|
||||||
} else {
|
|
||||||
remove_file(tns.loadnext, false);
|
remove_file(tns.loadnext, false);
|
||||||
if (reload)
|
|
||||||
tns.dirty = true;
|
tns.dirty = true;
|
||||||
}
|
}
|
||||||
while (tns.loadnext < filecnt && tns.thumbs[tns.loadnext].loaded)
|
while (tns.loadnext < tns.end && tns.thumbs[tns.loadnext].im != NULL)
|
||||||
tns.loadnext++;
|
tns.loadnext++;
|
||||||
if (tns.loadnext >= filecnt)
|
if (tns.loadnext >= tns.end)
|
||||||
redraw();
|
redraw();
|
||||||
else
|
else
|
||||||
check_timeouts(NULL);
|
check_timeouts(NULL);
|
||||||
|
@ -882,7 +876,6 @@ int main(int argc, char **argv)
|
||||||
tns_init(&tns, files, filecnt, &fileidx, &win);
|
tns_init(&tns, files, filecnt, &fileidx, &win);
|
||||||
while (!tns_load(&tns, 0, false))
|
while (!tns_load(&tns, 0, false))
|
||||||
remove_file(0, false);
|
remove_file(0, false);
|
||||||
tns.cnt = 1;
|
|
||||||
} else {
|
} else {
|
||||||
mode = MODE_IMAGE;
|
mode = MODE_IMAGE;
|
||||||
tns.thumbs = NULL;
|
tns.thumbs = NULL;
|
||||||
|
|
64
thumbs.c
64
thumbs.c
|
@ -56,7 +56,7 @@ char* tns_cache_filepath(const char *filepath)
|
||||||
return cfile;
|
return cfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
Imlib_Image tns_cache_load(const char *filepath)
|
Imlib_Image tns_cache_load(const char *filepath, bool *outdated)
|
||||||
{
|
{
|
||||||
char *cfile;
|
char *cfile;
|
||||||
struct stat cstats, fstats;
|
struct stat cstats, fstats;
|
||||||
|
@ -68,8 +68,12 @@ Imlib_Image tns_cache_load(const char *filepath)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((cfile = tns_cache_filepath(filepath)) != NULL) {
|
if ((cfile = tns_cache_filepath(filepath)) != NULL) {
|
||||||
if (stat(cfile, &cstats) == 0 && cstats.st_mtime == fstats.st_mtime)
|
if (stat(cfile, &cstats) == 0) {
|
||||||
|
if (cstats.st_mtime == fstats.st_mtime)
|
||||||
im = imlib_load_image(cfile);
|
im = imlib_load_image(cfile);
|
||||||
|
else
|
||||||
|
*outdated = true;
|
||||||
|
}
|
||||||
free(cfile);
|
free(cfile);
|
||||||
}
|
}
|
||||||
return im;
|
return im;
|
||||||
|
@ -165,8 +169,8 @@ void tns_init(tns_t *tns, const fileinfo_t *files, int cnt, int *sel, win_t *win
|
||||||
tns->thumbs = NULL;
|
tns->thumbs = NULL;
|
||||||
}
|
}
|
||||||
tns->files = files;
|
tns->files = files;
|
||||||
tns->cap = cnt;
|
tns->cnt = cnt;
|
||||||
tns->cnt = tns->loadnext = tns->first = 0;
|
tns->loadnext = tns->first = tns->end = tns->r_first = tns->r_end = 0;
|
||||||
tns->sel = sel;
|
tns->sel = sel;
|
||||||
tns->win = win;
|
tns->win = win;
|
||||||
tns->dirty = false;
|
tns->dirty = false;
|
||||||
|
@ -218,7 +222,7 @@ bool tns_load(tns_t *tns, int n, bool force)
|
||||||
|
|
||||||
if (tns == NULL || tns->thumbs == NULL)
|
if (tns == NULL || tns->thumbs == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (n < 0 || n >= tns->cap)
|
if (n < 0 || n >= tns->cnt)
|
||||||
return false;
|
return false;
|
||||||
file = &tns->files[n];
|
file = &tns->files[n];
|
||||||
if (file->name == NULL || file->path == NULL)
|
if (file->name == NULL || file->path == NULL)
|
||||||
|
@ -231,7 +235,7 @@ bool tns_load(tns_t *tns, int n, bool force)
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!force && (im = tns_cache_load(file->path)) != NULL) {
|
if (!force && (im = tns_cache_load(file->path, &force)) != NULL) {
|
||||||
cache_hit = true;
|
cache_hit = true;
|
||||||
} else {
|
} else {
|
||||||
#if HAVE_LIBEXIF
|
#if HAVE_LIBEXIF
|
||||||
|
@ -323,11 +327,28 @@ bool tns_load(tns_t *tns, int n, bool force)
|
||||||
if (!cache_hit)
|
if (!cache_hit)
|
||||||
tns_cache_write(t, file, true);
|
tns_cache_write(t, file, true);
|
||||||
|
|
||||||
t->loaded = true;
|
|
||||||
tns->dirty = true;
|
tns->dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tns_unload(tns_t *tns, int n)
|
||||||
|
{
|
||||||
|
thumb_t *t;
|
||||||
|
|
||||||
|
if (tns == NULL || tns->thumbs == NULL)
|
||||||
|
return;
|
||||||
|
if (n < 0 || n >= tns->cnt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
t = &tns->thumbs[n];
|
||||||
|
|
||||||
|
if (t->im != NULL) {
|
||||||
|
imlib_context_set_image(t->im);
|
||||||
|
imlib_free_image();
|
||||||
|
t->im = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tns_check_view(tns_t *tns, bool scrolled)
|
void tns_check_view(tns_t *tns, bool scrolled)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
@ -385,20 +406,31 @@ void tns_render(tns_t *tns)
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
cnt -= r % tns->cols;
|
cnt -= r % tns->cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = cnt % tns->cols ? 1 : 0;
|
r = cnt % tns->cols ? 1 : 0;
|
||||||
tns->x = x = (win->w - MIN(cnt, tns->cols) * thumb_dim) / 2 + 5;
|
tns->x = x = (win->w - MIN(cnt, tns->cols) * thumb_dim) / 2 + 5;
|
||||||
tns->y = y = (win->h - (cnt / tns->cols + r) * thumb_dim) / 2 + 5;
|
tns->y = y = (win->h - (cnt / tns->cols + r) * thumb_dim) / 2 + 5;
|
||||||
|
tns->loadnext = tns->cnt;
|
||||||
|
tns->end = tns->first + cnt;
|
||||||
|
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = tns->r_first; i < tns->r_end; i++) {
|
||||||
t = &tns->thumbs[tns->first + i];
|
if ((i < tns->first || i >= tns->end) && tns->thumbs[i].im != NULL)
|
||||||
|
tns_unload(tns, i);
|
||||||
|
}
|
||||||
|
tns->r_first = tns->first;
|
||||||
|
tns->r_end = tns->end;
|
||||||
|
|
||||||
|
for (i = tns->first; i < tns->end; i++) {
|
||||||
|
t = &tns->thumbs[i];
|
||||||
|
if (t->im != NULL) {
|
||||||
t->x = x + (THUMB_SIZE - t->w) / 2;
|
t->x = x + (THUMB_SIZE - t->w) / 2;
|
||||||
t->y = y + (THUMB_SIZE - t->h) / 2;
|
t->y = y + (THUMB_SIZE - t->h) / 2;
|
||||||
imlib_context_set_image(t->im);
|
imlib_context_set_image(t->im);
|
||||||
imlib_render_image_part_on_drawable_at_size(0, 0, t->w, t->h,
|
imlib_render_image_on_drawable_at_size(t->x, t->y, t->w, t->h);
|
||||||
t->x, t->y, t->w, t->h);
|
if (tns->files[i].marked)
|
||||||
if (tns->files[tns->first + i].marked)
|
tns_mark(tns, i, true);
|
||||||
tns_mark(tns, tns->first + i, true);
|
} else {
|
||||||
|
tns->loadnext = MIN(tns->loadnext, i);
|
||||||
|
}
|
||||||
if ((i + 1) % tns->cols == 0) {
|
if ((i + 1) % tns->cols == 0) {
|
||||||
x = tns->x;
|
x = tns->x;
|
||||||
y += thumb_dim;
|
y += thumb_dim;
|
||||||
|
@ -415,7 +447,7 @@ void tns_mark(tns_t *tns, int n, bool mark)
|
||||||
if (tns == NULL || tns->thumbs == NULL || tns->win == NULL)
|
if (tns == NULL || tns->thumbs == NULL || tns->win == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (n >= 0 && n < tns->cnt) {
|
if (n >= 0 && n < tns->cnt && tns->thumbs[n].im != NULL) {
|
||||||
win_t *win = tns->win;
|
win_t *win = tns->win;
|
||||||
thumb_t *t = &tns->thumbs[n];
|
thumb_t *t = &tns->thumbs[n];
|
||||||
unsigned long col = win->fullscreen ? win->fscol : win->bgcol;
|
unsigned long col = win->fullscreen ? win->fscol : win->bgcol;
|
||||||
|
@ -440,7 +472,7 @@ void tns_highlight(tns_t *tns, int n, bool hl)
|
||||||
if (tns == NULL || tns->thumbs == NULL || tns->win == NULL)
|
if (tns == NULL || tns->thumbs == NULL || tns->win == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (n >= 0 && n < tns->cnt) {
|
if (n >= 0 && n < tns->cnt && tns->thumbs[n].im != NULL) {
|
||||||
win_t *win = tns->win;
|
win_t *win = tns->win;
|
||||||
thumb_t *t = &tns->thumbs[n];
|
thumb_t *t = &tns->thumbs[n];
|
||||||
unsigned long col;
|
unsigned long col;
|
||||||
|
|
6
thumbs.h
6
thumbs.h
|
@ -31,16 +31,15 @@ typedef struct {
|
||||||
int h;
|
int h;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
bool loaded;
|
|
||||||
} thumb_t;
|
} thumb_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const fileinfo_t *files;
|
const fileinfo_t *files;
|
||||||
thumb_t *thumbs;
|
thumb_t *thumbs;
|
||||||
int cap;
|
|
||||||
int cnt;
|
int cnt;
|
||||||
int loadnext;
|
int loadnext;
|
||||||
int first;
|
int first, end;
|
||||||
|
int r_first, r_end;
|
||||||
int *sel;
|
int *sel;
|
||||||
|
|
||||||
win_t *win;
|
win_t *win;
|
||||||
|
@ -58,6 +57,7 @@ void tns_init(tns_t*, const fileinfo_t*, int, int*, win_t*);
|
||||||
void tns_free(tns_t*);
|
void tns_free(tns_t*);
|
||||||
|
|
||||||
bool tns_load(tns_t*, int, bool);
|
bool tns_load(tns_t*, int, bool);
|
||||||
|
void tns_unload(tns_t*, int);
|
||||||
|
|
||||||
void tns_render(tns_t*);
|
void tns_render(tns_t*);
|
||||||
void tns_mark(tns_t*, int, bool);
|
void tns_mark(tns_t*, int, bool);
|
||||||
|
|
Loading…
Reference in a new issue