Logo Search packages:      
Sourcecode: adesklets version File versions

xwindow.c

/*--- xwindow.c ----------------------------------------------------------------
Copyright (C) 2004, 2005 Sylvain Fourmanoit <syfou@users.sourceforge.net>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies of the Software and its documentation and acknowledgment shall be
given in the documentation and software packages that this Software was
used.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.   
------------------------------------------------------------------------------*/
/* Miscellaneous routines related to X Windows */

/*----------------------------------------------------------------------------*/
#include "xwindow.h"                /* X Windows related stuff */

#ifdef HAVE_LIBGEN_H
#include <libgen.h>                 /* dirname() function */
#endif

#ifdef HAVE_STRING_H
#include <string.h>                 /* strlen, strcpy functions */
#endif

/*----------------------------------------------------------------------------*/
#ifndef X_DISPLAY_MISSING
XSetWindowAttributes XDefaultWindowAttributes = {
  ParentRelative, /* Pixmap background_pixmap */
  0L,                   /* unsigned long background_pixel */
  0,              /* Pixmap border_pixmap */    
  0L,                   /* unsigned long border_pixel */
  0,              /* int bit_gravity */         
  0,              /* int win_gravity */         
  Always,         /* int backing_store */       
  0L,                   /* unsigned long backing_planes */
  0L,                   /* unsigned long backing_pixel */
  False,          /* Bool save_under */         
  BASE_EVENT_MASK,      /* long event_mask */         
  0L,                   /* long do_not_propagate_mask */
  True,           /* Bool override_redirect */  
  0,              /* Colormap colormap */       
  0               /* Cursor cursor */           
};

XErrorEvent xerror_event = {
  0,              /* int type */
  NULL,           /* Display *display */
  0L,                   /* unsigned long serial */
  0,              /* unsigned char error_code */
  0,              /* unsigned char request_code */
  0,              /* unsigned char minor_code */
  0               /* XID resourceid */
};
#endif

/*----------------------------------------------------------------------------*/
typedef struct s_context_backup {
  long                 context;
  Display            * display;
  Visual             * visual;
  Colormap             colormap;
  Drawable             drawable;
  Pixmap               mask;
  char                 dither_mask,
                       anti_alias,
                       dither,
                       blend;
  Imlib_Color_Modifier color_modifier;
  Imlib_Color_Range    color_range;
  Imlib_Operation      operation;
  Imlib_Font           font;
  Imlib_Text_Direction direction;
  double               angle;
  int                  red, 
                       green, 
                       blue, 
                       alpha;
  Imlib_Image          image;
  Imlib_Filter         filter;
} context_backup;

vector * contextes = NULL;

/*----------------------------------------------------------------------------*/
/* If present on the system, uses fontconfig to find all paths 
   containing truetype fonts: reused almost verbatim from fc-list source. 
*/
void 
xwindow_locate_truetype_fonts(void)
{
#ifdef HAVE_FONTCONFIG_FONTCONFIG_H
  int          j;
  FcObjectSet *os = 0;
  FcFontSet   *fs;
  FcPattern   *pat;
  FcChar8     *file;
#endif
#ifdef PKGDATADIR
  if (strlen(PKGDATADIR))
    imlib_add_path_to_font_path(PKGDATADIR);
#endif
#ifdef HAVE_FONTCONFIG_FONTCONFIG_H
  if (FcInit()) {
    pat = FcNameParse((FcChar8 *)":");
    os  = FcObjectSetCreate();
    FcObjectSetAdd(os, "file"); 
    fs = FcFontList(0, pat, os);
    if(pat) FcPatternDestroy(pat);
    if(fs) {
      for (j = 0; j < fs->nfont; j++)
      if (FcPatternGetString(fs->fonts[j], FC_FILE, 0, &file)==FcResultMatch)
        if ((strlen((char*)file)>4) && 
            (strstr((char*)file+strlen((char*)file)-4,".ttf")))
          imlib_add_path_to_font_path(dirname((char*)file));
      FcFontSetDestroy(fs);
      FcObjectSetDestroy(os);
    }
  }
#endif
  imlib_add_path_to_font_path(".");
#ifdef DEBUG
  imlib_add_path_to_font_path("../sharedata");
#endif
}

/*----------------------------------------------------------------------------*/
#ifndef X_DISPLAY_MISSING

