summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c153
1 files changed, 141 insertions, 12 deletions
diff --git a/src/main.c b/src/main.c
index 8905508..2503773 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,7 @@
/* main.c
Copyright (C) 1999-2003 Tom Gilbert.
+Copyright (C) 2010-2023 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -29,7 +30,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "timers.h"
#include "options.h"
#include "events.h"
-#include "support.h"
+#include "signals.h"
+#include "wallpaper.h"
+#include <termios.h>
+
+#ifdef HAVE_INOTIFY
+#include <sys/inotify.h>
+#endif
char **cmdargv = NULL;
int cmdargc = 0;
@@ -39,19 +46,38 @@ int main(int argc, char **argv)
{
atexit(feh_clean_exit);
+ srandom(getpid() * time(NULL) % ((unsigned int) -1));
+
+ setup_signal_handlers();
+
+#ifdef HAVE_LIBMAGIC
+ init_magic();
+#endif
+
init_parse_options(argc, argv);
init_imlib_fonts();
- if (opt.display)
+ if (opt.display) {
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();
if (opt.index)
init_index_mode();
- else if (opt.collage)
- init_collage_mode();
else if (opt.multiwindow)
init_multiwindow_mode();
else if (opt.list || opt.customlist)
@@ -63,19 +89,44 @@ int main(int argc, char **argv)
else if (opt.thumbs)
init_thumbnail_mode();
else if (opt.bgmode) {
- feh_wm_set_bg_file(opt.output_file, opt.bgmode);
+ feh_wm_set_bg_filelist(opt.bgmode);
exit(0);
}
- else {
+ else if (opt.display){
/* Slideshow mode is the default. Because it's spiffy */
opt.slideshow = 1;
init_slideshow_mode();
}
+ else {
+ eprintf("Invalid option combination");
+ }
/* main event loop */
while (feh_main_iteration(1));
- return(0);
+ return(sig_exit);
+}
+
+static void feh_process_signal(void)
+{
+ winwidget winwid = winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW);
+ int i;
+ int signo = sig_received;
+ sig_received = 0;
+
+ if (winwid) {
+ 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);
+ }
}
/* Return 0 to stop iterating, 1 if ok to continue. */
@@ -92,15 +143,32 @@ int feh_main_iteration(int block)
double t1 = 0.0, t2 = 0.0;
fehtimer ft;
- if (window_num == 0)
+ if (window_num == 0 || sig_exit != 0)
return(0);
+ if (sig_received) {
+ feh_process_signal();
+ }
+
if (first) {
/* Only need to set these up the first time */
xfd = ConnectionNumber(disp);
fdsize = xfd + 1;
pt = feh_get_time();
first = 0;
+ /*
+ * Only accept commands from stdin if
+ * - stdin is a terminal (otherwise it's probably used as an image / filelist)
+ * - we aren't running in multiwindow mode (cause it's not clear which
+ * window commands should be applied to in that case)
+ * - we're in the same process group as stdin, AKA we're not running
+ * in the background. Background processes are stopped with SIGTTOU
+ * if they try to write to stdout or change terminal attributes. They
+ * also don't get input from stdin anyway.
+ */
+ if (isatty(STDIN_FILENO) && !opt.multiwindow && getpgrp() == (tcgetpgrp(STDIN_FILENO))) {
+ setup_stdin();
+ }
}
/* Timers */
@@ -112,8 +180,12 @@ int feh_main_iteration(int block)
if (ev_handler[ev.type])
(*(ev_handler[ev.type])) (&ev);
- if (window_num == 0)
+ if (window_num == 0 || sig_exit != 0)
return(0);
+
+ if (sig_received) {
+ feh_process_signal();
+ }
}
XFlush(disp);
@@ -121,6 +193,16 @@ int feh_main_iteration(int block)
FD_ZERO(&fdset);
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;
@@ -158,12 +240,23 @@ int feh_main_iteration(int block)
&& ((errno == ENOMEM) || (errno == EINVAL)
|| (errno == EBADF)))
eprintf("Connection to X display lost");
- if ((ft) && (count == 0)) {
+ if (count == 0) {
/* This means the timer is due to be executed. If count was > 0,
that would mean an X event had woken us, we're not interested
in that */
feh_handle_timer();
}
+ /*
+ * Beware: If stdin is not connected, we may end up with xfd == 0.
+ * However, STDIN_FILENO == 0 holds as well in most cases. So we must
+ * check control_via_stdin to avoid mistaking an X11 event for stdin.
+ */
+ else if ((count > 0) && control_via_stdin && (FD_ISSET(STDIN_FILENO, &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 ;-) */
@@ -175,11 +268,21 @@ int feh_main_iteration(int block)
&& ((errno == ENOMEM) || (errno == EINVAL)
|| (errno == EBADF)))
eprintf("Connection to X display lost");
+ else if ((count > 0) && control_via_stdin && (FD_ISSET(STDIN_FILENO, &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)
+ if (window_num == 0 || sig_exit != 0)
return(0);
-
+
+ if (sig_received) {
+ feh_process_signal();
+ }
+
return(1);
}
@@ -187,6 +290,32 @@ void feh_clean_exit(void)
{
delete_rm_files();
+ 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);
+
+#ifdef HAVE_LIBMAGIC
+ uninit_magic();
+#endif
+
+ /*
+ * Only restore the old terminal settings if
+ * - we changed them in the first place
+ * - stdin still is a terminal (it might have been closed)
+ * - stdin still belongs to us (we might have been detached from the
+ * controlling terminal, in that case we probably shouldn't be messing
+ * around with it) <https://github.com/derf/feh/issues/324>
+ */
+ if (control_via_stdin && isatty(STDIN_FILENO) && getpgrp() == (tcgetpgrp(STDIN_FILENO)))
+ restore_stdin();
+
if (opt.filelistfile)
feh_write_filelist(filelist, opt.filelistfile);