summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/feh.h5
-rw-r--r--src/filelist.c2
-rw-r--r--src/help.raw1
-rw-r--r--src/main.c35
-rw-r--r--src/options.c19
-rw-r--r--src/options.h4
-rw-r--r--src/signals.c13
-rw-r--r--src/slideshow.c4
-rw-r--r--src/thumbnail.c12
-rw-r--r--src/winwidget.c92
-rw-r--r--src/winwidget.h9
11 files changed, 183 insertions, 13 deletions
diff --git a/src/feh.h b/src/feh.h
index 1d5e918..4d094a3 100644
--- a/src/feh.h
+++ b/src/feh.h
@@ -152,7 +152,7 @@ void feh_event_handle_stdin();
void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysym, unsigned int button);
fehkey *feh_str_to_kb(char * action);
void feh_action_run(feh_file * file, char *action, winwidget winwid);
-char *format_size(int size);
+char *format_size(double size);
char *feh_printf(char *str, feh_file * file, winwidget winwid);
void im_weprintf(winwidget w, char *fmt, ...);
void feh_draw_zoom(winwidget w);
@@ -179,6 +179,9 @@ void feh_edit_inplace_lossless(winwidget w, int orientation);
gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style * style);
char *build_caption_filename(feh_file * file, short create_dir);
gib_list *feh_list_jump(gib_list * root, gib_list * l, int direction, int num);
+#ifdef HAVE_INOTIFY
+void feh_event_handle_inotify(void);
+#endif
/* Imlib stuff */
extern Display *disp;
diff --git a/src/filelist.c b/src/filelist.c
index 6f4f6df..e3ae020 100644
--- a/src/filelist.c
+++ b/src/filelist.c
@@ -76,7 +76,7 @@ void feh_file_free(feh_file * file)
#ifdef HAVE_LIBEXIF
if (file->ed)
exif_data_unref(file->ed);
-#endif
+#endif
free(file);
return;
}
diff --git a/src/help.raw b/src/help.raw
index ca7c85c..7a9a658 100644
--- a/src/help.raw
+++ b/src/help.raw
@@ -99,6 +99,7 @@ OPTIONS
--max-dimension WxH Only show images with width <= W and height <= H
--scroll-step COUNT scroll COUNT pixels when movement key is pressed
--cache-size NUM imlib cache size in mebibytes (0 .. 2048)
+ --auto-reload automatically reload shown image if file was changed
MONTAGE MODE OPTIONS
-X, --ignore-aspect Set thumbnail to specified width/height without
diff --git a/src/main.c b/src/main.c
index 87cf7c4..31ab8f8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,6 +34,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "wallpaper.h"
#include <termios.h>
+#ifdef HAVE_INOTIFY
+#include <sys/inotify.h>
+#endif
+
char **cmdargv = NULL;
int cmdargc = 0;
char *mode = NULL;
@@ -53,6 +57,16 @@ int main(int argc, char **argv)
init_x_and_imlib();
init_keyevents();
init_buttonbindings();
+#ifdef HAVE_INOTIFY
+ if (opt.auto_reload) {
+ opt.inotify_fd = inotify_init();
+ if (opt.inotify_fd < 0) {
+ opt.auto_reload = 0;
+ weprintf("inotify_init failed:");
+ weprintf("Disabling inotify-based auto-reload");
+ }
+ }
+#endif
}
feh_event_init();
@@ -146,6 +160,13 @@ int feh_main_iteration(int block)
FD_SET(xfd, &fdset);
if (control_via_stdin)
FD_SET(STDIN_FILENO, &fdset);
+#ifdef HAVE_INOTIFY
+ if (opt.auto_reload) {
+ FD_SET(opt.inotify_fd, &fdset);
+ if (opt.inotify_fd >= fdsize)
+ fdsize = opt.inotify_fd + 1;
+ }
+#endif
/* Timers */
ft = first_timer;
@@ -191,6 +212,10 @@ int feh_main_iteration(int block)
}
else if ((count > 0) && (FD_ISSET(0, &fdset)))
feh_event_handle_stdin();
+#ifdef HAVE_INOTIFY
+ else if ((count > 0) && (FD_ISSET(opt.inotify_fd, &fdset)))
+ feh_event_handle_inotify();
+#endif
}
} else {
/* Don't block if there are events in the queue. That's a bit rude ;-) */
@@ -204,6 +229,10 @@ int feh_main_iteration(int block)
eprintf("Connection to X display lost");
else if ((count > 0) && (FD_ISSET(0, &fdset)))
feh_event_handle_stdin();
+#ifdef HAVE_INOTIFY
+ else if ((count > 0) && (FD_ISSET(opt.inotify_fd, &fdset)))
+ feh_event_handle_inotify();
+#endif
}
}
if (window_num == 0 || sig_exit != 0)
@@ -218,6 +247,12 @@ void feh_clean_exit(void)
free(opt.menu_font);
+#ifdef HAVE_INOTIFY
+ if (opt.auto_reload)
+ if (close(opt.inotify_fd))
+ eprintf("inotify close failed");
+#endif
+
if(disp)
XCloseDisplay(disp);
diff --git a/src/options.c b/src/options.c
index 37fad88..4c34b66 100644
--- a/src/options.c
+++ b/src/options.c
@@ -25,7 +25,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <strings.h>
-
#include "feh.h"
#include "filelist.h"
#include "options.h"
@@ -74,6 +73,9 @@ void init_parse_options(int argc, char **argv)
opt.xinerama = 1;
opt.xinerama_index = -1;
#endif /* HAVE_LIBXINERAMA */
+#ifdef HAVE_INOTIFY
+ opt.auto_reload = 1;
+#endif /* HAVE_INOTIFY */
feh_getopt_theme(argc, argv);
@@ -425,6 +427,9 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
{"conversion-timeout" , 1, 0, 245},
{"version-sort" , 0, 0, 246},
{"offset" , 1, 0, 247},
+#ifdef HAVE_INOTIFY
+ {"auto-reload" , 0, 0, 248},
+#endif
{0, 0, 0, 0}
};
int optch = 0, cmdx = 0;
@@ -517,6 +522,9 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
break;
case 'R':
opt.reload = atof(optarg);
+#ifdef HAVE_INOTIFY
+ opt.auto_reload = 0;
+#endif
break;
case 'S':
if (!strcasecmp(optarg, "name"))
@@ -810,6 +818,11 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.offset_flags = XParseGeometry(optarg, &opt.offset_x,
&opt.offset_y, (unsigned int *)&discard, (unsigned int *)&discard);
break;
+#ifdef HAVE_INOTIFY
+ case 248:
+ opt.auto_reload = 1;
+ break;
+#endif
default:
break;
}
@@ -897,6 +910,10 @@ static void show_version(void)
"exif "
#endif
+#ifdef HAVE_INOTIFY
+ "inotify "
+#endif
+
#ifdef INCLUDE_HELP
"help "
#endif
diff --git a/src/options.h b/src/options.h
index 7f8fe9c..883c8e2 100644
--- a/src/options.h
+++ b/src/options.h
@@ -58,6 +58,10 @@ struct __fehoptions {
unsigned char draw_exif;
unsigned char auto_rotate;
#endif
+#ifdef HAVE_INOTIFY
+ unsigned char auto_reload;
+ int inotify_fd;
+#endif
unsigned char list;
unsigned char quiet;
unsigned char preload;
diff --git a/src/signals.c b/src/signals.c
index d65f49b..85d81bc 100644
--- a/src/signals.c
+++ b/src/signals.c
@@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "feh.h"
+#include "filelist.h"
#include "winwidget.h"
#include "options.h"
@@ -94,10 +95,14 @@ void feh_handle_signal(int signo)
winwid = winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW);
if (winwid) {
- if (signo == SIGUSR1)
- slideshow_change_image(winwid, SLIDE_NEXT, 1);
- else if (signo == SIGUSR2)
- slideshow_change_image(winwid, SLIDE_PREV, 1);
+ if (filelist_len > 1) {
+ if (signo == SIGUSR1)
+ slideshow_change_image(winwid, SLIDE_NEXT, 1);
+ else if (signo == SIGUSR2)
+ slideshow_change_image(winwid, SLIDE_PREV, 1);
+ } else {
+ feh_reload_image(winwid, 0, 0);
+ }
} else if (opt.multiwindow) {
for (i = window_num - 1; i >= 0; i--)
feh_reload_image(windows[i], 0, 0);
diff --git a/src/slideshow.c b/src/slideshow.c
index 145ced1..ac8c545 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -445,7 +445,7 @@ void feh_action_run(feh_file * file, char *action, winwidget winwid)
return;
}
-char *format_size(int size)
+char *format_size(double size)
{
static char ret[5];
char units[] = {' ', 'k', 'M', 'G', 'T'};
@@ -454,7 +454,7 @@ char *format_size(int size)
size /= 1000;
postfix++;
}
- snprintf(ret, 5, "%3d%c", size, units[postfix]);
+ snprintf(ret, 5, "%3.0f%c", size, units[postfix]);
return ret;
}
diff --git a/src/thumbnail.c b/src/thumbnail.c
index 45fbabe..79109f4 100644
--- a/src/thumbnail.c
+++ b/src/thumbnail.c
@@ -93,7 +93,6 @@ void init_thumbnail_mode(void)
if (!opt.thumb_title)
opt.thumb_title = "%n";
-
mode = "thumbnail";
if (opt.font)
@@ -177,6 +176,7 @@ void init_thumbnail_mode(void)
td.h + title_area_h, 0, 0, 0, 255);
}
+
if (opt.display) {
winwid = winwidget_create_from_image(td.im_main, WIN_TYPE_THUMBNAIL);
winwidget_rename(winwid, PACKAGE " [thumbnail mode]");
@@ -418,6 +418,7 @@ void init_thumbnail_mode(void)
}
}
+
return;
}
@@ -783,7 +784,6 @@ void feh_thumbnail_show_fullsize(feh_file *thumbfile)
if (!l) {
eprintf("Cannot find %s in filelist, wtf", thumbfile->filename);
}
-
thumbwin = winwidget_get_first_window_of_type(WIN_TYPE_THUMBNAIL_VIEWER);
if (!thumbwin) {
thumbwin = winwidget_create_from_file(
@@ -793,7 +793,13 @@ void feh_thumbnail_show_fullsize(feh_file *thumbfile)
winwidget_show(thumbwin);
} else if (FEH_FILE(thumbwin->file->data) != thumbfile) {
thumbwin->file = l;
- feh_reload_image(thumbwin, 1, 1);
+#ifdef HAVE_INOTIFY
+ winwidget_inotify_remove(thumbwin);
+#endif
+ feh_reload_image(thumbwin, 1, 0);
+#ifdef HAVE_INOTIFY
+ winwidget_inotify_add(thumbwin, thumbfile);
+#endif
}
}
diff --git a/src/winwidget.c b/src/winwidget.c
index f3ecc84..70a65e0 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -30,6 +30,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "options.h"
#include "events.h"
+#ifdef HAVE_INOTIFY
+#include <sys/inotify.h>
+#endif
+
static void winwidget_unregister(winwidget win);
static void winwidget_register(winwidget win);
static winwidget winwidget_allocate(void);
@@ -78,6 +82,10 @@ static winwidget winwidget_allocate(void)
ret->click_offset_y = 0;
ret->has_rotated = 0;
+#ifdef HAVE_INOTIFY
+ ret->inotify_wd = -1;
+#endif
+
return(ret);
}
@@ -662,6 +670,9 @@ void winwidget_destroy_xwin(winwidget winwid)
void winwidget_destroy(winwidget winwid)
{
+#ifdef HAVE_INOTIFY
+ winwidget_inotify_remove(winwid);
+#endif
winwidget_destroy_xwin(winwid);
if (winwid->name)
free(winwid->name);
@@ -673,6 +684,76 @@ void winwidget_destroy(winwidget winwid)
return;
}
+#ifdef HAVE_INOTIFY
+void winwidget_inotify_remove(winwidget winwid)
+{
+ if (winwid->inotify_wd >= 0) {
+ D(("Removing inotify watch\n"));
+ if (inotify_rm_watch(opt.inotify_fd, winwid->inotify_wd))
+ weprintf("inotify_rm_watch failed:");
+ winwid->inotify_wd = -1;
+ }
+}
+#endif
+
+#ifdef HAVE_INOTIFY
+void winwidget_inotify_add(winwidget winwid, feh_file * file)
+{
+ if (opt.auto_reload) {
+ D(("Adding inotify watch for %s\n", file->filename));
+ char dir[PATH_MAX];
+ feh_file_dirname(dir, file, PATH_MAX);
+
+ /*
+ * Handle files without directory part, e.g. "feh somefile.jpg".
+ * These always reside in the current directory.
+ */
+ if (dir[0] == '\0') {
+ dir[0] = '.';
+ dir[1] = '\0';
+ }
+ winwid->inotify_wd = inotify_add_watch(opt.inotify_fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO);
+ if (winwid->inotify_wd < 0)
+ weprintf("inotify_add_watch failed:");
+ }
+}
+#endif
+
+#ifdef HAVE_INOTIFY
+#define INOTIFY_BUFFER_LEN (1024 * (sizeof (struct inotify_event)) + 16)
+void feh_event_handle_inotify(void)
+{
+ D(("Received inotify events\n"));
+ char buf[INOTIFY_BUFFER_LEN];
+ int i = 0;
+ int len = read (opt.inotify_fd, buf, INOTIFY_BUFFER_LEN);
+ if (len < 0) {
+ if (errno != EINTR)
+ eprintf("inotify event read failed");
+ } else if (!len)
+ eprintf("inotify event read failed");
+ while (i < len) {
+ struct inotify_event *event;
+ event = (struct inotify_event *) &buf[i];
+ for (int j = 0; j < window_num; j++) {
+ if(windows[j]->inotify_wd == event->wd) {
+ if (event->mask & IN_IGNORED) {
+ D(("inotify watch was implicitely removed\n"));
+ windows[j]->inotify_wd = -1;
+ } else if (event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) {
+ if (strcmp(event->name, FEH_FILE(windows[j]->file->data)->name) == 0) {
+ D(("inotify says file changed\n"));
+ feh_reload_image(windows[j], 0, 0);
+ }
+ }
+ break;
+ }
+ }
+ i += sizeof(struct inotify_event) + event->len;
+ }
+}
+#endif
+
void winwidget_destroy_all(void)
{
int i;
@@ -706,7 +787,16 @@ winwidget winwidget_get_first_window_of_type(unsigned int type)
int winwidget_loadimage(winwidget winwid, feh_file * file)
{
D(("filename %s\n", file->filename));
- return(feh_load_image(&(winwid->im), file));
+#ifdef HAVE_INOTIFY
+ winwidget_inotify_remove(winwid);
+#endif
+ int res = feh_load_image(&(winwid->im), file);
+#ifdef HAVE_INOTIFY
+ if (res) {
+ winwidget_inotify_add(winwid, file);
+ }
+#endif
+ return(res);
}
void winwidget_show(winwidget winwid)
diff --git a/src/winwidget.h b/src/winwidget.h
index 0a707ac..4d8fc4b 100644
--- a/src/winwidget.h
+++ b/src/winwidget.h
@@ -116,8 +116,17 @@ struct __winwidget {
time_t click_start_time;
unsigned char has_rotated;
+
+#ifdef HAVE_INOTIFY
+ int inotify_wd;
+#endif
};
+#ifdef HAVE_INOTIFY
+void winwidget_inotify_remove(winwidget winwid);
+void winwidget_inotify_add(winwidget winwid, feh_file * file);
+#endif
+
int winwidget_loadimage(winwidget winwid, feh_file * filename);
void winwidget_show(winwidget winwid);
void winwidget_show_menu(winwidget winwid);