int 
xwindow_non_fatal_error_handler(Display * display , XErrorEvent * ev)
{
  char buffer[1024];

  if(!display) return 0;

  /* Print out error description */
  if (!XGetErrorText(display,ev->error_code,buffer,sizeof(buffer)))
    fprintf(stderr,"Error: with X protocol on display `%s'\n%s\n",
          XDisplayName(NULL),buffer);
  /* Save error description */
  memcpy(&xerror_event,ev,sizeof(XErrorEvent));
  return 0;
}

/*----------------------------------------------------------------------------*/
void 
xwindow_error_reset(void)
{
  memset(&xerror_event,0,sizeof(XErrorEvent));
}

/*----------------------------------------------------------------------------*/
int
xwindow_error_check(void)
{
  return xerror_event.error_code==0;
}

/*----------------------------------------------------------------------------*/
/* Sends back dimensions of given window. */
int
xwindow_window_size(Display * display, Window window, 
                uint * width_return, uint * height_return)
{
  int dummy;
  Window root;
  return display && window && 
    XGetGeometry(display, window, &root,
             &dummy, &dummy, width_return, height_return,
             (uint*)&dummy,(uint*)&dummy);
}

/*----------------------------------------------------------------------------*/
/* Return 1 if given coordinates changed since last call.
   Note: only works with one set of coordinates  */
int
xwindow_window_moved_or_resized(int new_x, int new_y, 
                        int new_width, int new_height)
{
  static int x=-1, y=-1, width=-1, height=-1;
  int result;
  result=!(x==new_x && y==new_y && width==new_width && height==new_height);
  x=new_x;y=new_y;width=new_width;height=new_height;
  return result;
}

/*----------------------------------------------------------------------------*/
/* Returns 1 if background has changed since last call, 0 otherwise.
   This is enlightment mechanism. Go read:
   http://gershwin.ens.fr/vdaniel/Doc-Locale/Outils-Gnu-Linux/Eterm-0.9/#trans
   NOTE: this will always returns 0 when this mechanism is not supported.
 */
int 
xwindow_updated_background(Display * display, Window root, Atom id)
{
  int result=0;
  static Pixmap old_pixmap = None;
  Pixmap pixmap = None;
  Atom act_type;
  int act_format;
  unsigned long nitems, bytes_after;
  unsigned char *prop = NULL;

  if (!(display && root)) return 0;

  if(id==None) id=XInternAtom(display,"_XROOTMAP_ID", True);
  if(id!=None &&
     XGetWindowProperty(display, root, id, 0, 1, False, XA_PIXMAP,
                  &act_type, &act_format, &nitems, &bytes_after,
                  &prop)==Success && 
     prop) {
    pixmap = *((Pixmap *)prop);
    result=(old_pixmap!=pixmap); 
    XFree(prop);
  }

  old_pixmap=pixmap;
  return result;
}

/*----------------------------------------------------------------------------*/
/* Routine to grab the background in Imlib_Image.
   Returns NULL if it fails, Reference to output Imlib_Image otherwise.
 */
Imlib_Image
xwindow_grab_background(Display * display, int screen, Window window)
{
  int x, y;
  XEvent ev;
  Window src;
  XWindowAttributes attr;
  Imlib_Image background=NULL;

  if (!(display && window)) return NULL;

  if(XGetWindowAttributes(display,window,&attr) &&
     /* Avoid reparenting coordinates translation problem */
     XTranslateCoordinates(display,window,RootWindow(display,screen),
                     0, 0, &x, &y, &src)) {
  /* The trick is to create an Overrideredirect window overlapping our
     window with background type of Parent relative and then grab it.
     It seems overkill, but:
     - XGetImage() on root get all viewable children windows embedded.
     - XCopyArea() cause potential synchronisation problems depending
     on backing store settings of root window: playing around
     with GraphicsExpose events is not quicker nor simpler.

     This idea was taken from aterm source base. See src/pixmap.c 
     in core distribution (http://aterm.sourceforge.net/).
  */
    if((src=XCreateWindow(display, 
                    RootWindow(display,screen), 
                    x, y, attr.width, attr.height,
                    0,
                    CopyFromParent, CopyFromParent, CopyFromParent,
                    CWBackPixmap|CWBackingStore|
                    CWOverrideRedirect|CWEventMask,
                    &XDefaultWindowAttributes))) {
      xwindow_context_save(IMLIB_DRAWABLE|IMLIB_IMAGE);
      XGrabServer(display);
      XMapRaised(display,src);
      XSync(display,False);
      do 
      XWindowEvent(display, src, ExposureMask, &ev);
      while(ev.type!=Expose);
      imlib_context_set_drawable(src);
      background=imlib_create_image_from_drawable(0,0,0,
                                      attr.width,attr.height,0);
      XUngrabServer(display);
      XDestroyWindow(display,src);
    
      /* Make sure image has an alpha channel */
      imlib_context_set_image(background);
      imlib_image_set_has_alpha(1);
      
      /* Restore context */
      xwindow_context_restore();
    }
  }
  return background;
}

