From: <enl...@li...> - 2004-02-21 23:23:15
|
Enlightenment CVS committal Author : xcomputerman Project : e17 Module : proto Dir : e17/proto/esmart/src/trans Modified Files: esmart_trans.c Log Message: Esmart_Trans: Thorough cleanup of pixmap fetch function, modeled after Evidence (thanks Azundris). Fixed bug affecting windows with negative x, y coordinates - partially displayed windows should always render correctly now. =================================================================== RCS file: /cvsroot/enlightenment/e17/proto/esmart/src/trans/esmart_trans.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -3 -r1.6 -r1.7 --- esmart_trans.c 12 Jan 2004 15:54:12 -0000 1.6 +++ esmart_trans.c 21 Feb 2004 23:11:01 -0000 1.7 @@ -30,122 +30,147 @@ static void _esmart_trans_x11_clip_set(Evas_Object *o, Evas_Object *clip); static void _esmart_trans_x11_clip_unset(Evas_Object *o); -/** - * Stolen from ev and iconbar, hopefully this should be shareable now - */ static Evas_Object * -_esmart_trans_x11_pixmap_get(Evas *evas, Evas_Object *old, - int x, int y, int w, int h) +_esmart_trans_x11_pixmap_get(Evas *evas, Evas_Object *old, int x, int y, int w, int h) { - Atom prop,type; - int format; - unsigned long length,after; - unsigned char *data; - Evas_Object *new=NULL; - Pixmap p; - - if(old) - evas_object_del(old); - - if((prop=XInternAtom(ecore_x_display_get(),"_XROOTPMAP_ID",True))!=None) - { - /* FIXME: CACHE ME! */ - int ret=XGetWindowProperty(ecore_x_display_get(), - RootWindow(ecore_x_display_get(), 0), - prop, 0L, 1L, False, AnyPropertyType, &type, - &format,&length, &after,&data); - if((ret==Success)&&(type==XA_PIXMAP)&&((p=*((Pixmap *)data))!=None)) { - Imlib_Image im; - unsigned int pw,ph, pb,pd; - int px,py; - Window win_dummy; - Status st; - - st=XGetGeometry(ecore_x_display_get(),p,&win_dummy, &px,&py,&pw,&ph, &pb, &pd); - if(st&&(pw>0)&&(ph>0)) { -# ifdef NOIR_DEBUG - fprintf(stderr,"bg_ebg_trans: transparency update %3d,%3d %3dx%3d\n",x,y,w,h); -# endif - - imlib_context_set_drawable(*((Pixmap *)data)); - - if((x>=px)&&(y>=py)&&((x+w)<=(py+((signed int)pw)))&&((y+h)<=(py+((signed int)ph)))) - { - im = imlib_create_image_from_drawable (0, x, y, w, h, 1); - imlib_context_set_image (im); - } - else /* tiled root pixmap */ - { - Imlib_Image dst; - int sx, sy, dx, dy; - - im=imlib_create_image_from_drawable(0, px, py, pw, ph, 1); - dst=imlib_create_image(w, h); - imlib_context_set_image(dst); - imlib_image_clear(); - imlib_context_set_cliprect(0, 0, w, h); - - dx = (x%pw); - dy = (y%ph); - - /* There really ought to be a better way to do this, like - * negative coordinates, but I'm not sure those are valid */ - imlib_blend_image_onto_image(im, 1, dx, dy, pw - dx, ph - dy, - 0, 0, pw - dx, ph - dy); - imlib_blend_image_onto_image(im, 1, 0, dy, dx, pw - dy, - pw - dx, 0, dx, ph -dy); - imlib_blend_image_onto_image(im, 1, dx, 0, pw - dx, dy, - 0, ph - dy, pw - dx, dy); - imlib_blend_image_onto_image(im, 1, 0, 0, dx, dy, - pw - dx, ph - dy, dx, dy); - - - for (sx = 0; sx < w; sx += pw) - for (sy = 0; sy < h; sy += ph) - if(sx || sy) - imlib_image_copy_rect(0, 0, pw, ph, sx, sy); - - imlib_context_set_image(im); - imlib_free_image(); - imlib_context_set_image(dst); - } - imlib_image_set_format("argb"); - new=evas_object_image_add(evas); - evas_object_image_alpha_set(new,0); - evas_object_image_size_set(new,w,h); /* thanks rephorm */ - evas_object_image_data_copy_set(new,imlib_image_get_data_for_reading_only()); - imlib_free_image(); - - evas_object_image_fill_set(new,0,0,w,h); - evas_object_resize(new,w,h); - evas_object_move(new,0,0); - evas_object_layer_set(new,-9999); - evas_object_image_data_update_add(new,0,0,w,h); - evas_object_show(new); } -#if 1 - else /* this can happen with e16 */ - /* It would be nice to somehow make this actually attempt to - * get the background pixmap from e16 on alternate desktops. */ - fprintf(stderr,"bg_ebg_trans: got invalid pixmap from root-window, ignoring...\n"); -#endif - } - else - fprintf(stderr,"bg_ebg_trans: could not read root-window property _XROOTPMAP_ID...\n"); } - else - fprintf(stderr,"bg_ebg_trans: could not get XAtom _XROOTPMAP_ID...\n"); - - if(!new) { /* fallback if no root pixmap is found */ -#if 1 - fprintf(stderr,"bg_ebg_trans: cannot create transparency pixmap, no valid wallpaper set.\n"); -#endif - new=evas_object_rectangle_add(evas); - evas_object_resize(new,w,h); - evas_object_move(new,0,0); - evas_object_layer_set(new,-9999); - evas_object_color_set(new, 127,127,127, 255); - evas_object_show(new); } + int ret; + unsigned char *data; + Evas_Object *new = NULL; + Ecore_X_Pixmap p; + Ecore_X_Atom x_pixmap; + Ecore_X_Atom rootpmap, rootcolor; + Ecore_X_Window root, *root_list; + int offscreen = 0; + + int ox = 0, oy = 0; + + if (old) + evas_object_del(old); + + x_pixmap = ecore_x_atom_get("PIXMAP"); + rootpmap = ecore_x_atom_get("_XROOTPMAP_ID"); + rootcolor = ecore_x_atom_get("_XROOTCOLOR_PIXEL"); + root_list = ecore_x_window_root_list(&ret); + if(ret) + root = *root_list; + else + root = 0; /* Paranoid */ + + if (rootpmap) + { + ret = ecore_x_window_prop_property_get(root, rootpmap, + x_pixmap, 32, &data, &ret); + if (ret && (p = *((Ecore_X_Pixmap *) data))) + { + Imlib_Image im; + unsigned int pw, ph; + int px, py; + + ecore_x_pixmap_geometry_get(p, &px, &py, &pw, &ph); + if (pw && ph) { + imlib_context_set_drawable(*((Ecore_X_Pixmap *) data)); + + /* Check if the trans object will fit within the pixmap's boundaries */ + if ((x >= px) && (y >= py) && ((x + w) <= (py + ((signed int) pw))) + && ((y + h) <= (py + ((signed int) ph)))) + { + im = imlib_create_image_from_drawable(0, x, y, w, h, 1); + imlib_context_set_image(im); + } + else + { + Imlib_Image dest; + int sx, sy, dx, dy; + + /* Resolve offscreen coordinates by drawing only visible component */ + if (x < 0) + { + w += x; + ox = -x; + x = 0; + } + + if (y < 0) + { + h += y; + oy = -y; + y = 0; + } + + offscreen = 1; + im = imlib_create_image_from_drawable(0, px, py, pw, ph, 1); + dest = imlib_create_image(w, h); + imlib_context_set_image(dest); + imlib_image_clear(); + imlib_context_set_cliprect(0, 0, w, h); + + dx = x % pw; + dy = y % ph; + + for (sy = 0; sy < (h + dy); sy += ph) + for (sx = 0; sx < (w + dx); sx += pw) + imlib_blend_image_onto_image(im, 1, 0, 0, pw, ph, + sx - dx, sy - dy, pw, ph); + + imlib_context_set_image(im); + imlib_free_image(); + imlib_context_set_image(dest); + } + + imlib_image_set_format("argb"); + new = evas_object_image_add(evas); + evas_object_image_alpha_set(new, 0); + evas_object_image_size_set(new, w, h); + evas_object_image_data_copy_set(new, imlib_image_get_data_for_reading_only()); + imlib_free_image(); + + evas_object_image_fill_set(new, 0, 0, w, h); + evas_object_resize(new, w, h); + evas_object_move(new, ox, oy); + evas_object_layer_set(new, -9999); + evas_object_image_data_update_add(new, 0, 0, w, h); + evas_object_show(new); + } /* if (pw && ph) */ + else /* This could happen with E16: Try to get pixmap from multiple desktop? */ + fprintf(stderr, "Esmart_Trans Error: Got invalid pixmap from root window! Ignored.\n"); + } /* if ((p = *((Ecore_X_Pixmap *) data))) */ + else + { + free(data); + fprintf(stderr, "Esmart_Trans Error: Could not read root window pixmap property!\n"); + } + } /* ecore_x_window_prop_property_get() */ + else + fprintf(stderr, "Esmart_Trans Error: Could not obtain root pixmap atom.\n"); + + if (!new) /* Fallback if no root pixmap is found */ + { + int r = 0, g = 0, b = 0; + + new = evas_object_rectangle_add(evas); + evas_object_resize(new, w, h); + evas_object_move(new, 0, 0); + evas_object_layer_set(new, -9999); + + if (ecore_x_window_prop_property_get(root, rootcolor, ecore_x_atom_get("CARDINAL"), + 32, &data, &ret)) + { + unsigned long pixel = *((unsigned long *) data); + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = pixel & 0xff; + free (data); + } + else + { + fprintf(stderr, "Esmart_Trans Error: Cannot create transparency pixmap: no valid wallpaper and no background color set.\n"); + } + + evas_object_color_set(new, r, g, b, 255); + evas_object_show(new); + } - return new; + return new; } /* keep a global copy of this, so it only has to be created once */ |