/*--------------------------------*-C-*---------------------------------* * File: pixmap.c *----------------------------------------------------------------------* * Copyright (c) 1999 Ethan Fischer * Copyright (c) 1999 Sasha Vasko * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *---------------------------------------------------------------------*/ /*---------------------------------------------------------------------* * Originally written: * 1999 Sasha Vasko *----------------------------------------------------------------------*/ #ifndef lint static const char rcsid[] = "$Id: pixmap.c,v 1.3 2001/09/06 15:57:05 sashav Exp $"; #endif #include "rxvt.h" /* NECESSARY */ #if defined(BACKGROUND_IMAGE) || defined(TRANSPARENT) # include # ifdef XPM # include # endif #endif /*#define BENCHMARK_SHADING 200 */ /*#define DO_CLOCKING */ /*#define GETPIXEL_PUTPIXEL */ /*#define DEBUG_IMAGING */ #if defined(DO_CLOCKING) || defined(BENCHMARK_SHADING) #include #endif #ifdef DEBUG_X #define XGetGeometry(dpy,win,r,x,y,w,h,b,d) \ trace_XGetGeometry(__FILE__,__LINE__,dpy,win,r,x,y,w,h,b,d) #endif #if defined(BACKGROUND_IMAGE) || defined(TRANSPARENT) || defined(_MYSTYLE_) /* Xdisplay, Xroot, Xvisual and Xdepth needs to be defined if code is moved to some other prog */ #define CREATE_TRG_PIXMAP(w,h) XCreatePixmap(Xdisplay, Xroot, w, h, Xdepth) /* this comes from libasimage or from ximage_utils.c */ XImage * ScaleXImageToSize (XImage *src, Position width, Position height ); void ShadeXImage( XImage* srcImage, ShadingInfo* shading, GC gc ); int pixmap_error_handler (Display * dpy, XErrorEvent * error) { #ifdef DEBUG_IMAGING fprintf(stderr, "\n aterm caused XError # %u, in resource %lu, Request: %d.%d", error->error_code, error->resourceid, error->request_code, error->minor_code ); #endif return 0; } #ifndef USE_LIBASIMAGE /* used to be LIBASIMAGE_HEADERS*/ void CopyAndShadeArea( Drawable src, Pixmap trg, int x, int y, int w, int h, int trg_x, int trg_y, GC gc, ShadingInfo* shading ) { int (*oldXErrorHandler) (Display *, XErrorEvent *) ; /* we need to check if pixmap is still valid */ oldXErrorHandler = XSetErrorHandler (pixmap_error_handler); if( shading ) { XImage* img ; if( x <0 || y <0 ) return ; if((img = XGetImage (Xdisplay, src, x, y, w, h, AllPlanes, ZPixmap))!= NULL ) { ShadeXImage( img, shading, gc ); XPutImage(Xdisplay, trg, gc, img, 0, 0, trg_x, trg_y, w, h); #ifdef BENCHMARK_SHADING { int i; time_t before, after; double diff; before = time (NULL); for (i = 0; i < BENCHMARK_SHADING; i++) ShadeXImage (img, shading, gc); after = time (NULL); diff = difftime (after, before); printf ("CopyAndShadeArea(): %d shading runs took %.0f seconds\n", BENCHMARK_SHADING, diff); } #endif XDestroyImage( img ); return ; } } if( !XCopyArea (Xdisplay, src, trg, gc, x, y, w, h, trg_x, trg_y)) XFillRectangle( Xdisplay, trg, gc, trg_x, trg_y, w, h ); XSetErrorHandler (oldXErrorHandler); } int FillPixmapWithTile (Pixmap pixmap, Pixmap tile, int x, int y, int width, int height, int tile_x, int tile_y) { if (tile != None && pixmap != None) { GC gc; XGCValues gcv; gcv.tile = tile; gcv.fill_style = FillTiled; gcv.ts_x_origin = -tile_x; gcv.ts_y_origin = -tile_y; gc = XCreateGC (Xdisplay, tile, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); XFillRectangle (Xdisplay, pixmap, gc, x, y, width, height); XFreeGC (Xdisplay, gc); return 1; } return 0; } void ShadeTiledPixmap(Pixmap src, Pixmap trg, int src_w, int src_h, int x, int y, int w, int h, GC gc, ShadingInfo* shading) { int tile_x, tile_y, left_w, bott_h; tile_x = x%src_w ; tile_y = y%src_h ; left_w = min(src_w-tile_x,w); bott_h = min(src_h-tile_y,h); /*fprintf( stderr, "\nShadeTiledPixmap(): tile_x = %d, tile_y = %d, left_w = %d, bott_h = %d, SRC = %dx%d TRG=%dx%d", tile_x, tile_y, left_w, bott_h, src_w, src_h, w, h);*/ CopyAndShadeArea( src, trg, tile_x, tile_y, left_w, bott_h, 0, 0, gc, shading ); if( bott_h < h ) { /* right-top parts */ CopyAndShadeArea( src, trg, tile_x, 0, left_w, h-bott_h, 0, bott_h, gc, shading ); } if( left_w < w ) { /* left-bott parts */ CopyAndShadeArea( src, trg, 0, tile_y, w-left_w, bott_h, left_w, 0, gc, shading ); if( bott_h < h ) /* left-top parts */ CopyAndShadeArea( src, trg, 0, 0, w-left_w, h-bott_h, left_w, bott_h, gc, shading ); } } Pixmap ShadePixmap (Pixmap src, int x, int y, int width, int height, GC gc, ShadingInfo* shading ) { Pixmap trg = CREATE_TRG_PIXMAP(width, height); if( trg != None ) { CopyAndShadeArea( src, trg, x, y, width, height, 0, 0, gc, shading ); } return trg ; } Pixmap ScalePixmap (Pixmap src, int src_w, int src_h, int width, int height, GC gc, ShadingInfo* shading ) { XImage *srcImage, *trgImage; Pixmap trg = None; if (src != None) { if ((srcImage = XGetImage (Xdisplay, src, 0, 0, src_w, src_h, AllPlanes, ZPixmap)) != NULL) { if ((trgImage = ScaleXImageToSize (srcImage, (Dimension) width, (Dimension) height)) != NULL) { if ((trg = CREATE_TRG_PIXMAP(width, height)) != 0) { if( shading ) ShadeXImage( trgImage, shading, gc ); XPutImage (Xdisplay, trg, gc, trgImage, 0, 0, 0, 0, width, height); #ifdef BENCHMARK_SHADING { int i; time_t before, after; double diff; before = time (NULL); for (i = 0; i < BENCHMARK_SHADING; i++) ShadeXImage (trgImage, shading, gc); after = time (NULL); diff = difftime (after, before); printf ("ScalePixmap(): %d shading runs took %.0f seconds\n", BENCHMARK_SHADING, diff); } #endif } XDestroyImage (trgImage); } XDestroyImage (srcImage); } } return trg; } Pixmap CenterPixmap( Pixmap src, int src_w, int src_h, int width, int height, GC gc, ShadingInfo* shading) { int x, y, w, h, src_x = 0, src_y = 0 ; Pixmap trg ; /* create target pixmap of the size of the window */ trg = CREATE_TRG_PIXMAP(width, height); if( trg != None ) { /* fill it with background color */ XFillRectangle(Xdisplay, trg, gc, 0, 0, width, height); /* place image at the center of it */ x = (width-src_w)>>1 ; y = (height-src_h)>>1 ; if( x < 0 ) { src_x -= x ; w = min(width,src_w+x) ; x = 0 ; }else w = min(width, src_w) ; if( y < 0 ) { src_y -= y ; h = min(height, src_h+y); y = 0 ; }else h = min(height, src_h); CopyAndShadeArea( src, trg, src_x, src_y, w, h, x, y, gc, shading); } return trg ; } Pixmap GrowPixmap( Pixmap src, int src_w, int src_h, int width, int height, GC gc, ShadingInfo* shading) { int w, h; Pixmap trg ; /* create target pixmap of the size of the window */ trg = CREATE_TRG_PIXMAP(width, height); if( trg != None ) { /* fill it with background color */ XFillRectangle(Xdisplay, trg, gc, 0, 0, width, height); /* place image at the center of it */ w = min(width, src_w) ; h = min(height, src_h); CopyAndShadeArea( src, trg, 0, 0, w, h, 0, 0, gc, shading); } return trg ; } /* PROTO */ int GetRootDimensions( int* width, int* height ) { Window root ; int w_x, w_y ; unsigned int w_w, w_h, border_w, w_depth ; if( !XGetGeometry( Xdisplay, Xroot, &root, &w_x, &w_y, width, height, &border_w, &w_depth )) { *width = 0 ; *height = 0 ; } return (*width>0 && *height>0)?1:0 ; } int GetWinPosition (Window win, int *x, int *y) { Window root, parent, *children ; unsigned int nchildren ; static int rootWidth = 0, rootHeight = 0; XWindowAttributes attr ; int my_x, my_y, dumm ; unsigned int w, h, udumm ; XGetWindowAttributes( Xdisplay, win, &attr ); if( attr.map_state != IsViewable ) return 0; if( !x ) x = &my_x ; if( !y ) y = &my_y ; *x = 0 ; *y = 0 ; if( !rootWidth || !rootHeight ) if( !GetRootDimensions(&rootWidth, &rootHeight)) return 0; XGetGeometry( Xdisplay, win, &root, &dumm, &dumm, &w, &h, &udumm, &udumm ); while( XQueryTree( Xdisplay, win, &root, &parent, &children, &nchildren ) ) { int w_x, w_y ; unsigned int border_w ; if( children ) XFree( children ); if( !XGetGeometry( Xdisplay, win, &root, &w_x, &w_y, &udumm, &udumm, &border_w, &udumm )) break ; (*x)+=w_x+(int)border_w ; (*y)+=w_y+(int)border_w ; if( parent == root ) {/* taking in to consideration virtual desktopping */ int bRes = 1 ; if( *x>=rootWidth || (*x+(int)w) <= 0 || *y>=rootHeight || (*y+(int)h) <= 0 ) bRes = 0 ; /* don't want to return position outside the screen even if we fail */ /* while( *x < 0 ) *x += rootWidth ; while( *y < 0 ) *y += rootHeight ; while( *x+(int)w > rootWidth ) *x -= rootWidth ; while( *y+(int)h > rootHeight) *y -= rootHeight ; */ return bRes; } win = parent ; } *x = 0 ; *y = 0 ; return 0 ; } void sleep_a_little (int n) { struct timeval value; if (n <= 0) return; value.tv_usec = n % 1000000; value.tv_sec = n / 1000000; (void) select (1, 0, 0, 0, &value); } static Pixmap CutPixmap ( Pixmap src, Pixmap trg, int x, int y, unsigned int src_w, unsigned int src_h, unsigned int width, unsigned int height, GC gc, ShadingInfo * shading) { Bool my_pixmap = (trg == None )?True:False ; int screen_w, screen_h ; int offset_x = 0, offset_y = 0 ; screen_w = DisplayWidth( Xdisplay, Xscreen ); screen_h = DisplayHeight( Xdisplay, Xscreen ); while( x+(int)width < 0 ) x+= screen_w ; while( x >= screen_w ) x-= screen_w ; while( y+(int)height < 0 ) y+= screen_h ; while( y >= screen_h ) y-= screen_h ; if (width < 2 || height < 2 ) return trg; if( x < 0 ) { offset_x = (-x) ; x = 0 ; width -= offset_x ; } if( y < 0 ) { offset_y = (-y) ; y = 0 ; height -= offset_y ; } if( x+width >= screen_w ) width = screen_w - x ; if( y+height >= screen_h ) height = screen_h - y ; if (src == None) /* we don't have root pixmap ID */ { /* we want to create Overrideredirect window overlapping out window with background type of Parent Relative and then grab it */ XSetWindowAttributes attr ; XEvent event ; int tick_count = 0 ; Bool grabbed = False ; attr.background_pixmap = ParentRelative ; attr.backing_store = Always ; attr.event_mask = ExposureMask ; attr.override_redirect = True ; src = XCreateWindow(Xdisplay, Xroot, x, y, width, height, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixmap|CWBackingStore|CWOverrideRedirect|CWEventMask, &attr); if( src == None ) return trg ; XGrabServer( Xdisplay ); grabbed = True ; XMapRaised( Xdisplay, src ); XSync(Xdisplay, False ); /* now we have to wait for our window to become mapped - waiting for Expose */ for( tick_count = 0 ; !XCheckWindowEvent( Xdisplay, src, ExposureMask, &event ) && tick_count < 100 ; tick_count++) sleep_a_little(100); if( tick_count < 100 ) { if( trg == None ) trg = CREATE_TRG_PIXMAP (width+offset_x, height+offset_y); if (trg != None) { /* custom code to cut area, so to ungrab server ASAP */ if (shading) { XImage *img; img = XGetImage (Xdisplay, src, 0, 0, width, height, AllPlanes, ZPixmap); XDestroyWindow( Xdisplay, src ); src = None ; XUngrabServer( Xdisplay ); grabbed = False ; if (img != NULL) { ShadeXImage (img, shading, gc); XPutImage (Xdisplay, trg, gc, img, 0, 0, offset_x, offset_y, width, height); #ifdef BENCHMARK_SHADING { int i; time_t before, after; double diff; before = time (NULL); for (i = 0; i < BENCHMARK_SHADING; i++) ShadeXImage (img, shading, gc); after = time (NULL); diff = difftime (after, before); printf ("CutPixmap(): %d shading runs took %.0f seconds\n", BENCHMARK_SHADING, diff); } #endif XDestroyImage (img); }else if( my_pixmap ) { XFreePixmap( Xdisplay, trg ); trg = None ; } }else XCopyArea (Xdisplay, src, trg, gc, 0, 0, width, height, offset_x, offset_y); } } if( src ) XDestroyWindow( Xdisplay, src ); if( grabbed ) XUngrabServer( Xdisplay ); return trg ; } /* we have root pixmap ID */ /* find out our coordinates relative to the root window */ if (x + width > src_w || y + height > src_h) { /* tiled pixmap processing here */ Pixmap tmp ; width = min (width, src_w); height = min (height, src_h); tmp = CREATE_TRG_PIXMAP (width, height); if (tmp != None) { ShadeTiledPixmap (src, tmp, src_w, src_h, x, y, width, height, gc, shading); if( trg == None ) trg = CREATE_TRG_PIXMAP (width+offset_x, height+offset_y); if( trg != None ) XCopyArea (Xdisplay, tmp, trg, gc, 0, 0, width, height, offset_x, offset_y); XFreePixmap( Xdisplay, tmp ); return trg; } } /* create target pixmap of the size of the window */ if( trg == None ) trg = CREATE_TRG_PIXMAP (width+offset_x, height+offset_y); if (trg != None) { /* cut area */ CopyAndShadeArea (src, trg, x, y, width, height, offset_x, offset_y, gc, shading); } return trg; } Pixmap CutWinPixmap (Window win, Drawable src, int src_w, int src_h, int width, int height, GC gc, ShadingInfo * shading) { unsigned int x = 0, y = 0; if( src == None ) { #ifndef TRANSPARENT return None ; #else if( !(Options & Opt_transparent)) return None ; #endif } if (!GetWinPosition (win, &x, &y)) return None; return CutPixmap( src, None, x, y, src_w, src_h, width, height, gc, shading ); } /* PROTO */ Pixmap GetRootPixmap(Atom id) { Pixmap currentRootPixmap = None; if( id == None ) id = XInternAtom (Xdisplay, "_XROOTPMAP_ID", True); if( id != None ) { Atom act_type; int act_format; unsigned long nitems, bytes_after; unsigned char *prop = NULL; /*fprintf(stderr, "\n aterm GetRootPixmap(): root pixmap is set"); */ if (XGetWindowProperty (Xdisplay, Xroot, id, 0, 1, False, XA_PIXMAP, &act_type, &act_format, &nitems, &bytes_after, &prop) == Success) { if (prop) { currentRootPixmap = *((Pixmap *) prop); XFree (prop); /*fprintf(stderr, "\n aterm GetRootPixmap(): root pixmap is [%lu]", currentRootPixmap); */ } } } return currentRootPixmap ; } Pixmap ValidatePixmap(Pixmap p, int bSetHandler, int bTransparent, unsigned int *pWidth, unsigned int *pHeight) { int (*oldXErrorHandler) (Display *, XErrorEvent *) ; /* we need to check if pixmap is still valid */ Window root; int junk; if( bSetHandler ) oldXErrorHandler = XSetErrorHandler (pixmap_error_handler); if(bTransparent) p = GetRootPixmap( None ); if( !pWidth ) pWidth = &junk ; if( !pHeight ) pHeight = &junk ; if( p != None ) { if (!XGetGeometry (Xdisplay, p, &root, &junk, &junk, pWidth, pHeight, &junk, &junk)) p = None ; } if( bSetHandler ) XSetErrorHandler (oldXErrorHandler); return p ; } #endif /* LIBASIMAGE_HEADERS */ /***************************************************************************/ /* Down below goes aterm specific functions */ /***************************************************************************/ #define BG TermWin.background /*for convinience*/ /* PROTO */ int GetMyPosition( int* x, int* y ) { int bRet = 0 ; int (*old) (Display *, XErrorEvent *) = XSetErrorHandler (pixmap_error_handler); bRet = GetWinPosition( TermWin.vt, x, y ); XSetErrorHandler (old); return bRet ; } void FreeTargetPixmap() { if( BG.trgPixmap != None ) { XFreePixmap( Xdisplay, BG.trgPixmap ); /*just in case*/ BG.trgPixmap = None ; } } /* PROTO */ Pixmap SetSrcPixmap(Pixmap p) { if( BG.srcPixmap != None && BG.bMySource ) { XFreePixmap( Xdisplay, BG.srcPixmap ); BG.srcPixmap = p ; BG.bMySource = 0 ; } BG.srcPixmap = p ; BG.Width = 0 ; BG.Height = 0 ; if( BG.srcPixmap != None ) { Window root; unsigned int dum, w, h; int dummy; if (XGetGeometry (Xdisplay, BG.srcPixmap, &root, &dummy, &dummy, &w, &h, &dum, &dum)) { BG.Width = w ; BG.Height = h ; } } } /* PROTO */ void ValidateSrcPixmap(int bSetHandler) { if( !BG.bMySource ) { /* we need to check if pixmap is still valid */ Pixmap new_p ; new_p = ValidatePixmap( BG.srcPixmap , bSetHandler, ((Options & Opt_transparent) && BG.trgType != BGT_None), NULL, NULL ); if( new_p != BG.srcPixmap ) SetSrcPixmap(new_p); } } #ifdef _MYSTYLE_ Pixmap RenderMyStylePixmap( MyStyle *style, Pixmap root_pmap, unsigned int root_pmap_width, unsigned int root_pmap_height, unsigned int width, unsigned int height ) { /* fprintf( stderr, "Entering RenderMyStylePixmap : texture_type = %d\n", style->texture_type ); */ if (style->texture_type == TEXTURE_SOLID) return None; else if (style->texture_type < TEXTURE_PIXMAP) /* gradients */ return mystyle_make_pixmap (style, width, height, None); else if (style->texture_type == TEXTURE_PIXMAP) return style->back_icon.pix; else if (style->texture_type > TEXTURE_PIXMAP) { int real_x, real_y ; GetMyPosition( &real_x, &real_y); return mystyle_make_pixmap_overlay (style, real_x, real_y, width, height, None); } return None ; } #endif /* PROTO */ void RenderPixmap(int DontCheckSource ) { XGCValues gcvalue; GC gc; unsigned int width = TermWin_TotalWidth(); unsigned int height = TermWin_TotalHeight(); unsigned int fin_width, fin_height ; int (*oldXErrorHandler) (Display *, XErrorEvent *) ; /* for convinience only */ fin_width = width ; fin_height = height ; /*fprintf(stderr, "\n aterm: entering RenderPixmap, window size is %dx%d, trg_type = %d", width, height, BG.trgType ); */ gcvalue.foreground = PixColors[Color_bg]; gc = XCreateGC(Xdisplay, TermWin.vt, GCForeground, &gcvalue); /* we have some nice processing of all the X errors built in */ /* so let's not let us crash if anything goes wrong */ oldXErrorHandler = XSetErrorHandler (pixmap_error_handler); if( !DontCheckSource ) ValidateSrcPixmap( 0 ); if( BG.srcPixmap == None #ifdef _MYSTYLE_ && BG.trgType != BGT_MyStyle #endif ) { #ifdef TRANSPARENT if(!(Options & Opt_transparent) || BG.trgType == BGT_None) #endif { XSetErrorHandler (oldXErrorHandler); return ; /* nothing to do here */ } } /*fprintf(stderr, "\n aterm RenderPixmap(): freeing target pixmap ..."); */ if( BG.trgPixmap != BG.srcPixmap ) FreeTargetPixmap(); switch( BG.trgType ) { #define SHADING ((BG.bMySource)?NULL:&(BG.Shading)) case BGT_Tile : /* just copying source PixampID into trgPixmapID */ if( BG.bMySource || NO_NEED_TO_SHADE(BG.Shading)) { BG.trgPixmap = BG.srcPixmap ; fin_width = BG.Width ; fin_height = BG.Height; }else if( (BG.finWidth != width || BG.finHeight!=height ) && (BG.Width != BG.finWidth || BG.Height != BG.finHeight)) { fin_width = min(BG.Width, width); fin_height = min(BG.Height, height); BG.trgPixmap = ShadePixmap(BG.srcPixmap, 0, 0, fin_width, fin_height, gc, SHADING); } break ; case BGT_Center : /* more complicated case */ if( BG.finWidth != width || BG.finHeight!=height ) { /*fprintf(stderr, "\n aterm RenderPixmap(): (BGT_Center)src pixmap is [%lu]",BG.srcPixmap); */ BG.trgPixmap = CenterPixmap( BG.srcPixmap, BG.Width, BG.Height, width, height, gc, SHADING ); } break ; case BGT_Scale : if( BG.finWidth != width || BG.finHeight!=height ) { /*fprintf(stderr, "\n aterm RenderPixmap(): (BGT_Scale) src pixmap is [%lu]",BG.srcPixmap);*/ BG.trgPixmap = ScalePixmap( BG.srcPixmap, BG.Width, BG.Height, width, height, gc, SHADING ); } break ; case BGT_ScaleH : if( BG.finWidth != width ) { BG.trgPixmap = ScalePixmap( BG.srcPixmap, BG.Width, BG.Height, width, BG.Height, gc, SHADING ); fin_height = BG.Height; } break ; case BGT_ScaleV : if( BG.finHeight!=height ) { BG.trgPixmap = ScalePixmap( BG.srcPixmap, BG.Width, BG.Height, BG.Width, height, gc, SHADING ); fin_width = BG.Width ; } break ; case BGT_NoTile : if( BG.finWidth != width || BG.finHeight!=height ) { BG.trgPixmap = GrowPixmap( BG.srcPixmap, BG.Width, BG.Height, width, height, gc, SHADING ); } break ; case BGT_NoTileH : if( BG.finWidth != width ) { BG.trgPixmap = GrowPixmap( BG.srcPixmap, BG.Width, BG.Height, width, BG.Height, gc, SHADING ); fin_height = BG.Height; } break ; case BGT_NoTileV : if( BG.finHeight!=height ) { BG.trgPixmap = GrowPixmap( BG.srcPixmap, BG.Width, BG.Height, BG.Width, height, gc, SHADING ); fin_width = BG.Width ; } break ; case BGT_Cut : /*fprintf(stderr, "\n aterm RenderPixmap(): (BG_Cut)src pixmap is [%lu]",BG.srcPixmap); */ BG.trgPixmap = CutWinPixmap( TermWin.vt, BG.srcPixmap, BG.Width, BG.Height, width, height, gc, SHADING ); break ; #ifdef _MYSTYLE_ case BGT_MyStyle : BG.trgPixmap = RenderMyStylePixmap( BG.mystyle, BG.srcPixmap, BG.Width, BG.Height, width, height ); if( BG.mystyle->texture_type == TEXTURE_PIXMAP) { BG.srcPixmap = BG.mystyle->back_icon.pix ; /* so not to free it later */ BG.bMySource = False ; } break ; #endif } XFreeGC(Xdisplay, gc); /* don't need anymore */ if( BG.trgPixmap != None ) { BG.finWidth = fin_width ; BG.finHeight = fin_height; XSync(Xdisplay, 0); XSetWindowBackgroundPixmap(Xdisplay, TermWin.vt, BG.trgPixmap); TermWin.LastPixmapUsed = BG.srcPixmap ; BG.trgPixmapSet = 1 ; if( BG.trgPixmap != BG.srcPixmap ) {/* don't need it anymore server has it */ XFreePixmap( Xdisplay, BG.trgPixmap ); XSync(Xdisplay, 0); } BG.trgPixmap = None ; } /* restore old handler so we can crash again ;) */ XSetErrorHandler (oldXErrorHandler); } /******************************* RenderPixmap **********************/ #endif /* BACKGROUND_IMAGE || TRANSPARENT */ #ifdef BACKGROUND_IMAGE /* we need this stuff only to load background image from file */ #ifdef USE_LIBASIMAGE #ifndef LoadImage Pixmap LoadImageWithMask( Display *dpy, Window w, unsigned long max_colors, const char* realfilename, Pixmap* pMask ); #endif #endif /* PROTO */ int parse_pixmap_geom(const char *geom) { int w = 0, h = 0, x = 0, y = 0; int flags, changed = 0; if (geom == NULL) return 0; if (!strlen(geom)) return 0; if (!strcmp(geom, "?")) { static char str[] = "[10000x10000+10000+10000]"; /* should be big enough */ sprintf(str, "[%dx%d+%d+%d]", BG.srcWidth, BG.srcHeight, BG.srcX, BG.srcY ); xterm_seq(XTerm_title, str); return 0; } /*fprintf( stderr, "\n parse_pixmap_geom(): geometry is [%s]", geom );*/ flags = XParseGeometry(geom, &x, &y, (unsigned int *) &w, (unsigned int *) &h); if(!(flags & XValue)) x = 0 ; if(!(flags & YValue)) y = 0 ; if(!(flags & WidthValue)) w = -1 ; if(!(flags & HeightValue)) h = -1 ; MIN_IT(x, 10000); MIN_IT(y, 10000); MIN_IT(w, 10000); MIN_IT(h, 10000); if( w != BG.srcWidth ) { changed++; BG.srcWidth = w ; } if( h != BG.srcHeight ) { changed++; BG.srcHeight = h ; } if( x != BG.srcX ) { changed++; BG.srcX = x ; } if( y != BG.srcY ) { changed++; BG.srcY = y ; } /*fprintf( stderr, "\n parse_pixmap_geom(): geometry is [%dx%d+%d+%d]", w,h,x,y ); */ return changed; } /* PROTO */ void LoadBGPixmap(const char *file) { XpmAttributes xpmAttr; char *realfilename; assert(file != NULL); if (BG.srcPixmap != None && BG.bMySource ) { XFreePixmap(Xdisplay, BG.srcPixmap); BG.srcPixmap = None; } if (*file != '\0') { /* search environment variables here too */ if ((realfilename = (char *)File_find(file, ".xpm")) == NULL ) { #ifndef USE_LIBASIMAGE print_error("couldn't load XPM file [%s]", file); #endif }else { xpmAttr.closeness = 30000; xpmAttr.colormap = Xcmap; xpmAttr.visual = Xvisual; xpmAttr.depth = Xdepth; xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual | XpmDepth | XpmSize | XpmReturnPixels); #ifdef USE_LIBASIMAGE if( (BG.srcPixmap = LoadImageWithMask( Xdisplay, Xroot, 256, realfilename, NULL )) != None ) { Window root; int x, y ; unsigned int bw, depth ; if( XGetGeometry( Xdisplay, BG.srcPixmap, &root, &x, &y, &(xpmAttr.width), &(xpmAttr.height),&bw, &depth )==0) { xpmAttr.width = 0 ; xpmAttr.height = 0 ; } } #else if( XpmReadFileToPixmap(Xdisplay, Xroot, realfilename, &BG.srcPixmap, NULL, &xpmAttr) != 0 ) print_error("couldn't load XPM file [%s]", realfilename); #endif } } /* need to add geometry processing code here */ if( BG.srcPixmap == None ) { XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[Color_bg]); BG.bMySource = 0 ; BG.Width = 0 ; BG.Height = 0; BG.trgPixmapSet = 0 ; } else { BG.bMySource = 1 ; BG.Width = xpmAttr.width; BG.Height = xpmAttr.height; if( BG.srcWidth > 0 || BG.srcHeight > 0 || BG.srcX > 0 || BG.srcY > 0 ) { int w, h; Pixmap tmp ; if( BG.srcWidth <=0 ) w = BG.Width ; else w = min(BG.Width-BG.srcX,BG.srcWidth); if( BG.srcHeight <=0 ) h = BG.Height ; else h = min(BG.Height-BG.srcY,BG.srcHeight); tmp = ShadePixmap(BG.srcPixmap, BG.srcX, BG.srcY, w, h, DefaultGC(Xdisplay, Xscreen ), &(BG.Shading) ); if( tmp != None ) { XFreePixmap( Xdisplay, BG.srcPixmap ); BG.srcPixmap = tmp ; BG.Width = w ; BG.Height = h ; } } else if( !NO_NEED_TO_SHADE(BG.Shading) ) { Pixmap tmp ; GC gc = DefaultGC(Xdisplay, Xscreen ); tmp = ShadePixmap(BG.srcPixmap, 0, 0, BG.Width, BG.Height, DefaultGC(Xdisplay, Xscreen ), &(BG.Shading) ); if( tmp != None ) { XFreePixmap( Xdisplay, BG.srcPixmap ); BG.srcPixmap = tmp ; } } RenderPixmap(1); } scr_touch(); } #endif /* BACKGROUND_IMAGE */