/*----------------------------------------------------------------------------*/
/* Redraw updates rectangles onto window by copying background image at same
   position.
*/
void
xwindow_update_window(Window window, Imlib_Updates * updates,
                  Imlib_Image background, Imlib_Image foreground,
                  int transparency_flag)
{
  int x,y,width,height;
  Imlib_Image image;  
  Imlib_Updates update;
  
  /* Verify there is something to update */
  if(window && *updates) {
    /* Save context states */
    xwindow_context_save(IMLIB_IMAGE|IMLIB_COLOR|IMLIB_OPERATION|
                   IMLIB_BLEND|IMLIB_COLOR_MODIFIER|IMLIB_FILTER|
                   IMLIB_DRAWABLE);
   
    /* Pre-loop settings */
    imlib_context_set_drawable(window);
    imlib_context_set_blend(0);
    imlib_context_set_color_modifier(NULL);
    imlib_context_set_filter(NULL);
    if(transparency_flag) {
      imlib_context_set_operation(IMLIB_OP_COPY);
    } else
      imlib_context_set_image(foreground);
      
    /* Loop over updates */
    for(update=*updates;
      update;
      update=imlib_updates_get_next(update)) {
      imlib_updates_get_coordinates(update,&x,&y,(int*)&width,(int*)&height);
      if (transparency_flag) {
      if((image=imlib_create_image(width,height))) {
        imlib_context_set_image(image);

        /* Make sur the alpha channel is detected */
        imlib_image_set_has_alpha(1);

        /* Fill image wih full opaque black, then copy
           background over */
        imlib_context_set_color(0,0,0,255);
        imlib_image_fill_rectangle(0,0,width,height);
        imlib_blend_image_onto_image(background,0,
                               x,y,width,height,
                               0,0,width,height);

        /* Blend foreground over background */
        imlib_context_set_blend(1);
        imlib_blend_image_onto_image(foreground,1,
                               x,y,width,height,
                               0,0,width,height);

        /* Copy image to drawable and free it */
        imlib_context_set_blend(0);
        imlib_render_image_on_drawable(x,y);
        imlib_free_image();
      }
      } else
      /* Otherwise, just copy foreground, without alteration */
      imlib_render_image_part_on_drawable_at_size(x,y,width,height,
                                        x,y,width,height);
    }

    /* Restore initial context states */
    xwindow_context_restore();
  }
}

