"Fossies" - the Fresh Open Source Software Archive

Member "feh-3.4.1/src/main.c" (29 May 2020, 7521 Bytes) of package /linux/privat/feh-3.4.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "main.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.4_vs_3.4.1.

    1 /* main.c
    2 
    3 Copyright (C) 1999-2003 Tom Gilbert.
    4 Copyright (C) 2010-2020 Daniel Friesel.
    5 
    6 Permission is hereby granted, free of charge, to any person obtaining a copy
    7 of this software and associated documentation files (the "Software"), to
    8 deal in the Software without restriction, including without limitation the
    9 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   10 sell copies of the Software, and to permit persons to whom the Software is
   11 furnished to do so, subject to the following conditions:
   12 
   13 The above copyright notice and this permission notice shall be included in
   14 all copies of the Software and its documentation and acknowledgment shall be
   15 given in the documentation and software packages that this Software was
   16 used.
   17 
   18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   21 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   22 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   24 
   25 */
   26 
   27 #include "feh.h"
   28 #include "filelist.h"
   29 #include "winwidget.h"
   30 #include "timers.h"
   31 #include "options.h"
   32 #include "events.h"
   33 #include "signals.h"
   34 #include "wallpaper.h"
   35 #include <termios.h>
   36 
   37 #ifdef HAVE_INOTIFY
   38 #include <sys/inotify.h>
   39 #endif
   40 
   41 char **cmdargv = NULL;
   42 int cmdargc = 0;
   43 char *mode = NULL;
   44 
   45 int main(int argc, char **argv)
   46 {
   47     atexit(feh_clean_exit);
   48 
   49     srandom(getpid() * time(NULL) % ((unsigned int) -1));
   50 
   51     setup_signal_handlers();
   52     init_parse_options(argc, argv);
   53 
   54     init_imlib_fonts();
   55 
   56     if (opt.display) {
   57         init_x_and_imlib();
   58         init_keyevents();
   59         init_buttonbindings();
   60 #ifdef HAVE_INOTIFY
   61         if (opt.auto_reload) {
   62             opt.inotify_fd = inotify_init();
   63             if (opt.inotify_fd < 0) {
   64                 opt.auto_reload = 0;
   65                 weprintf("inotify_init failed:");
   66                 weprintf("Disabling inotify-based auto-reload");
   67             }
   68         }
   69 #endif
   70     }
   71 
   72     feh_event_init();
   73 
   74     if (opt.index)
   75         init_index_mode();
   76     else if (opt.multiwindow)
   77         init_multiwindow_mode();
   78     else if (opt.list || opt.customlist)
   79         init_list_mode();
   80     else if (opt.loadables)
   81         init_loadables_mode();
   82     else if (opt.unloadables)
   83         init_unloadables_mode();
   84     else if (opt.thumbs)
   85         init_thumbnail_mode();
   86     else if (opt.bgmode) {
   87         feh_wm_set_bg_filelist(opt.bgmode);
   88         exit(0);
   89     }
   90     else if (opt.display){
   91         /* Slideshow mode is the default. Because it's spiffy */
   92         opt.slideshow = 1;
   93         init_slideshow_mode();
   94     }
   95     else {
   96         eprintf("Invalid option combination");
   97     }
   98 
   99     /* main event loop */
  100     while (feh_main_iteration(1));
  101 
  102     return(sig_exit);
  103 }
  104 
  105 /* Return 0 to stop iterating, 1 if ok to continue. */
  106 int feh_main_iteration(int block)
  107 {
  108     static int first = 1;
  109     static int xfd = 0;
  110     static int fdsize = 0;
  111     static double pt = 0.0;
  112     XEvent ev;
  113     struct timeval tval;
  114     fd_set fdset;
  115     int count = 0;
  116     double t1 = 0.0, t2 = 0.0;
  117     fehtimer ft;
  118 
  119     if (window_num == 0 || sig_exit != 0)
  120         return(0);
  121 
  122     if (first) {
  123         /* Only need to set these up the first time */
  124         xfd = ConnectionNumber(disp);
  125         fdsize = xfd + 1;
  126         pt = feh_get_time();
  127         first = 0;
  128         /*
  129          * Only accept commands from stdin if
  130          * - stdin is a terminal (otherwise it's probably used as an image / filelist)
  131          * - we aren't running in multiwindow mode (cause it's not clear which
  132          *   window commands should be applied to in that case)
  133          * - we're in the same process group as stdin, AKA we're not running
  134          *   in the background. Background processes are stopped with SIGTTOU
  135          *   if they try to write to stdout or change terminal attributes. They
  136          *   also don't get input from stdin anyway.
  137          */
  138         if (isatty(STDIN_FILENO) && !opt.multiwindow && getpgrp() == (tcgetpgrp(STDIN_FILENO))) {
  139             setup_stdin();
  140         }
  141     }
  142 
  143     /* Timers */
  144     t1 = feh_get_time();
  145     t2 = t1 - pt;
  146     pt = t1;
  147     while (XPending(disp)) {
  148         XNextEvent(disp, &ev);
  149         if (ev_handler[ev.type])
  150             (*(ev_handler[ev.type])) (&ev);
  151 
  152         if (window_num == 0 || sig_exit != 0)
  153             return(0);
  154     }
  155     XFlush(disp);
  156 
  157     feh_redraw_menus();
  158 
  159     FD_ZERO(&fdset);
  160     FD_SET(xfd, &fdset);
  161     if (control_via_stdin)
  162         FD_SET(STDIN_FILENO, &fdset);
  163 #ifdef HAVE_INOTIFY
  164     if (opt.auto_reload) {
  165         FD_SET(opt.inotify_fd, &fdset);
  166         if (opt.inotify_fd >= fdsize)
  167             fdsize = opt.inotify_fd + 1;
  168     }
  169 #endif
  170 
  171     /* Timers */
  172     ft = first_timer;
  173     /* Don't do timers if we're zooming/panning/etc or if we are paused */
  174     if (ft && (opt.mode == MODE_NORMAL) && !opt.paused) {
  175         D(("There are timers in the queue\n"));
  176         if (ft->just_added) {
  177             D(("The first timer has just been added\n"));
  178             D(("ft->in = %f\n", ft->in));
  179             ft->just_added = 0;
  180             t1 = ft->in;
  181         } else {
  182             D(("The first timer was not just added\n"));
  183             t1 = ft->in - t2;
  184             if (t1 < 0.0)
  185                 t1 = 0.0;
  186             ft->in = t1;
  187         }
  188 
  189         XSync(disp, False);
  190         D(("I next need to action a timer in %f seconds\n", t1));
  191         /* Only do a blocking select if there's a timer due, or no events
  192            waiting */
  193         if (t1 == 0.0 || (block && !XPending(disp))) {
  194             tval.tv_sec = (long) t1;
  195             tval.tv_usec = (long) ((t1 - ((double) tval.tv_sec)) * 1000000);
  196             if (tval.tv_sec < 0)
  197                 tval.tv_sec = 0;
  198             if (tval.tv_usec <= 1000)
  199                 tval.tv_usec = 1000;
  200             errno = 0;
  201             D(("Performing blocking select - waiting for timer or event\n"));
  202             count = select(fdsize, &fdset, NULL, NULL, &tval);
  203             if ((count < 0)
  204                     && ((errno == ENOMEM) || (errno == EINVAL)
  205                         || (errno == EBADF)))
  206                 eprintf("Connection to X display lost");
  207             if (count == 0) {
  208                 /* This means the timer is due to be executed. If count was > 0,
  209                    that would mean an X event had woken us, we're not interested
  210                    in that */
  211                 feh_handle_timer();
  212             }
  213             else if ((count > 0) && (FD_ISSET(0, &fdset)))
  214                 feh_event_handle_stdin();
  215 #ifdef HAVE_INOTIFY
  216             else if ((count > 0) && (FD_ISSET(opt.inotify_fd, &fdset)))
  217                 feh_event_handle_inotify();
  218 #endif
  219         }
  220     } else {
  221         /* Don't block if there are events in the queue. That's a bit rude ;-) */
  222         if (block && !XPending(disp)) {
  223             errno = 0;
  224             D(("Performing blocking select - no timers, or zooming\n"));
  225             count = select(fdsize, &fdset, NULL, NULL, NULL);
  226             if ((count < 0)
  227                     && ((errno == ENOMEM) || (errno == EINVAL)
  228                         || (errno == EBADF)))
  229                 eprintf("Connection to X display lost");
  230             else if ((count > 0) && (FD_ISSET(0, &fdset)))
  231                 feh_event_handle_stdin();
  232 #ifdef HAVE_INOTIFY
  233             else if ((count > 0) && (FD_ISSET(opt.inotify_fd, &fdset)))
  234                 feh_event_handle_inotify();
  235 #endif
  236         }
  237     }
  238     if (window_num == 0 || sig_exit != 0)
  239         return(0);
  240     
  241     return(1);
  242 }
  243 
  244 void feh_clean_exit(void)
  245 {
  246     delete_rm_files();
  247 
  248     free(opt.menu_font);
  249 
  250 #ifdef HAVE_INOTIFY
  251     if (opt.auto_reload)
  252         if (close(opt.inotify_fd))
  253             eprintf("inotify close failed");
  254 #endif
  255 
  256     if(disp)
  257         XCloseDisplay(disp);
  258 
  259     /*
  260      * Only restore the old terminal settings if
  261      * - we changed them in the first place
  262      * - stdin still is a terminal (it might have been closed)
  263      * - stdin still belongs to us (we might have been detached from the
  264      *   controlling terminal, in that case we probably shouldn't be messing
  265      *   around with it) <https://github.com/derf/feh/issues/324>
  266      */
  267     if (control_via_stdin && isatty(STDIN_FILENO) && getpgrp() == (tcgetpgrp(STDIN_FILENO)))
  268         restore_stdin();
  269 
  270     if (opt.filelistfile)
  271         feh_write_filelist(filelist, opt.filelistfile);
  272 
  273     return;
  274 }