"Fossies" - the Fresh Open Source Software Archive

Member "feh-3.4.1/src/wallpaper.c" (29 May 2020, 24487 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 "wallpaper.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 /* wallpaper.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 <limits.h>
   28 #include <sys/stat.h>
   29 
   30 #include "feh.h"
   31 #include "filelist.h"
   32 #include "options.h"
   33 #include "wallpaper.h"
   34 
   35 Window ipc_win = None;
   36 Window my_ipc_win = None;
   37 Atom ipc_atom = None;
   38 static unsigned char timeout = 0;
   39 
   40 /*
   41  * This is a boolean indicating
   42  * That while we seem to see E16 IPC
   43  * it's actually E17 faking it
   44  * -- richlowe 2005-06-22
   45  */
   46 static char e17_fake_ipc = 0;
   47 
   48 void feh_wm_set_bg_filelist(unsigned char bgmode)
   49 {
   50     if (filelist_len == 0)
   51         eprintf("No files specified for background setting");
   52 
   53     switch (bgmode) {
   54         case BG_MODE_TILE:
   55             feh_wm_set_bg(NULL, NULL, 0, 0, 0, 0, 1);
   56             break;
   57         case BG_MODE_SCALE:
   58             feh_wm_set_bg(NULL, NULL, 0, 1, 0, 0, 1);
   59             break;
   60         case BG_MODE_FILL:
   61             feh_wm_set_bg(NULL, NULL, 0, 0, 1, 0, 1);
   62             break;
   63         case BG_MODE_MAX:
   64             feh_wm_set_bg(NULL, NULL, 0, 0, 2, 0, 1);
   65             break;
   66         default:
   67             feh_wm_set_bg(NULL, NULL, 1, 0, 0, 0, 1);
   68             break;
   69     }
   70 }
   71 
   72 static void feh_wm_load_next(Imlib_Image *im)
   73 {
   74     static gib_list *wpfile = NULL;
   75 
   76     if (wpfile == NULL)
   77         wpfile = filelist;
   78 
   79     if (feh_load_image(im, FEH_FILE(wpfile->data)) == 0)
   80         eprintf("Unable to load image %s", FEH_FILE(wpfile->data)->filename);
   81     if (wpfile->next)
   82         wpfile = wpfile->next;
   83 
   84     return;
   85 }
   86 
   87 static void feh_wm_set_bg_scaled(Pixmap pmap, Imlib_Image im, int use_filelist,
   88         int x, int y, int w, int h)
   89 {
   90     if (use_filelist)
   91         feh_wm_load_next(&im);
   92 
   93     gib_imlib_render_image_on_drawable_at_size(pmap, im, x, y, w, h,
   94             1, 1, !opt.force_aliasing);
   95 
   96     if (use_filelist)
   97         gib_imlib_free_image_and_decache(im);
   98 
   99     return;
  100 }
  101 
  102 static void feh_wm_set_bg_centered(Pixmap pmap, Imlib_Image im, int use_filelist,
  103         int x, int y, int w, int h)
  104 {
  105     int offset_x, offset_y;
  106 
  107     if (use_filelist)
  108         feh_wm_load_next(&im);
  109 
  110     if(opt.geom_flags & XValue)
  111         if(opt.geom_flags & XNegative)
  112             offset_x = (w - gib_imlib_image_get_width(im)) + opt.geom_x;
  113         else
  114             offset_x = opt.geom_x;
  115     else
  116         offset_x = (w - gib_imlib_image_get_width(im)) >> 1;
  117 
  118     if(opt.geom_flags & YValue)
  119         if(opt.geom_flags & YNegative)
  120             offset_y = (h - gib_imlib_image_get_height(im)) + opt.geom_y;
  121         else
  122             offset_y = opt.geom_y;
  123     else
  124         offset_y = (h - gib_imlib_image_get_height(im)) >> 1;
  125 
  126     gib_imlib_render_image_part_on_drawable_at_size(pmap, im,
  127         ((offset_x < 0) ? -offset_x : 0),
  128         ((offset_y < 0) ? -offset_y : 0),
  129         w,
  130         h,
  131         x + ((offset_x > 0) ? offset_x : 0),
  132         y + ((offset_y > 0) ? offset_y : 0),
  133         w,
  134         h,
  135         1, 1, 0);
  136 
  137     if (use_filelist)
  138         gib_imlib_free_image_and_decache(im);
  139 
  140     return;
  141 }
  142 
  143 static void feh_wm_set_bg_filled(Pixmap pmap, Imlib_Image im, int use_filelist,
  144         int x, int y, int w, int h)
  145 {
  146     int img_w, img_h, cut_x;
  147     int render_w, render_h, render_x, render_y;
  148 
  149     if (use_filelist)
  150         feh_wm_load_next(&im);
  151 
  152     img_w = gib_imlib_image_get_width(im);
  153     img_h = gib_imlib_image_get_height(im);
  154 
  155     cut_x = (((img_w * h) > (img_h * w)) ? 1 : 0);
  156 
  157     render_w = (  cut_x ? ((img_h * w) / h) : img_w);
  158     render_h = ( !cut_x ? ((img_w * h) / w) : img_h);
  159 
  160     render_x = (  cut_x ? ((img_w - render_w) >> 1) : 0);
  161     render_y = ( !cut_x ? ((img_h - render_h) >> 1) : 0);
  162 
  163     if ((opt.geom_flags & XValue) && cut_x) {
  164         if (opt.geom_flags & XNegative) {
  165             render_x = img_w - render_w + opt.geom_x;
  166         } else {
  167             render_x = opt.geom_x;
  168         }
  169         if (render_x < 0) {
  170             render_x = 0;
  171         } else if (render_x + render_w > img_w) {
  172             render_x = img_w - render_w;
  173         }
  174     }
  175     else if ((opt.geom_flags & YValue) && !cut_x) {
  176         if (opt.geom_flags & YNegative) {
  177             render_y = img_h - render_h + opt.geom_y;
  178         } else {
  179             render_y = opt.geom_y;
  180         }
  181         if (render_y < 0) {
  182             render_y = 0;
  183         } else if (render_y + render_h > img_h) {
  184             render_y = img_h - render_h;
  185         }
  186     }
  187 
  188     gib_imlib_render_image_part_on_drawable_at_size(pmap, im,
  189         render_x, render_y,
  190         render_w, render_h,
  191         x, y, w, h,
  192         1, 1, !opt.force_aliasing);
  193 
  194     if (use_filelist)
  195         gib_imlib_free_image_and_decache(im);
  196 
  197     return;
  198 }
  199 
  200 static void feh_wm_set_bg_maxed(Pixmap pmap, Imlib_Image im, int use_filelist,
  201         int x, int y, int w, int h)
  202 {
  203     int img_w, img_h, border_x;
  204     int render_w, render_h, render_x, render_y;
  205     int margin_x, margin_y;
  206 
  207     if (use_filelist)
  208         feh_wm_load_next(&im);
  209 
  210     img_w = gib_imlib_image_get_width(im);
  211     img_h = gib_imlib_image_get_height(im);
  212 
  213     border_x = (((img_w * h) > (img_h * w)) ? 0 : 1);
  214 
  215     render_w = (  border_x ? ((img_w * h) / img_h) : w);
  216     render_h = ( !border_x ? ((img_h * w) / img_w) : h);
  217 
  218     if(opt.geom_flags & XValue)
  219         if(opt.geom_flags & XNegative)
  220             margin_x = (w - render_w) + opt.geom_x;
  221         else
  222             margin_x = opt.geom_x;
  223     else
  224         margin_x = (w - render_w) >> 1;
  225 
  226     if(opt.geom_flags & YValue)
  227         if(opt.geom_flags & YNegative)
  228             margin_y = (h - render_h) + opt.geom_y;
  229         else
  230             margin_y = opt.geom_y;
  231     else
  232         margin_y = (h - render_h) >> 1;
  233 
  234     render_x = x + (  border_x ? margin_x : 0);
  235     render_y = y + ( !border_x ? margin_y : 0);
  236 
  237     gib_imlib_render_image_on_drawable_at_size(pmap, im,
  238         render_x, render_y,
  239         render_w, render_h,
  240         1, 1, !opt.force_aliasing);
  241 
  242     if (use_filelist)
  243         gib_imlib_free_image_and_decache(im);
  244 
  245     return;
  246 }
  247 
  248 void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
  249         int filled, int desktop, int use_filelist)
  250 {
  251     XGCValues gcvalues;
  252     XGCValues gcval;
  253     GC gc;
  254     char bgname[20];
  255     int num = (int) random();
  256     char bgfil[4096];
  257     char sendbuf[4096];
  258 
  259     /*
  260      * TODO this re-implements mkstemp (badly). However, it is only needed
  261      * for non-file images and enlightenment. Might be easier to just remove
  262      * it.
  263      */
  264 
  265     snprintf(bgname, sizeof(bgname), "FEHBG_%d", num);
  266 
  267     if (!fil && im) {
  268         if (getenv("HOME") == NULL) {
  269             weprintf("Cannot save wallpaper to temporary file: You have no HOME");
  270             return;
  271         }
  272         snprintf(bgfil, sizeof(bgfil), "%s/.%s.png", getenv("HOME"), bgname);
  273         imlib_context_set_image(im);
  274         imlib_image_set_format("png");
  275         gib_imlib_save_image(im, bgfil);
  276         D(("bg saved as %s\n", bgfil));
  277         fil = bgfil;
  278     }
  279 
  280     if (feh_wm_get_wm_is_e() && (enl_ipc_get_win() != None)) {
  281         if (use_filelist) {
  282             feh_wm_load_next(&im);
  283             fil = FEH_FILE(filelist->data)->filename;
  284         }
  285         snprintf(sendbuf, sizeof(sendbuf), "background %s bg.file %s", bgname, fil);
  286         enl_ipc_send(sendbuf);
  287 
  288         if (scaled) {
  289             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.solid 0 0 0", bgname);
  290             enl_ipc_send(sendbuf);
  291             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.tile 0", bgname);
  292             enl_ipc_send(sendbuf);
  293             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.xjust 512", bgname);
  294             enl_ipc_send(sendbuf);
  295             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.yjust 512", bgname);
  296             enl_ipc_send(sendbuf);
  297             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.xperc 1024", bgname);
  298             enl_ipc_send(sendbuf);
  299             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.yperc 1024", bgname);
  300             enl_ipc_send(sendbuf);
  301         } else if (centered) {
  302             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.solid 0 0 0", bgname);
  303             enl_ipc_send(sendbuf);
  304             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.tile 0", bgname);
  305             enl_ipc_send(sendbuf);
  306             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.xjust 512", bgname);
  307             enl_ipc_send(sendbuf);
  308             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.yjust 512", bgname);
  309             enl_ipc_send(sendbuf);
  310         } else {
  311             snprintf(sendbuf, sizeof(sendbuf), "background %s bg.tile 1", bgname);
  312             enl_ipc_send(sendbuf);
  313         }
  314 
  315         snprintf(sendbuf, sizeof(sendbuf), "use_bg %s %d", bgname, desktop);
  316         enl_ipc_send(sendbuf);
  317         enl_ipc_sync();
  318     } else {
  319         Atom prop_root, prop_esetroot, type;
  320         int format, i;
  321         unsigned long length, after;
  322         unsigned char *data_root = NULL, *data_esetroot = NULL;
  323         Pixmap pmap_d1, pmap_d2;
  324 
  325         char *home;
  326 
  327         /* local display to set closedownmode on */
  328         Display *disp2;
  329         Window root2;
  330         int depth2;
  331         int w, h;
  332 
  333         D(("Falling back to XSetRootWindowPixmap\n"));
  334 
  335         XColor color;
  336         Colormap cmap = DefaultColormap(disp, DefaultScreen(disp));
  337         if (opt.image_bg)
  338             XAllocNamedColor(disp, cmap, (char*) opt.image_bg, &color, &color);
  339         else
  340             XAllocNamedColor(disp, cmap, "black", &color, &color);
  341 
  342         if (scaled) {
  343             pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth);
  344 
  345 #ifdef HAVE_LIBXINERAMA
  346             if (opt.xinerama_index >= 0) {
  347                 gcval.foreground = color.pixel;
  348                 gc = XCreateGC(disp, root, GCForeground, &gcval);
  349                 XFillRectangle(disp, pmap_d1, gc, 0, 0, scr->width, scr->height);
  350                 XFreeGC(disp, gc);
  351             }
  352 
  353             if (opt.xinerama && xinerama_screens) {
  354                 for (i = 0; i < num_xinerama_screens; i++) {
  355                     if (opt.xinerama_index < 0 || opt.xinerama_index == i) {
  356                         feh_wm_set_bg_scaled(pmap_d1, im, use_filelist,
  357                             xinerama_screens[i].x_org, xinerama_screens[i].y_org,
  358                             xinerama_screens[i].width, xinerama_screens[i].height);
  359                     }
  360                 }
  361             }
  362             else
  363 #endif          /* HAVE_LIBXINERAMA */
  364                 feh_wm_set_bg_scaled(pmap_d1, im, use_filelist,
  365                     0, 0, scr->width, scr->height);
  366         } else if (centered) {
  367 
  368             D(("centering\n"));
  369 
  370             pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth);
  371             gcval.foreground = color.pixel;
  372             gc = XCreateGC(disp, root, GCForeground, &gcval);
  373             XFillRectangle(disp, pmap_d1, gc, 0, 0, scr->width, scr->height);
  374 
  375 #ifdef HAVE_LIBXINERAMA
  376             if (opt.xinerama && xinerama_screens) {
  377                 for (i = 0; i < num_xinerama_screens; i++) {
  378                     if (opt.xinerama_index < 0 || opt.xinerama_index == i) {
  379                         feh_wm_set_bg_centered(pmap_d1, im, use_filelist,
  380                             xinerama_screens[i].x_org, xinerama_screens[i].y_org,
  381                             xinerama_screens[i].width, xinerama_screens[i].height);
  382                     }
  383                 }
  384             }
  385             else
  386 #endif              /* HAVE_LIBXINERAMA */
  387                 feh_wm_set_bg_centered(pmap_d1, im, use_filelist,
  388                     0, 0, scr->width, scr->height);
  389 
  390             XFreeGC(disp, gc);
  391 
  392         } else if (filled == 1) {
  393 
  394             pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth);
  395 
  396 #ifdef HAVE_LIBXINERAMA
  397             if (opt.xinerama_index >= 0) {
  398                 gcval.foreground = color.pixel;
  399                 gc = XCreateGC(disp, root, GCForeground, &gcval);
  400                 XFillRectangle(disp, pmap_d1, gc, 0, 0, scr->width, scr->height);
  401                 XFreeGC(disp, gc);
  402             }
  403 
  404             if (opt.xinerama && xinerama_screens) {
  405                 for (i = 0; i < num_xinerama_screens; i++) {
  406                     if (opt.xinerama_index < 0 || opt.xinerama_index == i) {
  407                         feh_wm_set_bg_filled(pmap_d1, im, use_filelist,
  408                             xinerama_screens[i].x_org, xinerama_screens[i].y_org,
  409                             xinerama_screens[i].width, xinerama_screens[i].height);
  410                     }
  411                 }
  412             }
  413             else
  414 #endif              /* HAVE_LIBXINERAMA */
  415                 feh_wm_set_bg_filled(pmap_d1, im, use_filelist
  416                     , 0, 0, scr->width, scr->height);
  417 
  418         } else if (filled == 2) {
  419 
  420             pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth);
  421             gcval.foreground = color.pixel;
  422             gc = XCreateGC(disp, root, GCForeground, &gcval);
  423             XFillRectangle(disp, pmap_d1, gc, 0, 0, scr->width, scr->height);
  424 
  425 #ifdef HAVE_LIBXINERAMA
  426             if (opt.xinerama && xinerama_screens) {
  427                 for (i = 0; i < num_xinerama_screens; i++) {
  428                     if (opt.xinerama_index < 0 || opt.xinerama_index == i) {
  429                         feh_wm_set_bg_maxed(pmap_d1, im, use_filelist,
  430                             xinerama_screens[i].x_org, xinerama_screens[i].y_org,
  431                             xinerama_screens[i].width, xinerama_screens[i].height);
  432                     }
  433                 }
  434             }
  435             else
  436 #endif              /* HAVE_LIBXINERAMA */
  437                 feh_wm_set_bg_maxed(pmap_d1, im, use_filelist,
  438                     0, 0, scr->width, scr->height);
  439 
  440             XFreeGC(disp, gc);
  441 
  442         } else {
  443             if (use_filelist)
  444                 feh_wm_load_next(&im);
  445             w = gib_imlib_image_get_width(im);
  446             h = gib_imlib_image_get_height(im);
  447             pmap_d1 = XCreatePixmap(disp, root, w, h, depth);
  448             gib_imlib_render_image_on_drawable(pmap_d1, im, 0, 0, 1, 1, 0);
  449         }
  450 
  451         if (!opt.no_fehbg) {
  452             home = getenv("HOME");
  453             if (home) {
  454                 FILE *fp;
  455                 int fd;
  456                 char *path;
  457                 char *absolute_path;
  458                 struct stat s;
  459                 gib_list *filelist_pos = filelist;
  460                 path = estrjoin("/", home, ".fehbg", NULL);
  461                 if ((fp = fopen(path, "w")) == NULL) {
  462                     weprintf("Can't write to %s", path);
  463                 } else {
  464                     fputs("#!/bin/sh\n", fp);
  465                     fputs(cmdargv[0], fp);
  466                     fputs(" --no-fehbg --bg-", fp);
  467                     if (centered)
  468                         fputs("center", fp);
  469                     else if (scaled)
  470                         fputs("scale", fp);
  471                     else if (filled == 1)
  472                         fputs("fill", fp);
  473                     else if (filled == 2)
  474                         fputs("max", fp);
  475                     else
  476                         fputs("tile", fp);
  477                     if (opt.image_bg) {
  478                         fputs(" --image-bg ", fp);
  479                         fputs(shell_escape(opt.image_bg), fp);
  480                     }
  481 #ifdef HAVE_LIBXINERAMA
  482                     if (opt.xinerama) {
  483                         if (opt.xinerama_index >= 0) {
  484                             fprintf(fp, " --xinerama-index %d", opt.xinerama_index);
  485                         }
  486                     }
  487                     else {
  488                         fputs(" --no-xinerama", fp);
  489                     }
  490 #endif          /* HAVE_LIBXINERAMA */
  491                     if (opt.geom_flags & XValue) {
  492                         fprintf(fp, " --geometry %c%d",
  493                                 opt.geom_flags & XNegative ? '-' : '+',
  494                                 opt.geom_flags & XNegative ? abs(opt.geom_x) : opt.geom_x);
  495                         if (opt.geom_flags & YValue) {
  496                             fprintf(fp, "%c%d",
  497                                     opt.geom_flags & YNegative ? '-' : '+',
  498                                     opt.geom_flags & YNegative ? abs(opt.geom_y) : opt.geom_y);
  499                         }
  500                     }
  501                     if (opt.force_aliasing) {
  502                         fputs(" --force-aliasing", fp);
  503                     }
  504                     fputc(' ', fp);
  505                     if (use_filelist) {
  506 #ifdef HAVE_LIBXINERAMA
  507                         for (int i = 0; (i < opt.xinerama ? num_xinerama_screens : 1) && filelist_pos; i++) {
  508 #else
  509                         for (int i = 0; (i < 1                   ) && filelist_pos; i++) {
  510 #endif
  511                             absolute_path = feh_absolute_path(FEH_FILE(filelist_pos->data)->filename);
  512                             fputs(shell_escape(absolute_path), fp);
  513                             filelist_pos = filelist_pos->next;
  514                             free(absolute_path);
  515                             fputc(' ', fp);
  516                         }
  517                     } else if (fil) {
  518                         absolute_path = feh_absolute_path(fil);
  519                         fputs(shell_escape(absolute_path), fp);
  520                         free(absolute_path);
  521                     }
  522                     fputc('\n', fp);
  523                     fd = fileno(fp);
  524                     if (fstat(fd, &s) != 0 || fchmod(fd, s.st_mode | S_IXUSR | S_IXGRP) != 0) {
  525                         weprintf("Can't set %s as executable", path);
  526                     }
  527                     fclose(fp);
  528                 }
  529                 free(path);
  530             }
  531         }
  532 
  533         /* create new display, copy pixmap to new display */
  534         disp2 = XOpenDisplay(NULL);
  535         if (!disp2)
  536             eprintf("Can't reopen X display.");
  537         root2 = RootWindow(disp2, DefaultScreen(disp2));
  538         depth2 = DefaultDepth(disp2, DefaultScreen(disp2));
  539         XSync(disp, False);
  540         pmap_d2 = XCreatePixmap(disp2, root2, scr->width, scr->height, depth2);
  541         gcvalues.fill_style = FillTiled;
  542         gcvalues.tile = pmap_d1;
  543         gc = XCreateGC(disp2, pmap_d2, GCFillStyle | GCTile, &gcvalues);
  544         XFillRectangle(disp2, pmap_d2, gc, 0, 0, scr->width, scr->height);
  545         XFreeGC(disp2, gc);
  546         XSync(disp2, False);
  547         XSync(disp, False);
  548         XFreePixmap(disp, pmap_d1);
  549 
  550         prop_root = XInternAtom(disp2, "_XROOTPMAP_ID", True);
  551         prop_esetroot = XInternAtom(disp2, "ESETROOT_PMAP_ID", True);
  552 
  553         if (prop_root != None && prop_esetroot != None) {
  554             XGetWindowProperty(disp2, root2, prop_root, 0L, 1L,
  555                        False, AnyPropertyType, &type, &format, &length, &after, &data_root);
  556             if (type == XA_PIXMAP) {
  557                 XGetWindowProperty(disp2, root2,
  558                            prop_esetroot, 0L, 1L,
  559                            False, AnyPropertyType,
  560                            &type, &format, &length, &after, &data_esetroot);
  561                 if (data_root && data_esetroot) {
  562                     if (type == XA_PIXMAP && *((Pixmap *) data_root) == *((Pixmap *) data_esetroot)) {
  563                         XKillClient(disp2, *((Pixmap *)
  564                                      data_root));
  565                     }
  566                 }
  567             }
  568         }
  569 
  570         if (data_root)
  571             XFree(data_root);
  572     
  573         if (data_esetroot)
  574             XFree(data_esetroot);
  575 
  576         /* This will locate the property, creating it if it doesn't exist */
  577         prop_root = XInternAtom(disp2, "_XROOTPMAP_ID", False);
  578         prop_esetroot = XInternAtom(disp2, "ESETROOT_PMAP_ID", False);
  579 
  580         if (prop_root == None || prop_esetroot == None)
  581             eprintf("creation of pixmap property failed.");
  582 
  583         XChangeProperty(disp2, root2, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pmap_d2, 1);
  584         XChangeProperty(disp2, root2, prop_esetroot, XA_PIXMAP, 32,
  585                 PropModeReplace, (unsigned char *) &pmap_d2, 1);
  586 
  587         XSetWindowBackgroundPixmap(disp2, root2, pmap_d2);
  588         XClearWindow(disp2, root2);
  589         XFlush(disp2);
  590         XSetCloseDownMode(disp2, RetainPermanent);
  591         XCloseDisplay(disp2);
  592     }
  593     return;
  594 }
  595 
  596 signed char feh_wm_get_wm_is_e(void)
  597 {
  598     static signed char e = -1;
  599 
  600     /* check if E is actually running */
  601     if (e == -1) {
  602         /* XXX: This only covers E17 prior to 6/22/05 */
  603         if ((XInternAtom(disp, "ENLIGHTENMENT_COMMS", True) != None)
  604             && (XInternAtom(disp, "ENLIGHTENMENT_VERSION", True) != None)) {
  605             D(("Enlightenment detected.\n"));
  606             e = 1;
  607         } else {
  608             D(("Enlightenment not detected.\n"));
  609             e = 0;
  610         }
  611     }
  612     return(e);
  613 }
  614 
  615 int feh_wm_get_num_desks(void)
  616 {
  617     char *buf, *ptr;
  618     int desks;
  619 
  620     if (!feh_wm_get_wm_is_e())
  621         return(-1);
  622 
  623     buf = enl_send_and_wait("num_desks ?");
  624     if (buf == IPC_FAKE)    /* Fake E17 IPC */
  625         return(-1);
  626     D(("Got from E IPC: %s\n", buf));
  627     ptr = buf;
  628     while (ptr && !isdigit(*ptr))
  629         ptr++;
  630     desks = atoi(ptr);
  631 
  632     return(desks);
  633 }
  634 
  635 Window enl_ipc_get_win(void)
  636 {
  637 
  638     unsigned char *str = NULL;
  639     Atom prop, prop2, ever;
  640     unsigned long num, after;
  641     int format;
  642     Window dummy_win;
  643     int dummy_int;
  644     unsigned int dummy_uint;
  645 
  646     D(("Searching for IPC window.\n"));
  647 
  648     /*
  649      * Shortcircuit this entire func
  650      * if we already know it's an e17 fake
  651      */
  652     if (e17_fake_ipc)
  653         return(ipc_win);
  654 
  655             prop = XInternAtom(disp, "ENLIGHTENMENT_COMMS", True);
  656     if (prop == None) {
  657         D(("Enlightenment is not running.\n"));
  658         return(None);
  659     } else {
  660         /* XXX: This will only work with E17 prior to 6/22/2005 */
  661         ever = XInternAtom(disp, "ENLIGHTENMENT_VERSION", True);
  662         if (ever == None) {
  663             /* This is an E without ENLIGHTENMENT_VERSION */
  664             D(("E16 IPC Protocol not supported"));
  665             return(None);
  666         }
  667     }
  668     XGetWindowProperty(disp, root, prop, 0, 14, False, AnyPropertyType, &prop2, &format, &num, &after, &str);
  669     if (str) {
  670         sscanf((char *) str, "%*s %x", (unsigned int *) &ipc_win);
  671         XFree(str);
  672     }
  673     if (ipc_win != None) {
  674         if (!XGetGeometry
  675             (disp, ipc_win, &dummy_win, &dummy_int, &dummy_int,
  676              &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint)) {
  677             D((" -> IPC Window property is valid, but the window doesn't exist.\n"));
  678             ipc_win = None;
  679         }
  680         str = NULL;
  681         if (ipc_win != None) {
  682             XGetWindowProperty(disp, ipc_win, prop, 0, 14,
  683                        False, AnyPropertyType, &prop2, &format, &num, &after, &str);
  684             if (str) {
  685                 XFree(str);
  686             } else {
  687                 D((" -> IPC Window lacks the proper atom.  I can't talk to fake IPC windows....\n"));
  688                 ipc_win = None;
  689             }
  690         }
  691     }
  692     if (ipc_win != None) {
  693 
  694         XGetWindowProperty(disp, ipc_win, ever, 0, 14, False,
  695                    AnyPropertyType, &prop2, &format, &num, &after, &str);
  696         if (str) {
  697             /*
  698              * This is E17's way of telling us it's only pretending
  699              * as a workaround for a bug related to the way java handles
  700              * Window Managers.
  701              * (Only valid after date of this comment)
  702              * -- richlowe 2005-06-22
  703              */
  704             XFree(str);
  705             D((" -> Found a fake E17 IPC window, ignoring"));
  706             ipc_win = None;
  707             e17_fake_ipc = 1;
  708             return(ipc_win);
  709         }
  710 
  711         D((" -> IPC Window found and verified as 0x%08x.  Registering feh as an IPC client.\n", (int) ipc_win));
  712         XSelectInput(disp, ipc_win, StructureNotifyMask | SubstructureNotifyMask);
  713         enl_ipc_send("set clientname " PACKAGE);
  714         enl_ipc_send("set version " VERSION);
  715         enl_ipc_send("set email tom@linuxbrit.co.uk");
  716         enl_ipc_send("set web http://www.linuxbrit.co.uk");
  717         enl_ipc_send("set info Feh - be pr0n or be dead");
  718     }
  719     if (my_ipc_win == None) {
  720         my_ipc_win = XCreateSimpleWindow(disp, root, -2, -2, 1, 1, 0, 0, 0);
  721     }
  722     return(ipc_win);
  723 }
  724 
  725 void enl_ipc_send(char *str)
  726 {
  727 
  728     static char *last_msg = NULL;
  729     char buff[21];
  730     register unsigned short i;
  731     register unsigned char j;
  732     unsigned short len;
  733     XEvent ev;
  734 
  735     if (str == NULL) {
  736         if (last_msg == NULL)
  737             eprintf("eeek");
  738         str = last_msg;
  739         D(("Resending last message \"%s\" to Enlightenment.\n", str));
  740     } else {
  741         if (last_msg != NULL) {
  742             free(last_msg);
  743         }
  744         last_msg = estrdup(str);
  745         D(("Sending \"%s\" to Enlightenment.\n", str));
  746     }
  747     if (ipc_win == None) {
  748         if ((ipc_win = enl_ipc_get_win()) == None) {
  749             D(("Hrm. Enlightenment doesn't seem to be running. No IPC window, no IPC.\n"));
  750             return;
  751         }
  752     }
  753     len = strlen(str);
  754     ipc_atom = XInternAtom(disp, "ENL_MSG", False);
  755     if (ipc_atom == None) {
  756         D(("IPC error:  Unable to find/create ENL_MSG atom.\n"));
  757         return;
  758     }
  759     for (; XCheckTypedWindowEvent(disp, my_ipc_win, ClientMessage, &ev););  /* Discard any out-of-sync messages */
  760     ev.xclient.type = ClientMessage;
  761     ev.xclient.serial = 0;
  762     ev.xclient.send_event = True;
  763     ev.xclient.window = ipc_win;
  764     ev.xclient.message_type = ipc_atom;
  765     ev.xclient.format = 8;
  766 
  767     for (i = 0; i < len + 1; i += 12) {
  768         sprintf(buff, "%8x", (int) my_ipc_win);
  769         for (j = 0; j < 12; j++) {
  770             buff[8 + j] = str[i + j];
  771             if (!str[i + j]) {
  772                 break;
  773             }
  774         }
  775         buff[20] = 0;
  776         for (j = 0; j < 20; j++) {
  777             ev.xclient.data.b[j] = buff[j];
  778         }
  779         XSendEvent(disp, ipc_win, False, 0, (XEvent *) & ev);
  780     }
  781     return;
  782 }
  783 
  784 void enl_ipc_timeout(int sig)
  785 {
  786     if (sig == SIGALRM)
  787         timeout = 1;
  788     return;
  789 }
  790 
  791 char *enl_wait_for_reply(void)
  792 {
  793 
  794     XEvent ev;
  795     static char msg_buffer[20];
  796     register unsigned char i;
  797 
  798     alarm(2);
  799     for (; !XCheckTypedWindowEvent(disp, my_ipc_win, ClientMessage, &ev)
  800          && !timeout;);
  801     alarm(0);
  802     if (ev.xany.type != ClientMessage) {
  803         return(IPC_TIMEOUT);
  804     }
  805     for (i = 0; i < 20; i++) {
  806         msg_buffer[i] = ev.xclient.data.b[i];
  807     }
  808     return(msg_buffer + 8);
  809 }
  810 
  811 char *enl_ipc_get(const char *msg_data)
  812 {
  813 
  814     static char *message = NULL;
  815     static size_t len = 0;
  816     char buff[13], *ret_msg = NULL;
  817     register unsigned char i;
  818     unsigned char blen;
  819 
  820     if (msg_data == IPC_TIMEOUT) {
  821         return(IPC_TIMEOUT);
  822     }
  823     for (i = 0; i < 12; i++) {
  824         buff[i] = msg_data[i];
  825     }
  826     buff[12] = 0;
  827     blen = strlen(buff);
  828     if (message != NULL) {
  829         len += blen;
  830         message = (char *) erealloc(message, len + 1);
  831         strcat(message, buff);
  832     } else {
  833         len = blen;
  834         message = (char *) emalloc(len + 1);
  835         strcpy(message, buff);
  836     }
  837     if (blen < 12) {
  838         ret_msg = message;
  839         message = NULL;
  840         D(("Received complete reply:  \"%s\"\n", ret_msg));
  841     }
  842     return(ret_msg);
  843 }
  844 
  845 char *enl_send_and_wait(char *msg)
  846 {
  847     char *reply = IPC_TIMEOUT;
  848     struct sigaction e17_sh, feh_sh;
  849     sigset_t e17_ss;
  850 
  851     /*
  852      * Shortcut this func and return IPC_FAKE
  853      * If the IPC Window is the E17 fake
  854      */
  855     if (e17_fake_ipc)
  856         return IPC_FAKE;
  857 
  858     if (ipc_win == None) {
  859         /* The IPC window is missing.  Wait for it to return or feh to be killed. */
  860         /* Only called once in the E17 case */
  861         for (; enl_ipc_get_win() == None;) {
  862             if (e17_fake_ipc)
  863                 return IPC_FAKE;
  864             else
  865                 sleep(1);
  866         }
  867     }
  868 
  869     if ((sigemptyset(&e17_ss) == -1) || sigaddset(&e17_ss, SIGALRM) == -1) {
  870         weprintf("Failed to set up temporary E17 signal masks");
  871         return reply;
  872     }
  873     e17_sh.sa_handler = enl_ipc_timeout;
  874     e17_sh.sa_mask = e17_ss;
  875     e17_sh.sa_flags = 0;
  876     if (sigaction(SIGALRM, &e17_sh, &feh_sh) == -1) {
  877         weprintf("Failed to set up temporary E17 signal handler");
  878         return reply;
  879     }
  880 
  881     for (; reply == IPC_TIMEOUT;) {
  882         timeout = 0;
  883         enl_ipc_send(msg);
  884         for (; !(reply = enl_ipc_get(enl_wait_for_reply())););
  885         if (reply == IPC_TIMEOUT) {
  886             /* We timed out.  The IPC window must be AWOL.  Reset and resend message. */
  887             D(("IPC timed out.  IPC window has gone. Clearing ipc_win.\n"));
  888             XSelectInput(disp, ipc_win, None);
  889             ipc_win = None;
  890         }
  891     }
  892     if (sigaction(SIGALRM, &feh_sh, NULL) == -1) {
  893         weprintf("Failed to restore signal handler");
  894     }
  895     return(reply);
  896 }