"Fossies" - the Fresh Open Source Software Archive

Member "feh-3.4.1/src/menu.c" (29 May 2020, 37554 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 "menu.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 /* menu.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 "thumbnail.h"
   29 #include "wallpaper.h"
   30 #include "winwidget.h"
   31 #include "filelist.h"
   32 #include "options.h"
   33 
   34 Window menu_cover = 0;
   35 feh_menu *menu_root = NULL;
   36 feh_menu *menu_main = NULL;
   37 feh_menu *menu_single_win = NULL;
   38 feh_menu *menu_thumbnail_viewer = NULL;
   39 feh_menu *menu_thumbnail_win = NULL;
   40 feh_menu *menu_bg = NULL;
   41 static feh_menu_list *menus = NULL;
   42 static int common_menus = 0;
   43 
   44 static feh_menu *feh_menu_func_gen_info(feh_menu * m);
   45 static void feh_menu_func_free_info(feh_menu * m);
   46 static void feh_menu_func_free_options(feh_menu * m);
   47 static feh_menu *feh_menu_func_gen_options(feh_menu * m);
   48 void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, unsigned short data);
   49 void feh_menu_cb_opt_fullscreen(feh_menu * m, feh_menu_item * i);
   50 
   51 enum {
   52     CB_CLOSE = 1,
   53     CB_EXIT,
   54     CB_RELOAD,
   55     CB_REMOVE,
   56     CB_DELETE,
   57     CB_RESET,
   58     CB_REMOVE_THUMB,
   59     CB_DELETE_THUMB,
   60     CB_BG_TILED,
   61     CB_BG_SCALED,
   62     CB_BG_CENTERED,
   63     CB_BG_FILLED,
   64     CB_BG_TILED_NOFILE,
   65     CB_BG_SCALED_NOFILE,
   66     CB_BG_CENTERED_NOFILE,
   67     CB_BG_FILLED_NOFILE,
   68     CB_SORT_FILENAME,
   69     CB_SORT_IMAGENAME,
   70     CB_SORT_DIRNAME,
   71     CB_SORT_MTIME,
   72     CB_SORT_FILESIZE,
   73     CB_SORT_RANDOMIZE,
   74     CB_SAVE_IMAGE,
   75     CB_SAVE_FILELIST,
   76     CB_FIT,
   77     CB_OPT_DRAW_FILENAME,
   78     CB_OPT_DRAW_ACTIONS,
   79     CB_OPT_KEEP_HTTP,
   80     CB_OPT_FREEZE_WINDOW,
   81     CB_OPT_FULLSCREEN,
   82     CB_EDIT_ROTATE,
   83     CB_OPT_AUTO_ZOOM,
   84     CB_OPT_KEEP_ZOOM_VP
   85 };
   86 
   87 feh_menu *feh_menu_new(void)
   88 {
   89     feh_menu *m;
   90     XSetWindowAttributes attr;
   91     feh_menu_list *l;
   92     static Imlib_Image bg = NULL;
   93     static Imlib_Border border;
   94 
   95     m = (feh_menu *) emalloc(sizeof(feh_menu));
   96 
   97     attr.backing_store = NotUseful;
   98     attr.override_redirect = True;
   99     attr.colormap = cm;
  100     attr.border_pixel = 0;
  101     attr.background_pixmap = None;
  102     attr.save_under = False;
  103     attr.do_not_propagate_mask = True;
  104 
  105     m->win = XCreateWindow(
  106             disp, root, 1, 1, 1, 1, 0, depth, InputOutput, vis,
  107             CWOverrideRedirect | CWSaveUnder | CWBackingStore
  108             | CWColormap | CWBackPixmap | CWBorderPixel | CWDontPropagate, &attr);
  109     XSelectInput(disp, m->win,
  110             ButtonPressMask | ButtonReleaseMask | EnterWindowMask
  111             | LeaveWindowMask | PointerMotionMask | ButtonMotionMask);
  112 
  113     m->name = NULL;
  114     m->fehwin = NULL;
  115     m->pmap = 0;
  116     m->x = 0;
  117     m->y = 0;
  118     m->w = 0;
  119     m->h = 0;
  120     m->visible = 0;
  121     m->items = NULL;
  122     m->next = NULL;
  123     m->prev = NULL;
  124     m->updates = NULL;
  125     m->needs_redraw = 1;
  126     m->func_free = NULL;
  127     m->data = 0;
  128     m->calc = 0;
  129     m->bg = NULL;
  130 
  131     l = emalloc(sizeof(feh_menu_list));
  132     l->menu = m;
  133     l->next = menus;
  134     menus = l;
  135 
  136     if (!bg) {
  137         feh_load_image_char(&bg, PREFIX "/share/feh/images/menubg_default.png");
  138         if (bg) {
  139             border.left = border.right = border.top = border.bottom
  140                 = 4;
  141             imlib_context_set_image(bg);
  142             imlib_image_set_border(&border);
  143         }
  144     }
  145 
  146     if (bg)
  147         m->bg = gib_imlib_clone_image(bg);
  148 
  149     return(m);
  150 }
  151 
  152 void feh_menu_free(feh_menu * m)
  153 {
  154     feh_menu_item *i;
  155     feh_menu_list *l, *pl = NULL;
  156 
  157     if (m->name)
  158         free(m->name);
  159     XDestroyWindow(disp, m->win);
  160     if (m->pmap)
  161         XFreePixmap(disp, m->pmap);
  162     if (m->updates)
  163         imlib_updates_free(m->updates);
  164     for (i = m->items; i;) {
  165         feh_menu_item *ii;
  166 
  167         ii = i;
  168         i = i->next;
  169         if (ii->text)
  170             free(ii->text);
  171         if (ii->submenu)
  172             free(ii->submenu);
  173         free(ii);
  174     }
  175 
  176     for (l = menus; l; l = l->next) {
  177         if (l->menu == m) {
  178             if (pl)
  179                 pl->next = l->next;
  180             else
  181                 menus = l->next;
  182             free(l);
  183             break;
  184         }
  185         pl = l;
  186     }
  187     if (m->bg)
  188         gib_imlib_free_image_and_decache(m->bg);
  189 
  190     free(m);
  191 
  192     return;
  193 }
  194 
  195 feh_menu_item *feh_menu_find_selected(feh_menu * m)
  196 {
  197     feh_menu_item *i;
  198 
  199     D(("menu %p\n", m));
  200 
  201     for (i = m->items; i; i = i->next) {
  202         if (MENU_ITEM_IS_SELECTED(i))
  203             return(i);
  204     }
  205     return(NULL);
  206 }
  207 
  208 feh_menu_item *feh_menu_find_selected_r(feh_menu * m, feh_menu ** parent)
  209 {
  210     feh_menu_item *i, *ii;
  211     feh_menu *mm;
  212 
  213     D(("menu %p\n", m));
  214 
  215     for (i = m->items; i; i = i->next) {
  216         if (MENU_ITEM_IS_SELECTED(i)) {
  217             if (parent)
  218                 *parent = m;
  219             return(i);
  220         } else if (i->submenu) {
  221             mm = feh_menu_find(i->submenu);
  222             if (mm) {
  223                 ii = feh_menu_find_selected_r(mm, parent);
  224                 if (ii)
  225                     return(ii);
  226             }
  227         }
  228     }
  229     if (parent)
  230         *parent = m;
  231     return(NULL);
  232 }
  233 
  234 void feh_menu_select_next(feh_menu * selected_menu, feh_menu_item * selected_item)
  235 {
  236     feh_menu_item *i;
  237     if (!selected_item) {
  238         /* jump to first item, select it */
  239         feh_menu_select(selected_menu, selected_menu->items);
  240     } else {
  241         i = selected_item;
  242         while (1) {
  243             i = i->next;
  244             if (!i)
  245                 i = selected_menu->items;
  246             if (i->action || i->submenu || i->func_gen_sub || i->text) {
  247                 break;
  248             }
  249         }
  250         feh_menu_deselect_selected(selected_menu);
  251         feh_menu_select(selected_menu, i);
  252     }
  253 }
  254 
  255 void feh_menu_select_prev(feh_menu * selected_menu, feh_menu_item * selected_item)
  256 {
  257     feh_menu_item *i, *ii;
  258     if (!selected_item) {
  259         /* jump to last item, select it */
  260         for (i = selected_menu->items; i->next; i = i->next);
  261         feh_menu_select(selected_menu, i);
  262     } else {
  263         i = selected_item;
  264         while (1) {
  265             i = i->prev;
  266             if (!i) {
  267                 for (ii = selected_menu->items; ii->next; ii = ii->next);
  268                 i = ii;
  269             }
  270             if (i->action || i->submenu || i->func_gen_sub || i->text) {
  271                 break;
  272             }
  273         }
  274         feh_menu_deselect_selected(selected_menu);
  275         feh_menu_select(selected_menu, i);
  276     }
  277 }
  278 
  279 void feh_menu_select_parent(feh_menu * selected_menu)
  280 {
  281     feh_menu *m;
  282     feh_menu_item *i;
  283     /* find the parent menu's item which refers to this menu's name */
  284     if (selected_menu->prev) {
  285         m = selected_menu->prev;
  286         for (i = m->items; i; i = i->next) {
  287             if (i->submenu && !strcmp(i->submenu, selected_menu->name))
  288                 break;
  289         }
  290         /* shouldn't ever happen */
  291         if (i == NULL)
  292             i = m->items;
  293         feh_menu_deselect_selected(selected_menu);
  294         feh_menu_select(m, i);
  295     }
  296 }
  297 
  298 void feh_menu_select_submenu(feh_menu * selected_menu)
  299 {
  300     if (selected_menu->next) {
  301         feh_menu_deselect_selected(selected_menu);
  302         feh_menu_select(selected_menu->next, selected_menu->next->items);
  303     }
  304 }
  305 
  306 void feh_menu_item_activate(feh_menu * m, feh_menu_item * i)
  307 {
  308     /* watch out for this. I put it this way around so the menu
  309        goes away *before* we perform the action, if we start
  310        freeing menus on hiding, it will break ;-) */
  311     if ((i) && (i->action)) {
  312         feh_menu_hide(menu_root, False);
  313         feh_main_iteration(0);
  314         feh_menu_cb(m, i, i->action, i->data);
  315         if (m->func_free)
  316             m->func_free(m);
  317     }
  318 }
  319 
  320 feh_menu_item *feh_menu_find_at_xy(feh_menu * m, int x, int y)
  321 {
  322     feh_menu_item *i;
  323 
  324     D(("looking for menu item at %d,%d\n", x, y));
  325     for (i = m->items; i; i = i->next) {
  326         if (XY_IN_RECT(x, y, i->x, i->y, i->w, i->h)) {
  327             D(("Found an item\n"));
  328             return(i);
  329         }
  330     }
  331     D(("didn't find an item\n"));
  332     return(NULL);
  333 }
  334 
  335 void feh_menu_deselect_selected(feh_menu * m)
  336 {
  337     feh_menu_item *i;
  338 
  339     if (!m)
  340         return;
  341 
  342     i = feh_menu_find_selected(m);
  343     if (i) {
  344         D(("found a selected menu, deselecting it\n"));
  345         MENU_ITEM_SET_NORMAL(i);
  346         m->updates = imlib_update_append_rect(m->updates, i->x, i->y, i->w, i->h);
  347         m->needs_redraw = 1;
  348     }
  349     return;
  350 }
  351 
  352 void feh_menu_select(feh_menu * m, feh_menu_item * i)
  353 {
  354     MENU_ITEM_SET_SELECTED(i);
  355     m->updates = imlib_update_append_rect(m->updates, i->x, i->y, i->w, i->h);
  356     m->needs_redraw = 1;
  357     if (m->next) {
  358         m->next->prev = NULL;
  359         feh_menu_hide(m->next, TRUE);
  360         m->next = NULL;
  361     }
  362     if (i->submenu) {
  363         feh_menu *mm;
  364 
  365         mm = feh_menu_find(i->submenu);
  366         if (mm)
  367             feh_menu_show_at_submenu(mm, m, i);
  368         else if (i->func_gen_sub)
  369             feh_menu_show_at_submenu(i->func_gen_sub(m), m, i);
  370     }
  371     return;
  372 }
  373 
  374 void feh_menu_show_at(feh_menu * m, int x, int y)
  375 {
  376     if (m->calc)
  377         feh_menu_calc_size(m);
  378     if (!menu_cover) {
  379         XSetWindowAttributes attr;
  380 
  381         D(("creating menu cover window\n"));
  382         attr.override_redirect = True;
  383         attr.do_not_propagate_mask = True;
  384         menu_cover = XCreateWindow(
  385                 disp, root, 0, 0, scr->width,
  386                 scr->height, 0, 0, InputOnly, vis,
  387                 CWOverrideRedirect | CWDontPropagate, &attr);
  388         XSelectInput(disp, menu_cover,
  389                 KeyPressMask | ButtonPressMask |
  390                 ButtonReleaseMask | EnterWindowMask |
  391                 LeaveWindowMask | PointerMotionMask | ButtonMotionMask);
  392 
  393         XRaiseWindow(disp, menu_cover);
  394         XMapWindow(disp, menu_cover);
  395         menu_root = m;
  396         XUngrabPointer(disp, CurrentTime);
  397         XSetInputFocus(disp, menu_cover, RevertToPointerRoot, CurrentTime);
  398     }
  399     m->visible = 1;
  400     XMoveWindow(disp, m->win, x, y);
  401     m->x = x;
  402     m->y = y;
  403     XRaiseWindow(disp, m->win);
  404     feh_menu_redraw(m);
  405     XMapWindow(disp, m->win);
  406     return;
  407 }
  408 
  409 void feh_menu_show_at_xy(feh_menu * m, winwidget winwid, int x, int y)
  410 {
  411     if (!m)
  412         return;
  413 
  414     if (m->calc)
  415         feh_menu_calc_size(m);
  416     m->fehwin = winwid;
  417     if ((x + m->w) > scr->width)
  418         x = scr->width - m->w;
  419     if ((y + m->h) > scr->height)
  420         y = scr->height - m->h;
  421 
  422 #if 0
  423 /* #ifdef HAVE_LIBXINERAMA */
  424 /* this doesn't work correctly :( -- pabs */
  425     if (opt.xinerama && xinerama_screens) {
  426         if ((x + m->w) > xinerama_screens[xinerama_screen].width)
  427             x = xinerama_screens[xinerama_screen].width - m->w;
  428         if ((y + m->h) > xinerama_screens[xinerama_screen].height)
  429             y = xinerama_screens[xinerama_screen].height - m->h;
  430 
  431     }
  432 #endif              /* HAVE_LIBXINERAMA */
  433 
  434     if (x < 0)
  435         x = 0;
  436     if (y < 0)
  437         y = 0;
  438     feh_menu_move(m, x, y);
  439     feh_menu_show(m);
  440     return;
  441 }
  442 
  443 void feh_menu_show_at_submenu(feh_menu * m, feh_menu * parent_m, feh_menu_item * i)
  444 {
  445     int mx, my;
  446 
  447     if (!m)
  448         return;
  449 
  450     if (m->calc)
  451         feh_menu_calc_size(m);
  452     mx = parent_m->x + parent_m->w;
  453     my = parent_m->y + i->y - FEH_MENU_PAD_TOP;
  454     m->fehwin = parent_m->fehwin;
  455     parent_m->next = m;
  456     m->prev = parent_m;
  457     feh_menu_move(m, mx, my);
  458     feh_menu_show(m);
  459     return;
  460 }
  461 
  462 void feh_menu_move(feh_menu * m, int x, int y)
  463 {
  464     if (!m)
  465         return;
  466 
  467     if (m->visible)
  468         XMoveWindow(disp, m->win, x, y);
  469 
  470     m->x = x;
  471     m->y = y;
  472     return;
  473 }
  474 
  475 void feh_menu_slide_all_menus_relative(int dx, int dy)
  476 {
  477     int i;
  478     feh_menu_list *m;
  479     double vector_len = 0;
  480     int stepx = 0;
  481     int stepy = 0;
  482 
  483     vector_len = sqrt(dx * dx + dy * dy);
  484     if (vector_len) {
  485         if (dx)
  486             stepx = rint(dx / vector_len);
  487 
  488         if (dy)
  489             stepy = rint(dy / vector_len);
  490 
  491     }
  492     for (i = 0; i < vector_len; i++) {
  493         for (m = menus; m; m = m->next) {
  494             if (m->menu->visible)
  495                 feh_menu_move(m->menu, m->menu->x + stepx, m->menu->y + stepy);
  496 
  497         }
  498         XWarpPointer(disp, None, None, 0, 0, 0, 0, stepx, stepy);
  499     }
  500     return;
  501 }
  502 
  503 void feh_menu_hide(feh_menu * m, int func_free)
  504 {
  505     if (!m->visible)
  506         return;
  507     if (m->next) {
  508         m->next->prev = NULL;
  509         feh_menu_hide(m->next, func_free);
  510         m->next = NULL;
  511     }
  512     if (m == menu_root) {
  513         if (menu_cover) {
  514             D(("DESTROYING menu cover\n"));
  515             XDestroyWindow(disp, menu_cover);
  516             menu_cover = 0;
  517         }
  518         menu_root = NULL;
  519     }
  520     m->visible = 0;
  521     XUnmapWindow(disp, m->win);
  522     if (func_free && m->func_free)
  523         m->func_free(m);
  524     else
  525         feh_menu_deselect_selected(m);
  526     return;
  527 }
  528 
  529 void feh_menu_show(feh_menu * m)
  530 {
  531     if (!m)
  532         return;
  533     feh_menu_show_at(m, m->x, m->y);
  534     return;
  535 }
  536 
  537 feh_menu_item *feh_menu_add_toggle_entry(feh_menu * m, char *text,
  538         char *submenu, int action,
  539         unsigned short data, void (*func_free) (void *data), int setting)
  540 {
  541     feh_menu_item *mi;
  542 
  543     mi = feh_menu_add_entry(m, text, submenu, action, data, func_free);
  544     mi->is_toggle = TRUE;
  545     MENU_ITEM_TOGGLE_SET(mi, setting);
  546     return(mi);
  547 }
  548 
  549 feh_menu_item *feh_menu_add_entry(feh_menu * m, char *text, char *submenu,
  550     int action, unsigned short data, void (*func_free) (void *data))
  551 {
  552     feh_menu_item *mi, *ptr;
  553 
  554 
  555     mi = (feh_menu_item *) emalloc(sizeof(feh_menu_item));
  556     mi->state = MENU_ITEM_STATE_NORMAL;
  557     mi->is_toggle = FALSE;
  558     if (text)
  559         mi->text = estrdup(text);
  560     else
  561         mi->text = NULL;
  562     if (submenu)
  563         mi->submenu = estrdup(submenu);
  564     else
  565         mi->submenu = NULL;
  566     mi->action = action;
  567     mi->func_free = func_free;
  568     mi->data = data;
  569     mi->func_gen_sub = NULL;
  570     mi->next = NULL;
  571     mi->prev = NULL;
  572 
  573     if (!m->items)
  574         m->items = mi;
  575     else {
  576         for (ptr = m->items; ptr; ptr = ptr->next) {
  577             if (!ptr->next) {
  578                 ptr->next = mi;
  579                 mi->prev = ptr;
  580                 break;
  581             }
  582         }
  583     }
  584     m->calc = 1;
  585     return(mi);
  586 }
  587 
  588 void feh_menu_entry_get_size(feh_menu_item * i, int *w, int *h)
  589 {
  590     int tw, th;
  591 
  592     if (i->text) {
  593         gib_imlib_get_text_size(opt.menu_fn, i->text, NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT);
  594         *w = tw + FEH_MENUITEM_PAD_LEFT + FEH_MENUITEM_PAD_RIGHT;
  595         *h = th + FEH_MENUITEM_PAD_TOP + FEH_MENUITEM_PAD_BOTTOM;
  596     } else {
  597         *w = FEH_MENUITEM_PAD_LEFT + FEH_MENUITEM_PAD_RIGHT;
  598         *h = FEH_MENUITEM_PAD_TOP + FEH_MENUITEM_PAD_BOTTOM;
  599     }
  600 
  601     return;
  602 }
  603 
  604 void feh_menu_calc_size(feh_menu * m)
  605 {
  606     int prev_w, prev_h;
  607     feh_menu_item *i;
  608     int j = 0, count = 0, max_w = 0, max_h = 0, next_w = 0;
  609     int toggle_w = 1;
  610 
  611     prev_w = m->w;
  612     prev_h = m->h;
  613     m->calc = 0;
  614 
  615     for (i = m->items; i; i = i->next) {
  616         int w, h;
  617 
  618         feh_menu_entry_get_size(i, &w, &h);
  619         if (w > max_w)
  620             max_w = w;
  621         if (h > max_h)
  622             max_h = h;
  623         if (i->submenu) {
  624             next_w = FEH_MENU_SUBMENU_W;
  625             if (FEH_MENU_SUBMENU_H > max_h)
  626                 max_h = FEH_MENU_SUBMENU_H;
  627         }
  628         if (i->is_toggle) {
  629             toggle_w = FEH_MENU_TOGGLE_W + FEH_MENU_TOGGLE_PAD;
  630             if (FEH_MENU_TOGGLE_H > max_h)
  631                 max_h = FEH_MENU_TOGGLE_H;
  632         }
  633         count++;
  634     }
  635 
  636     m->h = FEH_MENU_PAD_TOP;
  637     for (i = m->items; i; i = i->next) {
  638         i->x = FEH_MENU_PAD_LEFT;
  639         i->y = m->h;
  640         i->w = max_w + toggle_w + next_w;
  641         i->toggle_x = 1;
  642         i->text_x = i->toggle_x + toggle_w;
  643         i->sub_x = i->text_x + max_w;
  644         if (i->text)
  645             i->h = max_h;
  646         else
  647             i->h = FEH_MENU_SEP_MAX_H;
  648         m->h += i->h;
  649         j++;
  650     }
  651     m->h += FEH_MENU_PAD_BOTTOM;
  652     m->w = next_w + toggle_w + max_w + FEH_MENU_PAD_LEFT + FEH_MENU_PAD_RIGHT;
  653 
  654     if ((prev_w != m->w) || (prev_h != m->h)) {
  655         if (m->pmap)
  656             XFreePixmap(disp, m->pmap);
  657         m->pmap = 0;
  658         m->needs_redraw = 1;
  659         XResizeWindow(disp, m->win, m->w, m->h);
  660         m->updates = imlib_update_append_rect(m->updates, 0, 0, m->w, m->h);
  661     }
  662     D(("menu size calculated. w=%d h=%d\n", m->w, m->h));
  663 
  664     /* Make sure bg is same size */
  665     if (m->bg) {
  666         int bg_w, bg_h;
  667 
  668         bg_w = gib_imlib_image_get_width(m->bg);
  669         bg_h = gib_imlib_image_get_height(m->bg);
  670 
  671         if (m->w != bg_w || m->h != bg_h) {
  672             Imlib_Image newim = imlib_create_image(m->w, m->h);
  673 
  674             D(("resizing bg to %dx%d\n", m->w, m->h));
  675 
  676             gib_imlib_blend_image_onto_image(newim, m->bg, 0, 0, 0, bg_w, bg_h, 0, 0, m->w, m->h, 0, 0, 1);
  677             gib_imlib_free_image_and_decache(m->bg);
  678             m->bg = newim;
  679         }
  680     }
  681 
  682     return;
  683 }
  684 
  685 void feh_menu_draw_item(feh_menu_item * i, Imlib_Image im, int ox, int oy)
  686 {
  687     D(("drawing item %p (text %s)\n", i, i->text));
  688 
  689     if (i->text) {
  690         D(("text item\n"));
  691         if (MENU_ITEM_IS_SELECTED(i)) {
  692             D(("selected item\n"));
  693             /* draw selected image */
  694             feh_menu_item_draw_at(i->x, i->y, i->w, i->h, im, ox, oy, 1);
  695         } else {
  696             D(("unselected item\n"));
  697             /* draw unselected image */
  698             feh_menu_item_draw_at(i->x, i->y, i->w, i->h, im, ox, oy, 0);
  699         }
  700 
  701         /* draw text */
  702         gib_imlib_text_draw(im, opt.menu_fn, NULL,
  703                 i->x - ox + i->text_x, i->y - oy + FEH_MENUITEM_PAD_TOP,
  704                 i->text, IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255);
  705         if (i->submenu) {
  706             D(("submenu item\n"));
  707             feh_menu_draw_submenu_at(i->x + i->sub_x,
  708                          i->y +
  709                          FEH_MENUITEM_PAD_TOP +
  710                          ((i->h -
  711                            FEH_MENUITEM_PAD_TOP -
  712                            FEH_MENUITEM_PAD_BOTTOM
  713                            -
  714                            FEH_MENU_SUBMENU_H) /
  715                           2), im, ox, oy);
  716         }
  717         if (i->is_toggle) {
  718             D(("toggleable item\n"));
  719             feh_menu_draw_toggle_at(i->x + i->toggle_x,
  720                         i->y +
  721                         FEH_MENUITEM_PAD_TOP +
  722                         ((i->h -
  723                           FEH_MENUITEM_PAD_TOP -
  724                           FEH_MENUITEM_PAD_BOTTOM -
  725                           FEH_MENU_TOGGLE_H) / 2),
  726                         FEH_MENU_TOGGLE_W, FEH_MENU_TOGGLE_H, im, ox, oy, MENU_ITEM_IS_ON(i));
  727         }
  728     } else {
  729         D(("separator item\n"));
  730         feh_menu_draw_separator_at(i->x, i->y, i->w, i->h, im, ox, oy);
  731     }
  732     return;
  733 }
  734 
  735 void feh_menu_redraw(feh_menu * m)
  736 {
  737     Imlib_Updates u, uu;
  738 
  739     if ((!m->needs_redraw) || (!m->visible) || (!m->updates))
  740         return;
  741     m->needs_redraw = 0;
  742     if (!m->pmap)
  743         m->pmap = XCreatePixmap(disp, m->win, m->w, m->h, depth);
  744     XSetWindowBackgroundPixmap(disp, m->win, m->pmap);
  745 
  746     u = imlib_updates_merge_for_rendering(m->updates, m->w, m->h);
  747     m->updates = NULL;
  748     if (u) {
  749         D(("I have updates to render\n"));
  750         for (uu = u; u; u = imlib_updates_get_next(u)) {
  751             int x, y, w, h;
  752             Imlib_Image im;
  753 
  754             imlib_updates_get_coordinates(u, &x, &y, &w, &h);
  755             D(("update coords %d,%d %d*%d\n", x, y, w, h));
  756             im = imlib_create_image(w, h);
  757             gib_imlib_image_fill_rectangle(im, 0, 0, w, h, 0, 0, 0, 0);
  758             if (im) {
  759                 feh_menu_draw_to_buf(m, im, x, y);
  760                 gib_imlib_render_image_on_drawable(m->pmap, im, x, y, 1, 0, 0);
  761                 gib_imlib_free_image(im);
  762                 XClearArea(disp, m->win, x, y, w, h, False);
  763             }
  764         }
  765         imlib_updates_free(uu);
  766     }
  767     return;
  768 }
  769 
  770 feh_menu *feh_menu_find(char *name)
  771 {
  772     feh_menu_list *l;
  773 
  774     for (l = menus; l; l = l->next) {
  775         if ((l->menu->name) && (!strcmp(l->menu->name, name)))
  776             return(l->menu);
  777     }
  778     return(NULL);
  779 }
  780 
  781 void feh_menu_draw_to_buf(feh_menu * m, Imlib_Image im, int ox, int oy)
  782 {
  783     feh_menu_item *i;
  784     int w, h;
  785 
  786     w = gib_imlib_image_get_width(im);
  787     h = gib_imlib_image_get_height(im);
  788 
  789     feh_menu_draw_menu_bg(m, im, ox, oy);
  790 
  791     for (i = m->items; i; i = i->next) {
  792         if (RECTS_INTERSECT(i->x, i->y, i->w, i->h, ox, oy, w, h))
  793             feh_menu_draw_item(i, im, ox, oy);
  794     }
  795     return;
  796 }
  797 
  798 void feh_menu_draw_menu_bg(feh_menu * m, Imlib_Image im, int ox, int oy)
  799 {
  800     int w, h;
  801 
  802     w = gib_imlib_image_get_width(im);
  803     h = gib_imlib_image_get_height(im);
  804 
  805     if (m->bg)
  806         gib_imlib_blend_image_onto_image(im, m->bg, 0, ox, oy, w, h, 0, 0, w, h, 0, 0, 0);
  807     else
  808         gib_imlib_image_fill_rectangle(im, 0, 0, w, h, 205, 203, 176, 255);
  809 
  810     return;
  811 }
  812 
  813 void feh_menu_draw_toggle_at(int x, int y, int w, int h, Imlib_Image dst, int ox, int oy, int on)
  814 {
  815     x -= ox;
  816     y -= oy;
  817     if (on)
  818         gib_imlib_image_fill_rectangle(dst, x, y, w, h, 0, 0, 0, 255);
  819     else
  820         gib_imlib_image_draw_rectangle(dst, x, y, w, h, 0, 0, 0, 255);
  821     return;
  822 }
  823 
  824 void feh_menu_draw_submenu_at(int x, int y, Imlib_Image dst, int ox, int oy)
  825 {
  826     ImlibPolygon poly;
  827 
  828     x -= ox;
  829     y -= oy;
  830 
  831     imlib_context_set_image(dst);
  832 
  833     poly = imlib_polygon_new();
  834     imlib_polygon_add_point(poly, x, y + 3);
  835     imlib_polygon_add_point(poly, x + 3, y + 6);
  836     imlib_polygon_add_point(poly, x, y + 9);
  837     imlib_context_set_color(0, 0, 0, 255);
  838     imlib_image_fill_polygon(poly);
  839     imlib_polygon_free(poly);
  840 
  841     return;
  842 }
  843 
  844 void feh_menu_draw_separator_at(int x, int y, int w, int h, Imlib_Image dst, int ox, int oy)
  845 {
  846     gib_imlib_image_fill_rectangle(dst, x - ox + 2, y - oy + 2, w - 4, h - 4, 0, 0, 0, 255);
  847     return;
  848 }
  849 
  850 void feh_menu_item_draw_at(int x, int y, int w, int h, Imlib_Image dst, int ox, int oy, int selected)
  851 {
  852     imlib_context_set_image(dst);
  853     if (selected)
  854         gib_imlib_image_fill_rectangle(dst, x - ox, y - oy, w, h, 127, 127, 127, 178);
  855     return;
  856 }
  857 
  858 void feh_raise_all_menus(void)
  859 {
  860     feh_menu_list *l;
  861 
  862     for (l = menus; l; l = l->next) {
  863         if (l->menu->visible)
  864             XRaiseWindow(disp, l->menu->win);
  865     }
  866     return;
  867 }
  868 
  869 void feh_redraw_menus(void)
  870 {
  871     feh_menu_list *l;
  872 
  873     for (l = menus; l; l = l->next) {
  874         if (l->menu->needs_redraw)
  875             feh_menu_redraw(l->menu);
  876     }
  877 
  878     return;
  879 }
  880 
  881 feh_menu *feh_menu_get_from_window(Window win)
  882 {
  883     feh_menu_list *l;
  884 
  885     for (l = menus; l; l = l->next)
  886         if (l->menu->win == win)
  887             return(l->menu);
  888     return(NULL);
  889 }
  890 
  891 void feh_menu_init_main(void)
  892 {
  893     feh_menu *m;
  894     feh_menu_item *mi;
  895 
  896     if (!common_menus)
  897         feh_menu_init_common();
  898 
  899     menu_main = feh_menu_new();
  900     menu_main->name = estrdup("MAIN");
  901 
  902     feh_menu_add_entry(menu_main, "File", "FILE", 0, 0, NULL);
  903     if (opt.slideshow || opt.multiwindow) {
  904         feh_menu_add_entry(menu_main, "Sort List", "SORT", 0, 0, NULL);
  905         mi = feh_menu_add_entry(menu_main, "Image Info", "INFO", 0, 0, NULL);
  906         mi->func_gen_sub = feh_menu_func_gen_info;
  907         feh_menu_add_entry(menu_main, NULL, NULL, 0, 0, NULL);
  908     }
  909     mi = feh_menu_add_entry(menu_main, "Options", "OPTIONS", 0, 0, NULL);
  910     mi->func_gen_sub = feh_menu_func_gen_options;
  911 
  912     if (opt.multiwindow)
  913         feh_menu_add_entry(menu_main, "Close", NULL, CB_CLOSE, 0, NULL);
  914     feh_menu_add_entry(menu_main, "Exit", NULL, CB_EXIT, 0, NULL);
  915 
  916     m = feh_menu_new();
  917     m->name = estrdup("FILE");
  918     feh_menu_add_entry(m, "Reset", NULL, CB_RESET, 0, NULL);
  919     feh_menu_add_entry(m, "Resize Window", NULL, CB_FIT, 0, NULL);
  920     feh_menu_add_entry(m, "Reload", NULL, CB_RELOAD, 0, NULL);
  921     feh_menu_add_entry(m, "Save Image", NULL, CB_SAVE_IMAGE, 0, NULL);
  922     feh_menu_add_entry(m, "Save List", NULL, CB_SAVE_FILELIST, 0, NULL);
  923     feh_menu_add_entry(m, "Edit in Place", "EDIT", 0, 0, NULL);
  924     feh_menu_add_entry(m, "Background", "BACKGROUND", 0, 0, NULL);
  925     feh_menu_add_entry(m, NULL, NULL, 0, 0, NULL);
  926     feh_menu_add_entry(m, "Hide", NULL, CB_REMOVE, 0, NULL);
  927     feh_menu_add_entry(m, "Delete", "CONFIRM", 0, 0, NULL);
  928 
  929     return;
  930 }
  931 
  932 void feh_menu_init_common()
  933 {
  934     int num_desks, i;
  935     char buf[30];
  936     feh_menu *m;
  937 
  938     if (!opt.menu_fn) {
  939         opt.menu_fn = gib_imlib_load_font(opt.menu_font);
  940         if (!opt.menu_fn)
  941             eprintf
  942                 ("couldn't load menu font %s, did you make install?\nAre you specifying a nonexistent font?\nDid you tell feh where to find it with --fontpath?",
  943                  opt.menu_font);
  944     }
  945 
  946     m = feh_menu_new();
  947     m->name = estrdup("SORT");
  948 
  949     feh_menu_add_entry(m, "By File Name", NULL, CB_SORT_FILENAME, 0, NULL);
  950     feh_menu_add_entry(m, "By Image Name", NULL, CB_SORT_IMAGENAME, 0, NULL);
  951     feh_menu_add_entry(m, "By Directory Name", NULL, CB_SORT_DIRNAME, 0, NULL);
  952     feh_menu_add_entry(m, "By Modification Date", NULL, CB_SORT_MTIME, 0, NULL);
  953     if (opt.preload || (opt.sort > SORT_MTIME))
  954         feh_menu_add_entry(m, "By File Size", NULL, CB_SORT_FILESIZE, 0, NULL);
  955     feh_menu_add_entry(m, "Randomize", NULL, CB_SORT_RANDOMIZE, 0, NULL);
  956 
  957     m = feh_menu_new();
  958     m->name = estrdup("CONFIRM");
  959     feh_menu_add_entry(m, "Confirm", NULL, CB_DELETE, 0, NULL);
  960 
  961     m = feh_menu_new();
  962     m->name = estrdup("EDIT");
  963     feh_menu_add_entry(m, "Rotate 90 CW", NULL, CB_EDIT_ROTATE, 1, NULL);
  964     feh_menu_add_entry(m, "Rotate 180", NULL, CB_EDIT_ROTATE, 2, NULL);
  965     feh_menu_add_entry(m, "Rotate 90 CCW", NULL, CB_EDIT_ROTATE, 3, NULL);
  966 
  967     menu_bg = feh_menu_new();
  968     menu_bg->name = estrdup("BACKGROUND");
  969 
  970     num_desks = feh_wm_get_num_desks();
  971     if (num_desks > 1) {
  972         feh_menu_add_entry(menu_bg, "Set Tiled", "TILED", 0, 0, NULL);
  973         feh_menu_add_entry(menu_bg, "Set Scaled", "SCALED", 0, 0, NULL);
  974         feh_menu_add_entry(menu_bg, "Set Centered", "CENTERED", 0, 0, NULL);
  975         feh_menu_add_entry(menu_bg, "Set Filled", "FILLED", 0, 0, NULL);
  976 
  977         m = feh_menu_new();
  978         m->name = estrdup("TILED");
  979         for (i = 0; i < num_desks; i++) {
  980             snprintf(buf, sizeof(buf), "Desktop %d", i + 1);
  981             if (opt.slideshow || opt.multiwindow)
  982                 feh_menu_add_entry(m, buf, NULL, CB_BG_TILED,
  983                         i, NULL);
  984             else
  985                 feh_menu_add_entry(m, buf, NULL, CB_BG_TILED_NOFILE,
  986                         i, NULL);
  987         }
  988 
  989         m = feh_menu_new();
  990         m->name = estrdup("SCALED");
  991         for (i = 0; i < num_desks; i++) {
  992             snprintf(buf, sizeof(buf), "Desktop %d", i + 1);
  993 
  994             if (opt.slideshow || opt.multiwindow)
  995                 feh_menu_add_entry(m, buf, NULL, CB_BG_SCALED,
  996                         i, NULL);
  997             else
  998                 feh_menu_add_entry(m, buf, NULL, CB_BG_SCALED_NOFILE,
  999                         i, NULL);
 1000         }
 1001 
 1002         m = feh_menu_new();
 1003         m->name = estrdup("CENTERED");
 1004         for (i = 0; i < num_desks; i++) {
 1005             snprintf(buf, sizeof(buf), "Desktop %d", i + 1);
 1006             if (opt.slideshow || opt.multiwindow)
 1007                 feh_menu_add_entry(m, buf, NULL,
 1008                         CB_BG_CENTERED, i, NULL);
 1009             else
 1010                 feh_menu_add_entry(m, buf, NULL,
 1011                         CB_BG_CENTERED_NOFILE, i, NULL);
 1012         }
 1013 
 1014         m = feh_menu_new();
 1015         m->name = estrdup("FILLED");
 1016         for (i = 0; i < num_desks; i++) {
 1017             snprintf(buf, sizeof(buf), "Desktop %d", i + 1);
 1018             if (opt.slideshow || opt.multiwindow)
 1019                 feh_menu_add_entry(m, buf, NULL,
 1020                         CB_BG_FILLED,
 1021                         i, NULL);
 1022             else
 1023                 feh_menu_add_entry(m, buf, NULL,
 1024                         CB_BG_FILLED_NOFILE,
 1025                         i, NULL);
 1026         }
 1027     } else {
 1028         if (opt.slideshow || opt.multiwindow) {
 1029             feh_menu_add_entry(menu_bg, "Set Tiled",
 1030                     NULL, CB_BG_TILED, 0, NULL);
 1031             feh_menu_add_entry(menu_bg, "Set Scaled",
 1032                     NULL, CB_BG_SCALED, 0, NULL);
 1033             feh_menu_add_entry(menu_bg, "Set Centered",
 1034                     NULL, CB_BG_CENTERED, 0, NULL);
 1035             feh_menu_add_entry(menu_bg, "Set Filled",
 1036                     NULL, CB_BG_FILLED, 0, NULL);
 1037         } else {
 1038             feh_menu_add_entry(menu_bg, "Set Tiled",
 1039                     NULL, CB_BG_TILED_NOFILE, 0, NULL);
 1040             feh_menu_add_entry(menu_bg, "Set Scaled",
 1041                     NULL, CB_BG_SCALED_NOFILE, 0, NULL);
 1042             feh_menu_add_entry(menu_bg, "Set Centered",
 1043                     NULL, CB_BG_CENTERED_NOFILE, 0, NULL);
 1044             feh_menu_add_entry(menu_bg, "Set Filled",
 1045                     NULL, CB_BG_FILLED_NOFILE, 0, NULL);
 1046         }
 1047     }
 1048     common_menus = 1;
 1049 
 1050     return;
 1051 }
 1052 
 1053 void feh_menu_init_single_win(void)
 1054 {
 1055     feh_menu *m;
 1056     feh_menu_item *mi;
 1057 
 1058     if (!common_menus)
 1059         feh_menu_init_common();
 1060 
 1061     menu_single_win = feh_menu_new();
 1062     menu_single_win->name = estrdup("SINGLEWIN");
 1063 
 1064     feh_menu_add_entry(menu_single_win, "File", "SINGLEWIN_FILE", 0, 0, NULL);
 1065     m = feh_menu_new();
 1066     m->name = estrdup("SINGLEWIN_FILE");
 1067     feh_menu_add_entry(m, "Reset", NULL, CB_RESET, 0, NULL);
 1068     feh_menu_add_entry(m, "Resize Window", NULL, CB_FIT, 0, NULL);
 1069     feh_menu_add_entry(m, "Reload", NULL, CB_RELOAD, 0, NULL);
 1070     feh_menu_add_entry(m, "Save Image", NULL, CB_SAVE_IMAGE, 0, NULL);
 1071     feh_menu_add_entry(m, "Save List", NULL, CB_SAVE_FILELIST, 0, NULL);
 1072     feh_menu_add_entry(m, "Edit in Place", "EDIT", 0, 0, NULL);
 1073     feh_menu_add_entry(m, "Background", "BACKGROUND", 0, 0, NULL);
 1074     if (opt.multiwindow || opt.slideshow) {
 1075         feh_menu_add_entry(m, NULL, NULL, 0, 0, NULL);
 1076         feh_menu_add_entry(m, "Hide", NULL, CB_REMOVE, 0, NULL);
 1077         feh_menu_add_entry(m, "Delete", "CONFIRM", 0, 0, NULL);
 1078     }
 1079 
 1080     mi = feh_menu_add_entry(menu_single_win, "Image Info", "INFO", 0, 0, NULL);
 1081     mi->func_gen_sub = feh_menu_func_gen_info;
 1082     feh_menu_add_entry(menu_single_win, NULL, NULL, 0, 0, NULL);
 1083     mi = feh_menu_add_entry(menu_single_win, "Options", "OPTIONS", 0, 0, NULL);
 1084     mi->func_gen_sub = feh_menu_func_gen_options;
 1085     feh_menu_add_entry(menu_single_win, "Close", NULL, CB_CLOSE, 0, NULL);
 1086     feh_menu_add_entry(menu_single_win, "Exit", NULL, CB_EXIT, 0, NULL);
 1087 
 1088     return;
 1089 }
 1090 
 1091 void feh_menu_init_thumbnail_win(void)
 1092 {
 1093     feh_menu *m;
 1094     feh_menu_item *mi;
 1095 
 1096     if (!common_menus)
 1097         feh_menu_init_common();
 1098 
 1099     menu_thumbnail_win = feh_menu_new();
 1100     menu_thumbnail_win->name = estrdup("THUMBWIN");
 1101 
 1102     feh_menu_add_entry(menu_thumbnail_win, "File", "THUMBWIN_FILE", 0, 0, NULL);
 1103     m = feh_menu_new();
 1104     m->name = estrdup("THUMBWIN_FILE");
 1105     feh_menu_add_entry(m, "Reset", NULL, CB_RESET, 0, NULL);
 1106     feh_menu_add_entry(m, "Resize Window", NULL, CB_FIT, 0, NULL);
 1107     feh_menu_add_entry(m, "Save Image", NULL, CB_SAVE_IMAGE, 0, NULL);
 1108     feh_menu_add_entry(m, "Save List", NULL, CB_SAVE_FILELIST, 0, NULL);
 1109     feh_menu_add_entry(m, "Background", "BACKGROUND", 0, 0, NULL);
 1110     feh_menu_add_entry(menu_thumbnail_win, NULL, NULL, 0, 0, NULL);
 1111     mi = feh_menu_add_entry(menu_thumbnail_win, "Options", "OPTIONS", 0, 0, NULL);
 1112     mi->func_gen_sub = feh_menu_func_gen_options;
 1113     feh_menu_add_entry(menu_thumbnail_win, "Close", NULL, CB_CLOSE, 0, NULL);
 1114     feh_menu_add_entry(menu_thumbnail_win, "Exit", NULL, CB_EXIT, 0, NULL);
 1115     return;
 1116 }
 1117 
 1118 void feh_menu_init_thumbnail_viewer(void)
 1119 {
 1120     feh_menu *m;
 1121     feh_menu_item *mi;
 1122 
 1123     if (!common_menus)
 1124         feh_menu_init_common();
 1125 
 1126     menu_thumbnail_viewer = feh_menu_new();
 1127     menu_thumbnail_viewer->name = estrdup("THUMBVIEW");
 1128 
 1129     feh_menu_add_entry(menu_thumbnail_viewer, "File", "THUMBVIEW_FILE",
 1130             0, 0, NULL);
 1131     m = feh_menu_new();
 1132     m->name = estrdup("THUMBVIEW_FILE");
 1133     feh_menu_add_entry(m, "Reset", NULL, CB_RESET, 0, NULL);
 1134     feh_menu_add_entry(m, "Resize Window", NULL, CB_FIT, 0, NULL);
 1135     feh_menu_add_entry(m, "Reload", NULL, CB_RELOAD, 0, NULL);
 1136     feh_menu_add_entry(m, "Save Image", NULL, CB_SAVE_IMAGE, 0, NULL);
 1137     feh_menu_add_entry(m, "Save List", NULL, CB_SAVE_FILELIST, 0, NULL);
 1138     feh_menu_add_entry(m, "Edit in Place", "EDIT", 0, 0, NULL);
 1139     feh_menu_add_entry(m, "Background", "BACKGROUND", 0, 0, NULL);
 1140     feh_menu_add_entry(m, NULL, NULL, 0, 0, NULL);
 1141     feh_menu_add_entry(m, "Hide", NULL, CB_REMOVE_THUMB, 0, NULL);
 1142     feh_menu_add_entry(m, "Delete", "THUMBVIEW_CONFIRM", 0, 0, NULL);
 1143     mi = feh_menu_add_entry(menu_thumbnail_viewer, "Image Info",
 1144             "INFO", 0, 0, NULL);
 1145     mi->func_gen_sub = feh_menu_func_gen_info;
 1146     feh_menu_add_entry(menu_thumbnail_viewer, NULL, NULL, 0, 0, NULL);
 1147     mi = feh_menu_add_entry(menu_thumbnail_viewer, "Options",
 1148             "OPTIONS", 0, 0, NULL);
 1149     mi->func_gen_sub = feh_menu_func_gen_options;
 1150     feh_menu_add_entry(menu_thumbnail_viewer, "Close", NULL, CB_CLOSE, 0, NULL);
 1151     feh_menu_add_entry(menu_thumbnail_viewer, "Exit", NULL, CB_EXIT, 0, NULL);
 1152     m = feh_menu_new();
 1153     m->name = estrdup("THUMBVIEW_CONFIRM");
 1154     feh_menu_add_entry(m, "Confirm", NULL, CB_DELETE_THUMB, 0, NULL);
 1155     return;
 1156 }
 1157 
 1158 void feh_menu_cb_opt_fullscreen(feh_menu * m, feh_menu_item * i)
 1159 {
 1160     int curr_screen = 0;
 1161 
 1162     MENU_ITEM_TOGGLE(i);
 1163     if (MENU_ITEM_IS_ON(i))
 1164         m->fehwin->full_screen = TRUE;
 1165     else
 1166         m->fehwin->full_screen = FALSE;
 1167 
 1168 #ifdef HAVE_LIBXINERAMA
 1169     if (opt.xinerama && xinerama_screens) {
 1170         int i, rect[4];
 1171 
 1172         winwidget_get_geometry(m->fehwin, rect);
 1173         for (i = 0; i < num_xinerama_screens; i++) {
 1174             xinerama_screen = 0;
 1175             if (XY_IN_RECT(rect[0], rect[1],
 1176                        xinerama_screens[i].x_org,
 1177                        xinerama_screens[i].y_org,
 1178                        xinerama_screens[i].width, xinerama_screens[i].height)) {
 1179                 curr_screen = xinerama_screen = i;
 1180                 break;
 1181             }
 1182 
 1183         }
 1184         if (opt.xinerama_index >= 0)
 1185             curr_screen = xinerama_screen = opt.xinerama_index;
 1186     }
 1187 #endif              /* HAVE_LIBXINERAMA */
 1188 
 1189     winwidget_destroy_xwin(m->fehwin);
 1190     winwidget_create_window(m->fehwin, m->fehwin->im_w, m->fehwin->im_h);
 1191 
 1192     winwidget_render_image(m->fehwin, 1, 0);
 1193     winwidget_show(m->fehwin);
 1194 
 1195 #ifdef HAVE_LIBXINERAMA
 1196     /* if we have xinerama and we're using it, then full screen the window
 1197      * on the head that the window was active on */
 1198     if (m->fehwin->full_screen == TRUE && opt.xinerama && xinerama_screens) {
 1199         xinerama_screen = curr_screen;
 1200         winwidget_move(m->fehwin, xinerama_screens[curr_screen].x_org, xinerama_screens[curr_screen].y_org);
 1201     }
 1202 #endif              /* HAVE_LIBXINERAMA */
 1203 }
 1204 
 1205 void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, unsigned short data)
 1206 {
 1207     char *path;
 1208 
 1209     switch (action) {
 1210         case CB_BG_TILED:
 1211             path = FEH_FILE(m->fehwin->file->data)->filename;
 1212             feh_wm_set_bg(path, m->fehwin->im, 0, 0, 0, data, 0);
 1213             break;
 1214         case CB_BG_SCALED:
 1215             path = FEH_FILE(m->fehwin->file->data)->filename;
 1216             feh_wm_set_bg(path, m->fehwin->im, 0, 1, 0, data, 0);
 1217             break;
 1218         case CB_BG_CENTERED:
 1219             path = FEH_FILE(m->fehwin->file->data)->filename;
 1220             feh_wm_set_bg(path, m->fehwin->im, 1, 0, 0, data, 0);
 1221             break;
 1222         case CB_BG_FILLED:
 1223             path = FEH_FILE(m->fehwin->file->data)->filename;
 1224             feh_wm_set_bg(path, m->fehwin->im, 0, 0, 1, data, 0);
 1225             break;
 1226         case CB_BG_TILED_NOFILE:
 1227             feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, 0, data, 0);
 1228             break;
 1229         case CB_BG_SCALED_NOFILE:
 1230             feh_wm_set_bg(NULL, m->fehwin->im, 0, 1, 0, data, 0);
 1231             break;
 1232         case CB_BG_CENTERED_NOFILE:
 1233             feh_wm_set_bg(NULL, m->fehwin->im, 1, 0, 0, data, 0);
 1234             break;
 1235         case CB_BG_FILLED_NOFILE:
 1236             feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, 1, data, 0);
 1237             break;
 1238         case CB_CLOSE:
 1239             winwidget_destroy(m->fehwin);
 1240             break;
 1241         case CB_EXIT:
 1242             winwidget_destroy_all();
 1243             break;
 1244         case CB_RESET:
 1245             if (m->fehwin->has_rotated) {
 1246                 m->fehwin->im_w = gib_imlib_image_get_width(m->fehwin->im);
 1247                 m->fehwin->im_h = gib_imlib_image_get_height(m->fehwin->im);
 1248                 winwidget_resize(m->fehwin, m->fehwin->im_w, m->fehwin->im_h, 0);
 1249             }
 1250             winwidget_reset_image(m->fehwin);
 1251             winwidget_render_image(m->fehwin, 1, 0);
 1252             break;
 1253         case CB_RELOAD:
 1254             feh_reload_image(m->fehwin, 0, 1);
 1255             break;
 1256         case CB_REMOVE:
 1257             feh_filelist_image_remove(m->fehwin, 0);
 1258             break;
 1259         case CB_DELETE:
 1260             feh_filelist_image_remove(m->fehwin, 1);
 1261             break;
 1262         case CB_REMOVE_THUMB:
 1263             feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 0);
 1264             feh_filelist_image_remove(m->fehwin, 0);
 1265             break;
 1266         case CB_DELETE_THUMB:
 1267             feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 1);
 1268             feh_filelist_image_remove(m->fehwin, 1);
 1269             break;
 1270         case CB_SORT_FILENAME:
 1271             filelist = gib_list_sort(filelist, feh_cmp_filename);
 1272             if (opt.jump_on_resort) {
 1273                 slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
 1274             }
 1275             break;
 1276         case CB_SORT_IMAGENAME:
 1277             filelist = gib_list_sort(filelist, feh_cmp_name);
 1278             if (opt.jump_on_resort) {
 1279                 slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
 1280             }
 1281             break;
 1282         case CB_SORT_DIRNAME:
 1283             filelist = gib_list_sort(filelist, feh_cmp_dirname);
 1284             if (opt.jump_on_resort) {
 1285                 slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
 1286             }
 1287             break;
 1288         case CB_SORT_MTIME:
 1289             filelist = gib_list_sort(filelist, feh_cmp_mtime);
 1290             if (opt.jump_on_resort) {
 1291                 slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
 1292             }
 1293             break;
 1294         case CB_SORT_FILESIZE:
 1295             filelist = gib_list_sort(filelist, feh_cmp_size);
 1296             if (opt.jump_on_resort) {
 1297                 slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
 1298             }
 1299             break;
 1300         case CB_SORT_RANDOMIZE:
 1301             filelist = gib_list_randomize(filelist);
 1302             if (opt.jump_on_resort) {
 1303                 slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
 1304             }
 1305             break;
 1306         case CB_FIT:
 1307             winwidget_size_to_image(m->fehwin);
 1308             break;
 1309         case CB_EDIT_ROTATE:
 1310             feh_edit_inplace(m->fehwin, data);
 1311             break;
 1312         case CB_SAVE_IMAGE:
 1313             slideshow_save_image(m->fehwin);
 1314             break;
 1315         case CB_SAVE_FILELIST:
 1316             feh_save_filelist();
 1317             break;
 1318         case CB_OPT_DRAW_FILENAME:
 1319             MENU_ITEM_TOGGLE(i);
 1320             if (MENU_ITEM_IS_ON(i))
 1321                 opt.draw_filename = TRUE;
 1322             else
 1323                 opt.draw_filename = FALSE;
 1324             winwidget_rerender_all(0);
 1325             break;
 1326         case CB_OPT_DRAW_ACTIONS:
 1327             MENU_ITEM_TOGGLE(i);
 1328             if (MENU_ITEM_IS_ON(i))
 1329                 opt.draw_actions = TRUE;
 1330             else
 1331                 opt.draw_actions = FALSE;
 1332             winwidget_rerender_all(0);
 1333             break;
 1334         case CB_OPT_KEEP_HTTP:
 1335             MENU_ITEM_TOGGLE(i);
 1336             if (MENU_ITEM_IS_ON(i))
 1337                 opt.keep_http = TRUE;
 1338             else
 1339                 opt.keep_http = FALSE;
 1340             break;
 1341         case CB_OPT_FREEZE_WINDOW:
 1342             MENU_ITEM_TOGGLE(i);
 1343             if (MENU_ITEM_IS_ON(i)) {
 1344                 opt.geom_flags = (WidthValue | HeightValue);
 1345                 opt.geom_w = m->fehwin->w;
 1346                 opt.geom_h = m->fehwin->h;
 1347             } else {
 1348                 opt.geom_flags = 0;
 1349             }
 1350             break;
 1351         case CB_OPT_FULLSCREEN:
 1352             feh_menu_cb_opt_fullscreen(m, i);
 1353             break;
 1354         case CB_OPT_AUTO_ZOOM:
 1355             MENU_ITEM_TOGGLE(i);
 1356             if (MENU_ITEM_IS_ON(i))
 1357                 opt.zoom_mode = ZOOM_MODE_MAX;
 1358             else
 1359                 opt.zoom_mode = 0;
 1360             winwidget_rerender_all(1);
 1361             break;
 1362         case CB_OPT_KEEP_ZOOM_VP:
 1363             MENU_ITEM_TOGGLE(i);
 1364             if (MENU_ITEM_IS_ON(i))
 1365                 opt.keep_zoom_vp = 1;
 1366             else
 1367                 opt.keep_zoom_vp = 0;
 1368             break;
 1369     }
 1370     return;
 1371 }
 1372 
 1373 static feh_menu *feh_menu_func_gen_info(feh_menu * m)
 1374 {
 1375     Imlib_Image im;
 1376     feh_menu *mm;
 1377     feh_file *file;
 1378     char buffer[400];
 1379 
 1380     if (!m->fehwin->file)
 1381         return(NULL);
 1382     file = FEH_FILE(m->fehwin->file->data);
 1383     im = m->fehwin->im;
 1384     if (!im)
 1385         return(NULL);
 1386     mm = feh_menu_new();
 1387     mm->name = estrdup("INFO");
 1388     snprintf(buffer, sizeof(buffer), "Filename: %s", file->name);
 1389     feh_menu_add_entry(mm, buffer, NULL, 0, 0, NULL);
 1390     if (!file->info)
 1391         feh_file_info_load(file, im);
 1392     if (file->info) {
 1393         snprintf(buffer, sizeof(buffer), "Size: %dKb", file->info->size / 1024);
 1394         feh_menu_add_entry(mm, buffer, NULL, 0, 0, NULL);
 1395         snprintf(buffer, sizeof(buffer), "Dimensions: %dx%d", file->info->width, file->info->height);
 1396         feh_menu_add_entry(mm, buffer, NULL, 0, 0, NULL);
 1397         snprintf(buffer, sizeof(buffer), "Type: %s", file->info->format);
 1398         feh_menu_add_entry(mm, buffer, NULL, 0, 0, NULL);
 1399     }
 1400 
 1401     mm->func_free = feh_menu_func_free_info;
 1402     return(mm);
 1403 }
 1404 
 1405 static void feh_menu_func_free_info(feh_menu * m)
 1406 {
 1407     feh_menu_free(m);
 1408     return;
 1409 }
 1410 
 1411 static feh_menu *feh_menu_func_gen_options(feh_menu * m)
 1412 {
 1413     feh_menu *mm;
 1414 
 1415     mm = feh_menu_new();
 1416     mm->name = estrdup("OPTIONS");
 1417     mm->fehwin = m->fehwin;
 1418     feh_menu_add_toggle_entry(mm, "Auto-Zoom", NULL, CB_OPT_AUTO_ZOOM,
 1419                 0, NULL, opt.zoom_mode);
 1420     feh_menu_add_toggle_entry(mm, "Freeze Window Size", NULL,
 1421                 CB_OPT_FREEZE_WINDOW, 0, NULL, opt.geom_flags);
 1422     feh_menu_add_toggle_entry(mm, "Fullscreen", NULL,
 1423                 CB_OPT_FULLSCREEN, 0, NULL, m->fehwin->full_screen);
 1424     feh_menu_add_toggle_entry(mm, "Keep viewport zoom & pos", NULL,
 1425                 CB_OPT_KEEP_ZOOM_VP, 0, NULL, opt.keep_zoom_vp);
 1426 
 1427     feh_menu_add_entry(mm, NULL, NULL, 0, 0, NULL);
 1428 
 1429     feh_menu_add_toggle_entry(mm, "Draw Filename", NULL,
 1430                 CB_OPT_DRAW_FILENAME, 0, NULL, opt.draw_filename);
 1431     feh_menu_add_toggle_entry(mm, "Draw Actions", NULL,
 1432                 CB_OPT_DRAW_ACTIONS, 0, NULL, opt.draw_actions);
 1433     feh_menu_add_toggle_entry(mm, "Keep HTTP Files", NULL,
 1434                 CB_OPT_KEEP_HTTP, 0, NULL, opt.keep_http);
 1435     mm->func_free = feh_menu_func_free_options;
 1436     return(mm);
 1437 }
 1438 
 1439 static void feh_menu_func_free_options(feh_menu * m)
 1440 {
 1441     feh_menu_free(m);
 1442     return;
 1443 }