/*----------------------------------------------------------------------------*/
/* This move a window using outline rectangles if a window is mapped, and
   updates cfgfile_item params accordingly. This is used by adesklets
   if we created an `override_notify' window, and that therefore cannot take
   advantage of any windows manager. Returns 1 if the window has been moved, 
   0 othermize.
   NOTE: The window is not remmaped at the end if the move was sucessfull:
   it is the duty of the caller to do so.
*/
int
xwindow_move_window(Display * display, Window root, Window window,
                cfgfile_item * params)
{
  int dummy, grab_x, grab_y, old_x, old_y, x=0, y=0, result=0;
  uint screen_width, screen_height;
  XWindowAttributes attr;
  XGCValues xgcvalues;
  Window dummy_window;
  GC gc;
  Cursor cursor;
  XEvent ev;

  if (!(display && window)) return 0;

  /* Test that main window is mapped,
     and if screen size could be known */
  if(XGetWindowAttributes(display,window,&attr) &&
     attr.map_state!=IsUnmapped &&
     xwindow_window_size(display,root,&screen_width,&screen_height)) {
    /* Initialize a graphics context for the root window behind ours */
    xgcvalues.function=GXxor;
    xgcvalues.foreground=WhitePixel(display,params->scr);
    xwindow_error_reset();
    gc=XCreateGC(display,root,GCFunction|GCForeground,&xgcvalues);
    /* Initialize cursor */
    cursor = XCreateFontCursor(display,XC_fleur);
    /* Initialize old coordinates */
    old_x=attr.x; old_y=attr.y;
    /* Unmap the window */
    if (xwindow_error_check() &&
      XUnmapWindow(display,window)) {
      /* Query, then grab the pointer */
      if(XQueryPointer(display, window, &dummy_window,
                   &dummy_window, &grab_x, &grab_y,
                   &dummy, &dummy, (uint*)&dummy) &&
       XGrabPointer(display,root,True,
                  PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
                  GrabModeAsync,GrabModeAsync,
                  root, cursor, 0)==GrabSuccess) {
      /* Draw initial rectangle */
      XDrawRectangle(display,root,gc,
                   attr.x,attr.y,attr.width-1,attr.height-1);
      dummy=0;
      do {
        XWindowEvent(display,root,
                   PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
                   &ev);
        switch(ev.type) {
        case ButtonPress:
          dummy=1;
          break;
        case ButtonRelease:
          /* We want a button press in our window before we take
             this into account: the idea is that we want to ignore
             button release event from menu */
          if(dummy) {
            /* Erase final rectangle */
            XDrawRectangle(display,root,gc,
                       old_x,old_y,attr.width-1,attr.height-1);
            result=1;
          }
          break;
        case MotionNotify:
          /* Compute new coordinates. */
          x=attr.x+(ev.xmotion.x-grab_x);
          y=attr.y+(ev.xmotion.y-grab_y);
          /* Rectifies it */
          x=((x+attr.width)<screen_width)?x:screen_width-attr.width;
          y=((y+attr.height)<screen_height)?y:screen_height-attr.height;
          x=(x>0)?x:0;
          y=(y>0)?y:0;
          /* Draw rectangles: we use a GCxor function for
           not having to remember background data. */
          if (x!=old_x || y!=old_y) {
            XDrawRectangle(display,root,gc,
                       old_x,old_y,attr.width-1,attr.height-1);
            XDrawRectangle(display,root,gc,
                       x,y,attr.width-1,attr.height-1);
          }
          /* Save coordinates */
          old_x=x; old_y=y;
          break;
        }
      } while(!result);
      XUngrabPointer(display,0);
      if(old_x!=params->x || old_y!=params->y) 
        result=XMoveWindow(display,window,x,y);
      }
      /* Save new coordinates if it changed, remap the window otherwize */
      if(old_x!=params->x||old_y!=params->y) {
      params->x=old_x;
      params->y=old_y;
      } else
      XMapWindow(display,window);
    }
  }
  return result;
}

/*----------------------------------------------------------------------------*/
int
xwindow_resize_window(Display * display, Window window, cfgfile_item * item,
                  int width, int height, int force_update)
{
  int x,y, result=0;
  uint screen_width, screen_height;
  XSizeHints * hints;
  XWindowAttributes attr;

  if (!(display && window)) return 0;

  if (width>0 && height>=0)
    if(XGetWindowAttributes(display, window, &attr))
      if (force_update || width!=attr.width || height!=attr.height) {
      if (attr.override_redirect) {
        /* Unmanaged window: boundaries check */
        screen_width=WidthOfScreen(ScreenOfDisplay(display,item->scr));
        screen_height=HeightOfScreen(ScreenOfDisplay(display,item->scr));
        x=item->x;
        y=item->y;
        x=(x+width>screen_width)?screen_width-width:x;
        y=(y+height>screen_height)?screen_height-height:y;
        
        if (x>=0 && y>=0)
          if (XMoveResizeWindow(display,window,
                          x,y,(uint)width,(uint)height))
            result=1;
      } else {
        /* Managed window: no boundary check */
        xwindow_error_reset();
        XResizeWindow(display,window,(uint)width,(uint)height);
        if(xwindow_error_check()) {
          /* WM_Hints settings */
          if ((hints=XAllocSizeHints())) {
            hints->min_width=hints->max_width=(uint)width;
            hints->min_height=hints->max_height=(uint)height;
            hints->flags=PMinSize|PMaxSize;
            XSetWMNormalHints(display,window,hints);
            XFree(hints);
          }
          result=1;
        }
      }
      }
  return result;
}

