summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--ChangeLog7
-rw-r--r--Makefile18
-rw-r--r--config.mk1
-rw-r--r--man/feh.pre34
-rw-r--r--share/applications/Makefile24
-rw-r--r--share/applications/feh.pre10
-rw-r--r--src/filelist.c29
-rw-r--r--src/filelist.h3
-rw-r--r--src/help.raw4
-rw-r--r--src/imlib.c40
-rw-r--r--src/keyevents.c6
-rw-r--r--src/menu.c12
-rw-r--r--src/options.c6
-rw-r--r--src/options.h2
-rw-r--r--src/slideshow.c50
16 files changed, 229 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index bbfa508..3620e7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/share/applications/*.desktop
/src/deps.mk
/src/*.o
/src/*.inc
diff --git a/ChangeLog b/ChangeLog
index cca0525..561abfd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+git HEAD
+ * Add --keep-zoom-vp option to keep zoom and offsets when switching
+ images (patch by sdaau). Press 'k' to toggle it.
+ * Add --sort mtime option (patch by guns)
+ * Add a desktop file (installed to share/applications/feh.desktop)
+ * Use "feh -" to read image from stdin
+
Mon, 24 Dec 2012 15:45:54 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Release v2.8
diff --git a/Makefile b/Makefile
index 16c15e2..94d811b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
include config.mk
-all: build-src build-man
+all: build-src build-man build-applications
build-src:
@${MAKE} -C src
@@ -8,6 +8,9 @@ build-src:
build-man:
@${MAKE} -C man
+build-applications:
+ @${MAKE} -C share/applications
+
test: all
@PACKAGE=${PACKAGE} prove test
@@ -16,7 +19,7 @@ test-x11: all
prove test/feh-bg.i
install: install-man install-doc install-bin install-font install-img
-install: install-examples
+install: install-examples install-applications
install-man:
@echo installing manuals to ${man_dir}
@@ -57,12 +60,19 @@ install-examples:
@cp examples/* ${example_dir}
@chmod 644 ${example_dir}/*
+install-applications:
+ @echo installing desktop file to ${desktop_dir}
+ @mkdir -p ${desktop_dir}
+ @cp share/applications/feh.desktop ${desktop_dir}
+ @chmod 644 ${desktop_dir}/feh.desktop
+
uninstall:
rm -f ${man_dir}/man1/feh.1 ${man_dir}/man1/feh-cam.1
rm -f ${man_dir}/man1/gen-cam-menu.1
rm -rf ${doc_dir}
rm -f ${bin_dir}/feh ${bin_dir}/feh-cam ${bin_dir}/gen-cam-menu
+ rm -f ${desktop_dir}/feh.desktop
rm -rf ${font_dir}
rm -rf ${image_dir}
@@ -86,6 +96,8 @@ disttest: dist
clean:
@${MAKE} -C src clean
@${MAKE} -C man clean
+ @${MAKE} -C share/applications clean
.PHONY: all test test-x11 install uninstall clean install-man install-doc \
- install-bin install-font install-img install-examples dist
+ install-bin install-font install-img install-examples \
+ install-applications dist
diff --git a/config.mk b/config.mk
index e0b30cd..bd598df 100644
--- a/config.mk
+++ b/config.mk
@@ -12,6 +12,7 @@ doc_dir = ${main_dir}/share/doc/feh
image_dir = ${main_dir}/share/feh/images
font_dir = ${main_dir}/share/feh/fonts
example_dir = ${main_dir}/share/doc/feh/examples
+desktop_dir = ${main_dir}/share/applications
# default CFLAGS
CFLAGS ?= -g -O2
diff --git a/man/feh.pre b/man/feh.pre
index e9ee3b7..a1df25a 100644
--- a/man/feh.pre
+++ b/man/feh.pre
@@ -72,6 +72,10 @@ image in it, the keyboard and mouse can be used to change slides
In slideshow mode, images can be deleted either from the filelist or from the
disk, the new filelist can then be saved to the disk and reopened at a later
time.
+An image can also be read from stdin via
+.Qq feh - .
+However, you should not combine reading from stdin with normal file / filelist
+usage.
.
.Pp
.
@@ -375,6 +379,11 @@ with
.Qq Nm
in the name.
.
+.It Cm --keep-zoom-vp
+.
+When switching images, keep zoom and viewport settings
+.Pq zoom level and X, Y offsets
+.
.It Cm -l , --list
.
Don't display images. Analyze them and display an
@@ -527,10 +536,15 @@ in paused mode.
.It Cm -S , --sort Ar sort_type
.
The file list may be sorted according to image parameters. Allowed sort
-types are: name, filename, width, height, pixels, size, format. For sort
-modes other than name or filename, a preload run will be necessary,
+types are: name, filename, mtime, width, height, pixels, size, format. For sort
+modes other than name, filename, or mtime, a preload run will be necessary,
causing a delay proportional to the number of images in the list.
.
+.Pp
+.
+The mtime sort mode sorts images by most recently modified. To sort by oldest
+first, reverse the filelist with --reverse.
+.
.It Cm -| , --start-at Ar filename
.
Start the filelist at
@@ -1048,16 +1062,16 @@ and save the caption, or escape to cancel editing. Note that you can insert
an actual newline into the caption using
.Aq CTRL+return .
.
-.It e Bq toggle_exif
-.
-.Pq only if compiled with exif=1
-Toggle EXIF tag display
-.
.It d Bq toggle_filenames
.
Toggle filename display
.Pq see Cm --draw-filename
.
+.It e Bq toggle_exif
+.
+.Pq only if compiled with exif=1
+Toggle EXIF tag display
+.
.It f Bq save_filelist
.
Save the current filelist as
@@ -1074,6 +1088,12 @@ change slides based on
Toggle info display
.Pq see Cm --info
.
+.It k Bq toggle_keep_vp
+.
+Toggle zoom and viewport keeping. When enabled,
+.Nm
+will keep zoom and X, Y offset when switching images.
+.
.It m Bq toggle_menu
.
Show menu. Use the arrow keys and return to select items,
diff --git a/share/applications/Makefile b/share/applications/Makefile
new file mode 100644
index 0000000..d57e33d
--- /dev/null
+++ b/share/applications/Makefile
@@ -0,0 +1,24 @@
+include ../../config.mk
+
+SOURCES = ${shell echo *.pre}
+TARGETS = ${SOURCES:.pre=.desktop}
+
+all: ${TARGETS}
+
+.pre.desktop:
+ sed \
+ -e 's/\$$VERSION\$$/${VERSION}/g' \
+ -e 's/\$$DATE\$$/'"$$(date '+%B %d, %Y')"/g \
+ -e 's/\$$MAN_CURL\$$/${MAN_CURL}/' \
+ -e 's/\$$MAN_DEBUG\$$/${MAN_DEBUG}/' \
+ -e 's/\$$MAN_EXIF\$$/${MAN_EXIF}/' \
+ -e 's/\$$MAN_XINERAMA\$$/${MAN_XINERAMA}/' \
+ -e 's:\$$IMAGEDIR\$$:${image_dir}:' \
+ < ${@:.desktop=.pre} > $@
+
+clean:
+ rm -f *.desktop
+
+.SUFFIXES: .pre .desktop
+
+.PHONY: clean
diff --git a/share/applications/feh.pre b/share/applications/feh.pre
new file mode 100644
index 0000000..d7b22c7
--- /dev/null
+++ b/share/applications/feh.pre
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Feh
+Comment=Fast Imlib2-based Image Viewer
+Exec=feh %f
+Terminal=false
+Type=Application
+Icon=$IMAGEDIR$/logo.svg
+Categories=Graphics;2DGraphics;Viewer;
+MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/pjpeg;image/png;image/tiff;image/x-bmp;image/x-pcx;image/x-png;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-tga;image/x-xbitmap;
+Name[en_US]=feh
diff --git a/src/filelist.c b/src/filelist.c
index 542dbdf..3ea0928 100644
--- a/src/filelist.c
+++ b/src/filelist.c
@@ -185,6 +185,11 @@ void add_file_to_filelist_recursively(char *origpath, unsigned char level)
/* We'll download it later... */
free(path);
return;
+ } else if ((len == 1) && (path[0] == '-')) {
+ D(("Addig stdin (-) to filelist\n"));
+ filelist = gib_list_add_front(filelist, feh_file_new(path));
+ free(path);
+ return;
} else if (opt.filelistfile) {
char *newpath = feh_absolute_path(path);
@@ -354,6 +359,25 @@ int feh_cmp_name(void *file1, void *file2)
return(strcmp(FEH_FILE(file1)->name, FEH_FILE(file2)->name));
}
+/* Return -1 if file1 is _newer_ than file2 */
+int feh_cmp_mtime(void *file1, void *file2)
+{
+ struct stat s1, s2;
+
+ if (stat(FEH_FILE(file1)->filename, &s1)) {
+ feh_print_stat_error(FEH_FILE(file1)->filename);
+ return(-1);
+ }
+
+ if (stat(FEH_FILE(file2)->filename, &s2)) {
+ feh_print_stat_error(FEH_FILE(file2)->filename);
+ return(-1);
+ }
+
+ /* gib_list_sort is not stable, so explicitly return 0 as -1 */
+ return(s1.st_mtime >= s2.st_mtime ? -1 : 1);
+}
+
int feh_cmp_width(void *file1, void *file2)
{
return((FEH_FILE(file1)->info->width - FEH_FILE(file2)->info->width));
@@ -381,7 +405,7 @@ int feh_cmp_format(void *file1, void *file2)
void feh_prepare_filelist(void)
{
- if (opt.list || opt.customlist || (opt.sort > SORT_FILENAME)
+ if (opt.list || opt.customlist || (opt.sort > SORT_MTIME)
|| opt.preload || opt.min_width || opt.min_height
|| (opt.max_width != UINT_MAX) || (opt.max_height != UINT_MAX)) {
/* For these sort options, we have to preload images */
@@ -407,6 +431,9 @@ void feh_prepare_filelist(void)
case SORT_FILENAME:
filelist = gib_list_sort(filelist, feh_cmp_filename);
break;
+ case SORT_MTIME:
+ filelist = gib_list_sort(filelist, feh_cmp_mtime);
+ break;
case SORT_WIDTH:
filelist = gib_list_sort(filelist, feh_cmp_width);
break;
diff --git a/src/filelist.h b/src/filelist.h
index 00e36e8..7bfd518 100644
--- a/src/filelist.h
+++ b/src/filelist.h
@@ -56,7 +56,7 @@ struct __feh_file_info {
enum filelist_recurse { FILELIST_FIRST, FILELIST_CONTINUE, FILELIST_LAST };
-enum sort_type { SORT_NONE, SORT_NAME, SORT_FILENAME, SORT_WIDTH,
+enum sort_type { SORT_NONE, SORT_NAME, SORT_FILENAME, SORT_MTIME, SORT_WIDTH,
SORT_HEIGHT,
SORT_PIXELS,
SORT_SIZE, SORT_FORMAT
@@ -82,6 +82,7 @@ void feh_save_filelist();
int feh_cmp_name(void *file1, void *file2);
int feh_cmp_filename(void *file1, void *file2);
+int feh_cmp_mtime(void *file1, void *file2);
int feh_cmp_width(void *file1, void *file2);
int feh_cmp_height(void *file1, void *file2);
int feh_cmp_pixels(void *file1, void *file2);
diff --git a/src/help.raw b/src/help.raw
index 8e25b00..462e715 100644
--- a/src/help.raw
+++ b/src/help.raw
@@ -28,6 +28,7 @@ OPTIONS
mode or when window geometry is fixed. If combined
with --auto-zoom, zooming will be limited to the
the size.
+ --keep-zoom-vp Keep viewport zoom and settings while changing images
-w, --multiwindow Open all files at once, one window per image
-x, --borderless Create borderless windows
-d, --draw-filename Show the filename in the image window
@@ -45,7 +46,8 @@ OPTIONS
-U, --loadable List all loadable files. No image display
-u, --unloadable List all unloadable files. No image display
-S, --sort SORT_TYPE Sort files by:
- name, filename, width, height, pixels, size or format
+ name, filename, mtime, width, height, pixels, size,
+ or format
-n, --reverse Reverse sort order
-A, --action ACTION Specify action to perform when pressing <return>.
Executed by /bin/sh, may contain FORMAT SPECIFIERS
diff --git a/src/imlib.c b/src/imlib.c
index e9f92ad..bdf54ac 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -61,6 +61,7 @@ int num_xinerama_screens;
int childpid = 0;
+static char *feh_stdin_load_image();
static char *feh_http_load_image(char *url);
static char *feh_magick_load_image(char *filename);
@@ -209,7 +210,8 @@ void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
int feh_load_image(Imlib_Image * im, feh_file * file)
{
Imlib_Load_Error err;
- enum { SRC_IMLIB, SRC_HTTP, SRC_MAGICK } image_source = SRC_IMLIB;
+ enum { SRC_IMLIB, SRC_HTTP, SRC_MAGICK, SRC_STDIN } image_source =
+ SRC_IMLIB;
char *tmpname = NULL;
char *real_filename = NULL;
@@ -225,6 +227,10 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
tmpname = feh_http_load_image(file->filename);
}
+ if ((strlen(file->filename) == 1) && (file->filename[0] == '-')) {
+ image_source = SRC_STDIN;
+ tmpname = feh_stdin_load_image();
+ }
else
*im = imlib_load_image_with_error_return(file->filename, &err);
@@ -269,6 +275,38 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
return(1);
}
+static char *feh_stdin_load_image()
+{
+ char buf[1024];
+ size_t readsize;
+ char *sfn = estrjoin("_", "/tmp/feh_stdin", "XXXXXX", NULL);
+ int fd = mkstemp(sfn);
+ FILE *outfile;
+
+ if (fd == -1) {
+ free(sfn);
+ return NULL;
+ }
+
+ outfile = fdopen(fd, "w");
+
+ if (outfile == NULL) {
+ free(sfn);
+ return NULL;
+ }
+
+ while ((readsize = fread(buf, sizeof(char), sizeof(buf), stdin)) > 0) {
+ if (fwrite(buf, sizeof(char), readsize, outfile) < readsize) {
+ free(sfn);
+ return NULL;
+ }
+ }
+
+ fclose(outfile);
+
+ return sfn;
+}
+
static char *feh_magick_load_image(char *filename)
{
char argv_fd[12];
diff --git a/src/keyevents.c b/src/keyevents.c
index 470d624..9bda112 100644
--- a/src/keyevents.c
+++ b/src/keyevents.c
@@ -154,6 +154,7 @@ void init_keyevents(void) {
feh_set_kb(&keys.mirror, 0, XK_bar, 0, 0, 0, 0);
feh_set_kb(&keys.reload_minus, 0, XK_minus, 0, 0, 0, 0);
feh_set_kb(&keys.reload_plus, 0, XK_plus, 0, 0, 0, 0);
+ feh_set_kb(&keys.toggle_keep_vp, 0, XK_k, 0, 0, 0, 0);
home = getenv("HOME");
if (!home)
@@ -307,6 +308,8 @@ void init_keyevents(void) {
cur_kb = &keys.reload_minus;
else if (!strcmp(action, "reload_plus"))
cur_kb = &keys.reload_plus;
+ else if (!strcmp(action, "toggle_keep_vp"))
+ cur_kb = &keys.toggle_keep_vp;
else
weprintf("keys: Invalid action: %s", action);
@@ -761,5 +764,8 @@ void feh_event_handle_keypress(XEvent * ev)
else if (opt.verbose)
weprintf("Cannot set RELOAD lower than 1 second.");
}
+ else if (feh_is_kp(&keys.toggle_keep_vp, keysym, state)) {
+ opt.keep_zoom_vp = !opt.keep_zoom_vp;
+ }
return;
}
diff --git a/src/menu.c b/src/menu.c
index ee045ae..722ce02 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -56,7 +56,7 @@ enum {
CB_SORT_FILENAME, CB_SORT_IMAGENAME, CB_SORT_FILESIZE, CB_SORT_RANDOMIZE,
CB_SAVE_IMAGE, CB_SAVE_FILELIST, CB_FIT, CB_OPT_DRAW_FILENAME,
CB_OPT_DRAW_ACTIONS, CB_OPT_KEEP_HTTP, CB_OPT_FREEZE_WINDOW,
- CB_OPT_FULLSCREEN, CB_EDIT_ROTATE, CB_OPT_AUTO_ZOOM
+ CB_OPT_FULLSCREEN, CB_EDIT_ROTATE, CB_OPT_AUTO_ZOOM, CB_OPT_KEEP_ZOOM_VP
};
feh_menu *feh_menu_new(void)
@@ -1326,6 +1326,14 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, unsigned short dat
opt.zoom_mode = 0;
winwidget_rerender_all(1);
break;
+ case CB_OPT_KEEP_ZOOM_VP:
+ MENU_ITEM_TOGGLE(i);
+ if (MENU_ITEM_IS_ON(i))
+ opt.keep_zoom_vp = 1;
+ else
+ opt.keep_zoom_vp = 0;
+ winwidget_rerender_all(1);
+ break;
}
return;
}
@@ -1381,6 +1389,8 @@ static feh_menu *feh_menu_func_gen_options(feh_menu * m)
CB_OPT_FREEZE_WINDOW, 0, NULL, opt.geom_flags);
feh_menu_add_toggle_entry(mm, "Fullscreen", NULL,
CB_OPT_FULLSCREEN, 0, NULL, m->fehwin->full_screen);
+ feh_menu_add_toggle_entry(mm, "Keep viewport zoom & pos", NULL,
+ CB_OPT_KEEP_ZOOM_VP, 0, NULL, opt.keep_zoom_vp);
feh_menu_add_entry(mm, NULL, NULL, 0, 0, NULL);
diff --git a/src/options.c b/src/options.c
index 240b0d6..469115e 100644
--- a/src/options.c
+++ b/src/options.c
@@ -397,6 +397,7 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
{"info" , 1, 0, 234},
{"force-aliasing", 0, 0, 235},
{"no-fehbg" , 0, 0, 236},
+ {"keep-zoom-vp" , 0, 0, 237},
{0, 0, 0, 0}
};
@@ -500,6 +501,8 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.sort = SORT_NAME;
else if (!strcasecmp(optarg, "filename"))
opt.sort = SORT_FILENAME;
+ else if (!strcasecmp(optarg, "mtime"))
+ opt.sort = SORT_MTIME;
else if (!strcasecmp(optarg, "width"))
opt.sort = SORT_WIDTH;
else if (!strcasecmp(optarg, "height"))
@@ -722,6 +725,9 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
case 236:
opt.no_fehbg = 1;
break;
+ case 237:
+ opt.keep_zoom_vp = 1;
+ break;
default:
break;
}
diff --git a/src/options.h b/src/options.h
index d30c396..f3f49eb 100644
--- a/src/options.h
+++ b/src/options.h
@@ -72,6 +72,7 @@ struct __fehoptions {
unsigned char text_bg;
unsigned char image_bg;
unsigned char no_fehbg;
+ unsigned char keep_zoom_vp;
char *output_file;
char *output_dir;
@@ -189,6 +190,7 @@ struct __fehkb {
struct __fehkey toggle_fullscreen;
struct __fehkey reload_minus;
struct __fehkey reload_plus;
+ struct __fehkey toggle_keep_vp;
};
struct __fehbutton {
diff --git a/src/slideshow.c b/src/slideshow.c
index d79c859..65aae3d 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -149,6 +149,16 @@ void feh_reload_image(winwidget w, int resize, int force_new)
Imlib_Image tmp;
int old_w, old_h;
+ unsigned char tmode =0;
+ int tim_x =0;
+ int tim_y =0;
+ double tzoom =0;
+
+ tmode = w->mode;
+ tim_x = w->im_x;
+ tim_y = w->im_y;
+ tzoom = w->zoom;
+
if (!w->file) {
im_weprintf(w, "couldn't reload, this image has no file associated with it.");
winwidget_render_image(w, 0, 0);
@@ -216,7 +226,16 @@ void feh_reload_image(winwidget w, int resize, int force_new)
w->im_w = gib_imlib_image_get_width(w->im);
w->im_h = gib_imlib_image_get_height(w->im);
}
- winwidget_render_image(w, resize, 0);
+ if (opt.keep_zoom_vp) {
+ /* put back in: */
+ w->mode = tmode;
+ w->im_x = tim_x;
+ w->im_y = tim_y;
+ w->zoom = tzoom;
+ winwidget_render_image(w, 0, 0);
+ } else {
+ winwidget_render_image(w, resize, 0);
+ }
winwidget_rename(w, title);
free(title);
@@ -236,6 +255,11 @@ void slideshow_change_image(winwidget winwid, int change, int render)
int our_filelist_len = filelist_len;
char *s;
+ unsigned char tmode =0;
+ int tim_x =0;
+ int tim_y =0;
+ double tzoom =0;
+
/* Without this, clicking a one-image slideshow reloads it. Not very *
intelligent behaviour :-) */
if (filelist_len < 2 && opt.cycle_once == 0)
@@ -308,6 +332,14 @@ void slideshow_change_image(winwidget winwid, int change, int render)
last = NULL;
}
+ if (opt.keep_zoom_vp) {
+ /* pre loadimage - record settings */
+ tmode = winwid->mode;
+ tim_x = winwid->im_x;
+ tim_y = winwid->im_y;
+ tzoom = winwid->zoom;
+ }
+
if ((winwidget_loadimage(winwid, FEH_FILE(current_file->data)))
!= 0) {
winwid->mode = MODE_NORMAL;
@@ -318,8 +350,20 @@ void slideshow_change_image(winwidget winwid, int change, int render)
winwidget_reset_image(winwid);
winwid->im_w = gib_imlib_image_get_width(winwid->im);
winwid->im_h = gib_imlib_image_get_height(winwid->im);
- if (render)
- winwidget_render_image(winwid, 1, 0);
+ if (opt.keep_zoom_vp) {
+ /* put back in: */
+ winwid->mode = tmode;
+ winwid->im_x = tim_x;
+ winwid->im_y = tim_y;
+ winwid->zoom = tzoom;
+ }
+ if (render) {
+ if (opt.keep_zoom_vp) {
+ winwidget_render_image(winwid, 0, 0);
+ } else {
+ winwidget_render_image(winwid, 1, 0);
+ }
+ }
s = slideshow_create_name(FEH_FILE(current_file->data), winwid);
winwidget_rename(winwid, s);