/*----------------------------------------------------------------------------*/
/* Looks for the Nautilus desktop window to draw to, given the toplevel
 * window of the Nautilus desktop. Basically recursively calls itself
 * looking for subwindows the same size as the root window. 

 NOTE: This code was copied verbatim from xpenguins-2.2 source code base -
       http://xpenguins.seul.org/
*/
static Window
xwindow_get_nautilus_desktop(Display *display, int screen, Window window,
                       int depth)
{
  Window rootReturn, parentReturn, *children;
  Window winreturn = window;
  unsigned int nChildren;

  if (depth > 5) {
    return ((Window) 0);
  }
  else if (XQueryTree(display, window, &rootReturn, &parentReturn,
             &children, &nChildren)) {
    int i;
    for (i = 0; i < nChildren; ++i) {
      XWindowAttributes attributes;
      if (XGetWindowAttributes(display, children[i], &attributes)) {
      if (attributes.width == DisplayWidth(display, screen)
          && attributes.height == DisplayHeight(display, screen)) {
        /* Found a possible desktop window */
        winreturn = xwindow_get_nautilus_desktop(display, screen,
                                       children[i], depth+1);
      }
      }  
    }
    XFree((char *) children);
  }
  return winreturn;
}

/*----------------------------------------------------------------------------*/
/* Returns the root window, or the fake root window depending on
   WM. Autodetect fake root for Xfce4.
*/
Window
xwindow_get_root_window(Display * display, int scr)
{
  unsigned long dummy;
  Window result = RootWindow(display,scr),
    * toplevel = NULL;
  Atom TYPE, 
    NAUTILUS_DESKTOP_WINDOW_ID = XInternAtom(display,
                                   "NAUTILUS_DESKTOP_WINDOW_ID",
                                   False);

  if (XGetWindowProperty(display, result,
                         NAUTILUS_DESKTOP_WINDOW_ID,
                         0, 1, False, XA_WINDOW,
                         &TYPE, 
                   (int*)((void*)&dummy),
                         &dummy, 
                   &dummy,
                         (unsigned char **)((void*)&toplevel)) == Success
      && toplevel)
    result = xwindow_get_nautilus_desktop(display,scr,*toplevel,0);
  return result;
}

#endif /* X_MISSING_DISPLAY , far, far above! */

/*----------------------------------------------------------------------------*/
/* Save selected elements of imlib2 context for future restoration.
   Note: This uses a vector `contextes' of context_backup references,
         used like a stack (last-in, first-out): this lead to correct
         recursive call of the function pairs xwindow_context_save().
         and xwindow_context_restore().
*/
void
xwindow_context_save(long mycontext)
{
  context_backup * context;

  /* Contextes initialisation */
  if(!contextes && (!(contextes=vector_init()))) {
      debug("Error initialising contexes!\n");
      return;
  }

  /* New context initialisation */
  if(!(context=(context_backup*)malloc(sizeof(context_backup)))) {
    debug("Error initialising new context!\n");
    return;
  }
  
  /* Save present context */
  context->context=mycontext;

#ifdef X_DISPLAY_MISSING
  mycontext&=~(IMLIB_DISPLAY|IMLIB_VISUAL|IMLIB_COLORMAP|IMLIB_DRAWABLE|
             IMLIB_MASK|IMLIB_DITHER_MASK);
#endif

  /* Most frequently saved items are traited first, for optimisation sake */
#define CONTEXT_ACTION(mask, x ) \
  if(mycontext&(mask)) {\
      x ;\
  }\
  if(!(mycontext&=~(mask))) goto end_of_context_save

  CONTEXT_ACTION(IMLIB_IMAGE,
             context->image=imlib_context_get_image());
  CONTEXT_ACTION(IMLIB_COLOR,
             imlib_context_get_color(&context->red,
                               &context->green,
                               &context->blue,
                               &context->alpha));
  CONTEXT_ACTION(IMLIB_BLEND,
             context->blend=imlib_context_get_blend());
  CONTEXT_ACTION(IMLIB_FONT,
             context->font=imlib_context_get_font());
  CONTEXT_ACTION(IMLIB_OPERATION,
             context->operation=imlib_context_get_operation());
  CONTEXT_ACTION(IMLIB_COLOR_RANGE,
             context->color_range=imlib_context_get_color_range());
  CONTEXT_ACTION(IMLIB_FILTER,
             context->filter=imlib_context_get_filter());
#ifndef X_DISPLAY_MISSING
  CONTEXT_ACTION(IMLIB_DISPLAY,
             context->display=imlib_context_get_display());  
  CONTEXT_ACTION(IMLIB_VISUAL,
             context->visual=imlib_context_get_visual());
  CONTEXT_ACTION(IMLIB_COLORMAP,
             context->colormap=imlib_context_get_colormap());
  CONTEXT_ACTION(IMLIB_DRAWABLE,
             context->drawable=imlib_context_get_drawable());
  CONTEXT_ACTION(IMLIB_MASK,
             context->mask=imlib_context_get_mask());
  CONTEXT_ACTION(IMLIB_DITHER_MASK,
             context->dither_mask=imlib_context_get_dither_mask());
#endif
  CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
             context->anti_alias=imlib_context_get_anti_alias());
  CONTEXT_ACTION(IMLIB_DITHER,
             context->dither=imlib_context_get_dither());
  CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
             context->color_modifier=
                imlib_context_get_color_modifier());
  CONTEXT_ACTION(IMLIB_DIRECTION,
             context->direction=imlib_context_get_direction());
  CONTEXT_ACTION(IMLIB_ANGLE,
             context->angle=imlib_context_get_angle());
#undef CONTEXT_ACTION

   /* This code should never be reached ! */
  debug("Error in creating new context!\n");

 end_of_context_save:
  vector_push(contextes,context);
}

/*----------------------------------------------------------------------------*/
/* Restore a given imlib context, somewhere after a call 
   to xwindow_context_save */
void
xwindow_context_restore(void)
{
  context_backup * context;

  /* Verify there is comething to restore */
  if(!contextes || !contextes->pos) {
    debug("No context to restore!\n");
    return;
  }

  /* Commodity setting */
  context=(context_backup*)contextes->content[contextes->pos-1];

  /* Most frequently saved items are traited first, for optimisation sake */
#define CONTEXT_ACTION(mask, x ) \
  if(context->context&(mask)) {\
      x ;\
  }\
  if(!(context->context&=~(mask))) goto end_of_restore_context

  CONTEXT_ACTION(IMLIB_IMAGE,
             imlib_context_set_image(context->image));
  CONTEXT_ACTION(IMLIB_COLOR,
             imlib_context_set_color(context->red,
                               context->green,
                               context->blue,
                               context->alpha));
  CONTEXT_ACTION(IMLIB_BLEND,
             imlib_context_set_blend(context->blend));
  CONTEXT_ACTION(IMLIB_FONT,
             imlib_context_set_font(context->font));
  CONTEXT_ACTION(IMLIB_OPERATION,
             imlib_context_set_operation(context->operation));
  CONTEXT_ACTION(IMLIB_COLOR_RANGE,
             imlib_context_set_color_range(context->color_range));
  CONTEXT_ACTION(IMLIB_FILTER,
             imlib_context_set_filter(context->filter));
#ifndef X_DISPLAY_MISSING
  CONTEXT_ACTION(IMLIB_DISPLAY,
             imlib_context_set_display(context->display));
  CONTEXT_ACTION(IMLIB_VISUAL,
             imlib_context_set_visual(context->visual));
  CONTEXT_ACTION(IMLIB_COLORMAP,
             imlib_context_set_colormap(context->colormap));
  CONTEXT_ACTION(IMLIB_DRAWABLE,
               imlib_context_set_drawable(context->drawable));
  CONTEXT_ACTION(IMLIB_MASK,
             imlib_context_set_mask(context->mask));
  CONTEXT_ACTION(IMLIB_DITHER_MASK,
             imlib_context_set_dither_mask(context->dither_mask));
#endif
  CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
             imlib_context_set_anti_alias(context->anti_alias));
  CONTEXT_ACTION(IMLIB_DITHER,
             imlib_context_set_dither(context->dither));
  CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
             imlib_context_set_color_modifier(context->color_modifier));
  CONTEXT_ACTION(IMLIB_DIRECTION,
             imlib_context_set_direction(context->direction));
  CONTEXT_ACTION(IMLIB_ANGLE,
             imlib_context_set_angle(context->angle));
#undef CONTEXT_ACTION

  /* This code should never be reached ! */
  debug("Error restoring context!\n");

 end_of_restore_context:
  vector_pop(contextes);
  if(!contextes->pos)
    contextes=vector_free(contextes);
}

Generated by  Doxygen 1.6.0   Back to index