Better support for option cleanup in python package
[adesklets.git] / src / xwindow.c
blob3eaf9f7eef9977c82bc3cb644d180a5ce5ba5d2d
1 /*--- xwindow.c ----------------------------------------------------------------
2 Copyright (C) 2004, 2005 Sylvain Fourmanoit <syfou@users.sourceforge.net>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to
6 deal in the Software without restriction, including without limitation the
7 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 sell copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies of the Software and its documentation and acknowledgment shall be
13 given in the documentation and software packages that this Software was
14 used.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 ------------------------------------------------------------------------------*/
23 /* Miscellaneous routines related to X Windows */
25 /*----------------------------------------------------------------------------*/
26 #include "xwindow.h" /* X Windows related stuff */
28 #ifdef HAVE_LIBGEN_H
29 #include <libgen.h> /* dirname() function */
30 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h> /* strlen, strcpy functions */
34 #endif
36 /*----------------------------------------------------------------------------*/
37 #ifndef X_DISPLAY_MISSING
38 XSetWindowAttributes XDefaultWindowAttributes = {
39 ParentRelative, /* Pixmap background_pixmap */
40 0L, /* unsigned long background_pixel */
41 0, /* Pixmap border_pixmap */
42 0L, /* unsigned long border_pixel */
43 0, /* int bit_gravity */
44 0, /* int win_gravity */
45 Always, /* int backing_store */
46 0L, /* unsigned long backing_planes */
47 0L, /* unsigned long backing_pixel */
48 False, /* Bool save_under */
49 BASE_EVENT_MASK, /* long event_mask */
50 0L, /* long do_not_propagate_mask */
51 True, /* Bool override_redirect */
52 0, /* Colormap colormap */
53 0 /* Cursor cursor */
56 XErrorEvent xerror_event = {
57 0, /* int type */
58 NULL, /* Display *display */
59 0L, /* unsigned long serial */
60 0, /* unsigned char error_code */
61 0, /* unsigned char request_code */
62 0, /* unsigned char minor_code */
63 0 /* XID resourceid */
65 #endif
67 /*----------------------------------------------------------------------------*/
68 typedef struct s_context_backup {
69 long context;
70 Display * display;
71 Visual * visual;
72 Colormap colormap;
73 Drawable drawable;
74 Pixmap mask;
75 char dither_mask,
76 anti_alias,
77 dither,
78 blend;
79 Imlib_Color_Modifier color_modifier;
80 Imlib_Color_Range color_range;
81 Imlib_Operation operation;
82 Imlib_Font font;
83 Imlib_Text_Direction direction;
84 double angle;
85 int red,
86 green,
87 blue,
88 alpha;
89 Imlib_Image image;
90 Imlib_Filter filter;
91 } context_backup;
93 vector * contextes = NULL;
95 /*----------------------------------------------------------------------------*/
96 /* If present on the system, uses fontconfig to find all paths
97 containing truetype fonts: reused almost verbatim from fc-list source.
99 void
100 xwindow_locate_truetype_fonts(void)
102 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
103 int j;
104 FcObjectSet *os = 0;
105 FcFontSet *fs;
106 FcPattern *pat;
107 FcChar8 *file;
108 #endif
109 #ifdef PKGDATADIR
110 if (strlen(PKGDATADIR))
111 imlib_add_path_to_font_path(PKGDATADIR);
112 #endif
113 #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
114 if (FcInit()) {
115 pat = FcNameParse((FcChar8 *)":");
116 os = FcObjectSetCreate();
117 FcObjectSetAdd(os, "file");
118 fs = FcFontList(0, pat, os);
119 if(pat) FcPatternDestroy(pat);
120 if(fs) {
121 for (j = 0; j < fs->nfont; j++)
122 if (FcPatternGetString(fs->fonts[j], FC_FILE, 0, &file)==FcResultMatch)
123 if ((strlen((char*)file)>4) &&
124 (strstr((char*)file+strlen((char*)file)-4,".ttf")))
125 imlib_add_path_to_font_path(dirname((char*)file));
126 FcFontSetDestroy(fs);
127 FcObjectSetDestroy(os);
130 #endif
131 imlib_add_path_to_font_path(".");
132 #ifdef DEBUG
133 imlib_add_path_to_font_path("../sharedata");
134 #endif
137 /*----------------------------------------------------------------------------*/
138 #ifndef X_DISPLAY_MISSING
140 int
141 xwindow_non_fatal_error_handler(Display * display , XErrorEvent * ev)
143 char buffer[1024];
145 if(!display) return 0;
147 /* Print out error description */
148 if (!XGetErrorText(display,ev->error_code,buffer,sizeof(buffer)))
149 fprintf(stderr,"Error: with X protocol on display `%s'\n%s\n",
150 XDisplayName(NULL),buffer);
151 /* Save error description */
152 memcpy(&xerror_event,ev,sizeof(XErrorEvent));
153 return 0;
156 /*----------------------------------------------------------------------------*/
157 void
158 xwindow_error_reset(void)
160 memset(&xerror_event,0,sizeof(XErrorEvent));
163 /*----------------------------------------------------------------------------*/
165 xwindow_error_check(void)
167 return xerror_event.error_code==0;
170 /*----------------------------------------------------------------------------*/
171 /* Sends back dimensions of given window. */
173 xwindow_window_size(Display * display, Window window,
174 uint * width_return, uint * height_return)
176 int dummy;
177 Window root;
178 return display && window &&
179 XGetGeometry(display, window, &root,
180 &dummy, &dummy, width_return, height_return,
181 (uint*)&dummy,(uint*)&dummy);
184 /*----------------------------------------------------------------------------*/
185 /* Return 1 if given coordinates changed since last call.
186 Note: only works with one set of coordinates */
188 xwindow_window_moved_or_resized(int new_x, int new_y,
189 int new_width, int new_height)
191 static int x=-1, y=-1, width=-1, height=-1;
192 int result;
193 result=!(x==new_x && y==new_y && width==new_width && height==new_height);
194 x=new_x;y=new_y;width=new_width;height=new_height;
195 return result;
198 /*----------------------------------------------------------------------------*/
199 /* Returns 1 if background has changed since last call, 0 otherwise.
200 This is enlightment mechanism. Go read:
201 http://gershwin.ens.fr/vdaniel/Doc-Locale/Outils-Gnu-Linux/Eterm-0.9/#trans
202 NOTE: this will always returns 0 when this mechanism is not supported.
204 int
205 xwindow_updated_background(Display * display, Window root, Atom id)
207 int result=0;
208 static Pixmap old_pixmap = None;
209 Pixmap pixmap = None;
210 Atom act_type;
211 int act_format;
212 unsigned long nitems, bytes_after;
213 unsigned char *prop = NULL;
215 if (!(display && root)) return 0;
217 if(id==None) id=XInternAtom(display,"_XROOTPMAP_ID", True);
218 if(id!=None &&
219 XGetWindowProperty(display, root, id, 0, 1, False, XA_PIXMAP,
220 &act_type, &act_format, &nitems, &bytes_after,
221 &prop)==Success &&
222 prop) {
223 pixmap = *((Pixmap *)prop);
224 result=(old_pixmap!=pixmap);
225 XFree(prop);
228 old_pixmap=pixmap;
229 return result;
232 /*----------------------------------------------------------------------------*/
233 /* Routine to grab the background in Imlib_Image.
234 Returns NULL if it fails, Reference to output Imlib_Image otherwise.
236 Imlib_Image
237 xwindow_grab_background(Display * display, int screen, Window window)
239 int x, y;
240 XEvent ev;
241 Window src;
242 XWindowAttributes attr;
243 Imlib_Image background=NULL;
245 if (!(display && window)) return NULL;
247 if(XGetWindowAttributes(display,window,&attr) &&
248 /* Avoid reparenting coordinates translation problem */
249 XTranslateCoordinates(display,window,RootWindow(display,screen),
250 0, 0, &x, &y, &src)) {
251 /* The trick is to create an Overrideredirect window overlapping our
252 window with background type of Parent relative and then grab it.
253 It seems overkill, but:
254 - XGetImage() on root get all viewable children windows embedded.
255 - XCopyArea() cause potential synchronisation problems depending
256 on backing store settings of root window: playing around
257 with GraphicsExpose events is not quicker nor simpler.
259 This idea was taken from aterm source base. See src/pixmap.c
260 in core distribution (http://aterm.sourceforge.net/).
262 if((src=XCreateWindow(display,
263 RootWindow(display,screen),
264 x, y, attr.width, attr.height,
266 CopyFromParent, CopyFromParent, CopyFromParent,
267 CWBackPixmap|CWBackingStore|
268 CWOverrideRedirect|CWEventMask,
269 &XDefaultWindowAttributes))) {
270 xwindow_context_save(IMLIB_DRAWABLE|IMLIB_IMAGE);
271 XGrabServer(display);
272 XMapRaised(display,src);
273 XSync(display,False);
275 XWindowEvent(display, src, ExposureMask, &ev);
276 while(ev.type!=Expose);
277 imlib_context_set_drawable(src);
278 background=imlib_create_image_from_drawable(0,0,0,
279 attr.width,attr.height,0);
280 XUngrabServer(display);
281 XDestroyWindow(display,src);
283 /* Make sure image has an alpha channel */
284 imlib_context_set_image(background);
285 imlib_image_set_has_alpha(1);
287 /* Restore context */
288 xwindow_context_restore();
291 return background;
294 /*----------------------------------------------------------------------------*/
295 /* Redraw updates rectangles onto window by copying background image at same
296 position.
298 void
299 xwindow_update_window(Window window, Imlib_Updates * updates,
300 Imlib_Image background, Imlib_Image foreground,
301 int transparency_flag)
303 int x,y,width,height;
304 Imlib_Image image;
305 Imlib_Updates update;
307 /* Verify there is something to update */
308 if(window && *updates) {
309 /* Save context states */
310 xwindow_context_save(IMLIB_IMAGE|IMLIB_COLOR|IMLIB_OPERATION|
311 IMLIB_BLEND|IMLIB_COLOR_MODIFIER|IMLIB_FILTER|
312 IMLIB_DRAWABLE);
314 /* Pre-loop settings */
315 imlib_context_set_drawable(window);
316 imlib_context_set_blend(0);
317 imlib_context_set_color_modifier(NULL);
318 imlib_context_set_filter(NULL);
319 if(transparency_flag) {
320 imlib_context_set_operation(IMLIB_OP_COPY);
321 } else
322 imlib_context_set_image(foreground);
324 /* Loop over updates */
325 for(update=*updates;
326 update;
327 update=imlib_updates_get_next(update)) {
328 imlib_updates_get_coordinates(update,&x,&y,(int*)&width,(int*)&height);
329 if (transparency_flag) {
330 if((image=imlib_create_image(width,height))) {
331 imlib_context_set_image(image);
333 /* Make sur the alpha channel is detected */
334 imlib_image_set_has_alpha(1);
336 /* Fill image wih full opaque black, then copy
337 background over */
338 imlib_context_set_color(0,0,0,255);
339 imlib_image_fill_rectangle(0,0,width,height);
340 imlib_blend_image_onto_image(background,0,
341 x,y,width,height,
342 0,0,width,height);
344 /* Blend foreground over background */
345 imlib_context_set_blend(1);
346 imlib_blend_image_onto_image(foreground,1,
347 x,y,width,height,
348 0,0,width,height);
350 /* Copy image to drawable and free it */
351 imlib_context_set_blend(0);
352 imlib_render_image_on_drawable(x,y);
353 imlib_free_image();
355 } else
356 /* Otherwise, just copy foreground, without alteration */
357 imlib_render_image_part_on_drawable_at_size(x,y,width,height,
358 x,y,width,height);
361 /* Restore initial context states */
362 xwindow_context_restore();
366 /*----------------------------------------------------------------------------*/
367 /* This move a window using outline rectangles if a window is mapped, and
368 updates cfgfile_item params accordingly. This is used by adesklets
369 if we created an `override_notify' window, and that therefore cannot take
370 advantage of any windows manager. Returns 1 if the window has been moved,
371 0 othermize.
372 NOTE: The window is not remmaped at the end if the move was sucessfull:
373 it is the duty of the caller to do so.
376 xwindow_move_window(Display * display, Window root, Window window,
377 cfgfile_item * params)
379 int dummy, grab_x, grab_y, old_x, old_y, x=0, y=0, result=0;
380 uint screen_width, screen_height;
381 XWindowAttributes attr;
382 XGCValues xgcvalues;
383 Window dummy_window;
384 GC gc;
385 Cursor cursor;
386 XEvent ev;
388 if (!(display && window)) return 0;
390 /* Test that main window is mapped,
391 and if screen size could be known */
392 if(XGetWindowAttributes(display,window,&attr) &&
393 attr.map_state!=IsUnmapped &&
394 xwindow_window_size(display,root,&screen_width,&screen_height)) {
395 /* Initialize a graphics context for the root window behind ours */
396 xgcvalues.function=GXxor;
397 xgcvalues.foreground=WhitePixel(display,params->scr);
398 xwindow_error_reset();
399 gc=XCreateGC(display,root,GCFunction|GCForeground,&xgcvalues);
400 /* Initialize cursor */
401 cursor = XCreateFontCursor(display,XC_fleur);
402 /* Initialize old coordinates */
403 old_x=attr.x; old_y=attr.y;
404 /* Unmap the window */
405 if (xwindow_error_check() &&
406 XUnmapWindow(display,window)) {
407 /* Query, then grab the pointer */
408 if(XQueryPointer(display, window, &dummy_window,
409 &dummy_window, &grab_x, &grab_y,
410 &dummy, &dummy, (uint*)&dummy) &&
411 XGrabPointer(display,root,True,
412 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
413 GrabModeAsync,GrabModeAsync,
414 root, cursor, 0)==GrabSuccess) {
415 /* Draw initial rectangle */
416 XDrawRectangle(display,root,gc,
417 attr.x,attr.y,attr.width-1,attr.height-1);
418 dummy=0;
419 do {
420 XWindowEvent(display,root,
421 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
422 &ev);
423 switch(ev.type) {
424 case ButtonPress:
425 dummy=1;
426 break;
427 case ButtonRelease:
428 /* We want a button press in our window before we take
429 this into account: the idea is that we want to ignore
430 button release event from menu */
431 if(dummy) {
432 /* Erase final rectangle */
433 XDrawRectangle(display,root,gc,
434 old_x,old_y,attr.width-1,attr.height-1);
435 result=1;
437 break;
438 case MotionNotify:
439 /* Compute new coordinates. */
440 x=attr.x+(ev.xmotion.x-grab_x);
441 y=attr.y+(ev.xmotion.y-grab_y);
442 /* Rectifies it */
443 x=((x+attr.width)<screen_width)?x:screen_width-attr.width;
444 y=((y+attr.height)<screen_height)?y:screen_height-attr.height;
445 x=(x>0)?x:0;
446 y=(y>0)?y:0;
447 /* Draw rectangles: we use a GCxor function for
448 not having to remember background data. */
449 if (x!=old_x || y!=old_y) {
450 XDrawRectangle(display,root,gc,
451 old_x,old_y,attr.width-1,attr.height-1);
452 XDrawRectangle(display,root,gc,
453 x,y,attr.width-1,attr.height-1);
455 /* Save coordinates */
456 old_x=x; old_y=y;
457 break;
459 } while(!result);
460 XUngrabPointer(display,0);
461 if(old_x!=params->x || old_y!=params->y)
462 result=XMoveWindow(display,window,x,y);
464 /* Save new coordinates if it changed, remap the window otherwize */
465 if(old_x!=params->x||old_y!=params->y) {
466 params->x=old_x;
467 params->y=old_y;
468 } else
469 XMapWindow(display,window);
472 return result;
475 /*----------------------------------------------------------------------------*/
477 xwindow_resize_window(Display * display, Window window, cfgfile_item * item,
478 int width, int height, int force_update)
480 int x,y, result=0;
481 uint screen_width, screen_height;
482 XSizeHints * hints;
483 XWindowAttributes attr;
485 if (!(display && window)) return 0;
487 if (width>0 && height>=0)
488 if(XGetWindowAttributes(display, window, &attr))
489 if (force_update || width!=attr.width || height!=attr.height) {
490 if (attr.override_redirect) {
491 /* Unmanaged window: boundaries check */
492 screen_width=WidthOfScreen(ScreenOfDisplay(display,item->scr));
493 screen_height=HeightOfScreen(ScreenOfDisplay(display,item->scr));
494 x=item->x;
495 y=item->y;
496 x=(x+width>screen_width)?screen_width-width:x;
497 y=(y+height>screen_height)?screen_height-height:y;
499 if (x>=0 && y>=0)
500 if (XMoveResizeWindow(display,window,
501 x,y,(uint)width,(uint)height))
502 result=1;
503 } else {
504 /* Managed window: no boundary check */
505 xwindow_error_reset();
506 XResizeWindow(display,window,(uint)width,(uint)height);
507 if(xwindow_error_check()) {
508 /* WM_Hints settings */
509 if ((hints=XAllocSizeHints())) {
510 hints->min_width=hints->max_width=(uint)width;
511 hints->min_height=hints->max_height=(uint)height;
512 hints->flags=PMinSize|PMaxSize;
513 XSetWMNormalHints(display,window,hints);
514 XFree(hints);
516 result=1;
520 return result;
523 #ifdef WM_DETECTION_OLD_STYLE
524 /*----------------------------------------------------------------------------*/
525 /* Here is a function that recursively calls itself (up to a limit) to find
526 the window ID of the KDE desktop to draw on. This is the hierarchy we're
527 trying to traverse:
529 -> The root window
530 0 -> window with name="KDE Desktop"
531 1 -> window with no name
532 2 -> window with name="KDE Desktop" & _NET_WM_WINDOW_TYPE_DESKTOP
533 3 -> window with no name and width >= width of screen
535 The last window in the hierarchy is the one to draw to. The
536 numbers show the value of the `depth' argument.
538 NOTE: This code was copied from xpenguins source code base -
539 http://xpenguins.seul.org/
541 static Window
542 xwindow_get_kde_desktop(Display *display, int screen, Window window,
543 Atom atom, char *atomname, int depth)
545 char *name = NULL;
546 unsigned char *wintype = NULL;
547 Window winreturn = 0;
548 unsigned long nitems, bytesafter;
549 Atom actual_type;
550 int actual_format;
551 Window rootReturn, parentReturn, *children;
552 unsigned int nChildren;
553 char go_deeper = 0;
554 if (XFetchName(display, window, &name)) {
555 if (strcasecmp(name, "KDE Desktop") == 0) {
556 /* Presumably either at depth 0 or 2 */
557 if (XGetWindowProperty(display, window, atom, 0, 1,
558 False, XA_ATOM,
559 &actual_type, &actual_format,
560 &nitems, &bytesafter,
561 &wintype) == Success
562 && wintype) {
563 char *tmpatomname = XGetAtomName(display, *((Atom*)wintype));
564 if (tmpatomname) {
565 if (strcmp(atomname, tmpatomname) == 0 && depth == 2) {
566 /* OK, at depth 2 */
567 go_deeper = 1;
569 XFree((char *) tmpatomname);
572 else if (depth < 2) {
573 go_deeper = 1;
576 else if (depth == 1) {
577 go_deeper = 1;
579 XFree((char *) name);
581 else if (depth == 1) {
582 go_deeper = 1;
584 /* If go_deeper is 1 then there is a possibility that the background
585 * window is a descendant of the current window; otherwise we're
586 * barking up the wrong tree. */
587 if (go_deeper && XQueryTree(display, window, &rootReturn,
588 &parentReturn, &children,
589 &nChildren)) {
590 int i;
591 for (i = 0; i < nChildren; ++i) {
592 /* children[i] is now at depth 3 */
593 if (depth == 2) {
594 XWindowAttributes attributes;
595 if (XGetWindowAttributes(display, children[i], &attributes)) {
596 if (attributes.width >= DisplayWidth(display, screen)/2
597 && attributes.height > 0) {
598 /* Found it! */
599 winreturn = children[i];
600 break;
604 else if ((winreturn = xwindow_get_kde_desktop(display, screen,
605 children[i],
606 atom, atomname,
607 depth+1))) {
608 break;
611 XFree((char *) children);
613 return winreturn;
616 /*----------------------------------------------------------------------------*/
617 /* Looks for the Nautilus desktop window to draw to, given the toplevel
618 window of the Nautilus desktop. Basically recursively calls itself
619 looking for subwindows the same size as the root window.
621 NOTE: This code was copied verbatim from xpenguins-2.2 source code base -
622 http://xpenguins.seul.org/
624 static Window
625 xwindow_get_nautilus_desktop(Display *display, int screen, Window window,
626 int depth)
628 Window rootReturn, parentReturn, *children;
629 Window winreturn = window;
630 unsigned int nChildren;
632 if (depth > 5) {
633 return ((Window) 0);
635 else if (XQueryTree(display, window, &rootReturn, &parentReturn,
636 &children, &nChildren)) {
637 int i;
638 for (i = 0; i < nChildren; ++i) {
639 XWindowAttributes attributes;
640 if (XGetWindowAttributes(display, children[i], &attributes)) {
641 if (attributes.width == DisplayWidth(display, screen)
642 && attributes.height == DisplayHeight(display, screen)) {
643 /* Found a possible desktop window */
644 winreturn = xwindow_get_nautilus_desktop(display, screen,
645 children[i], depth+1);
649 XFree((char *) children);
651 return winreturn;
653 #endif /* WM_DETECTION_OLD_STYLE */
655 /*----------------------------------------------------------------------------*/
656 /* Returns the root window, or the fake root window depending on
657 WM. Autodetect fake root for Xfce4, nautilus and KDE.
659 Window
660 xwindow_get_root_window(Display * display, int scr)
662 #ifdef WM_DETECTION_OLD_STYLE
663 int i;
664 unsigned long dummy;
665 Window rootReturn, parentReturn, *children;
666 unsigned int nChildren;
667 Window result = 0;
668 Window root = RootWindow(display,scr),
669 * toplevel = NULL;
670 Atom TYPE,
671 NAUTILUS_DESKTOP_WINDOW_ID = XInternAtom(display,
672 "NAUTILUS_DESKTOP_WINDOW_ID",
673 False);
675 if (XGetWindowProperty(display, root,
676 NAUTILUS_DESKTOP_WINDOW_ID,
677 0, 1, False, XA_WINDOW,
678 &TYPE,
679 (int*)((void*)&dummy),
680 &dummy,
681 &dummy,
682 (unsigned char **)((void*)&toplevel)) == Success
683 && toplevel)
684 result = xwindow_get_nautilus_desktop(display,scr,*toplevel,0);
686 /* Next look for a virtual root or a KDE Desktop */
687 if (!result
688 && XQueryTree(display, root, &rootReturn, &parentReturn,
689 &children, &nChildren)) {
690 Atom _NET_WM_WINDOW_TYPE = XInternAtom(display,
691 "_NET_WM_WINDOW_TYPE",
692 False);
693 Atom __SWM_VROOT = XInternAtom(display, "__SWM_VROOT", False);
695 for (i=0; i<nChildren && !result; ++i) {
696 Window *toplevel = (Window *) 0;
697 if (XGetWindowProperty(display, children[i],
698 __SWM_VROOT, 0, 1, False, XA_WINDOW,
699 &TYPE, (int*) ((void*)&dummy),
700 &dummy, &dummy,
701 (unsigned char **)((void*)&toplevel)) == Success
702 && toplevel)
703 /* KDE < 2.1 */
704 result = *toplevel;
705 else
706 /* KDE >= 2.1 */
707 result = xwindow_get_kde_desktop(display, scr, children[i],
708 _NET_WM_WINDOW_TYPE,
709 "_NET_WM_WINDOW_TYPE_DESKTOP",
710 0);
712 XFree((char *) children);
715 return (result)?result:root;
716 #else
717 uint window = 0;
718 char * root_env;
719 XWindowAttributes xattr;
721 /* Try reading the ADESKLETS_ROOT environment variable to identify the root */
722 if ((root_env=getenv("ADESKLETS_ROOT")) &&
723 sscanf(root_env,"%x", &window)==1)
724 if (XGetWindowAttributes(display, (Window)window, &xattr)==0) {
725 debug("Invalid 0x%x Windows given as root!", window);
726 window=0;
729 /* Use the specified window as root, or the real root otherwise */
730 return (window)?(Window)window:RootWindow(display, scr);
731 #endif /* WM_DETECTION_OLD_STYLE */
734 #endif /* X_MISSING_DISPLAY , far, far above! */
736 /*----------------------------------------------------------------------------*/
737 /* Save selected elements of imlib2 context for future restoration.
738 Note: This uses a vector `contextes' of context_backup references,
739 used like a stack (last-in, first-out): this lead to correct
740 recursive call of the function pairs xwindow_context_save().
741 and xwindow_context_restore().
743 void
744 xwindow_context_save(long mycontext)
746 context_backup * context;
748 /* Contextes initialisation */
749 if(!contextes && (!(contextes=vector_init()))) {
750 debug("Error initialising contexes!\n");
751 return;
754 /* New context initialisation */
755 if(!(context=(context_backup*)malloc(sizeof(context_backup)))) {
756 debug("Error initialising new context!\n");
757 return;
760 /* Save present context */
761 context->context=mycontext;
763 #ifdef X_DISPLAY_MISSING
764 mycontext&=~(IMLIB_DISPLAY|IMLIB_VISUAL|IMLIB_COLORMAP|IMLIB_DRAWABLE|
765 IMLIB_MASK|IMLIB_DITHER_MASK);
766 #endif
768 /* Most frequently saved items are traited first, for optimisation sake */
769 #define CONTEXT_ACTION(mask, x ) \
770 if(mycontext&(mask)) {\
771 x ;\
773 if(!(mycontext&=~(mask))) goto end_of_context_save
775 CONTEXT_ACTION(IMLIB_IMAGE,
776 context->image=imlib_context_get_image());
777 CONTEXT_ACTION(IMLIB_COLOR,
778 imlib_context_get_color(&context->red,
779 &context->green,
780 &context->blue,
781 &context->alpha));
782 CONTEXT_ACTION(IMLIB_BLEND,
783 context->blend=imlib_context_get_blend());
784 CONTEXT_ACTION(IMLIB_FONT,
785 context->font=imlib_context_get_font());
786 CONTEXT_ACTION(IMLIB_OPERATION,
787 context->operation=imlib_context_get_operation());
788 CONTEXT_ACTION(IMLIB_COLOR_RANGE,
789 context->color_range=imlib_context_get_color_range());
790 CONTEXT_ACTION(IMLIB_FILTER,
791 context->filter=imlib_context_get_filter());
792 #ifndef X_DISPLAY_MISSING
793 CONTEXT_ACTION(IMLIB_DISPLAY,
794 context->display=imlib_context_get_display());
795 CONTEXT_ACTION(IMLIB_VISUAL,
796 context->visual=imlib_context_get_visual());
797 CONTEXT_ACTION(IMLIB_COLORMAP,
798 context->colormap=imlib_context_get_colormap());
799 CONTEXT_ACTION(IMLIB_DRAWABLE,
800 context->drawable=imlib_context_get_drawable());
801 CONTEXT_ACTION(IMLIB_MASK,
802 context->mask=imlib_context_get_mask());
803 CONTEXT_ACTION(IMLIB_DITHER_MASK,
804 context->dither_mask=imlib_context_get_dither_mask());
805 #endif
806 CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
807 context->anti_alias=imlib_context_get_anti_alias());
808 CONTEXT_ACTION(IMLIB_DITHER,
809 context->dither=imlib_context_get_dither());
810 CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
811 context->color_modifier=
812 imlib_context_get_color_modifier());
813 CONTEXT_ACTION(IMLIB_DIRECTION,
814 context->direction=imlib_context_get_direction());
815 CONTEXT_ACTION(IMLIB_ANGLE,
816 context->angle=imlib_context_get_angle());
817 #undef CONTEXT_ACTION
819 /* This code should never be reached ! */
820 debug("Error in creating new context!\n");
822 end_of_context_save:
823 vector_push(contextes,context);
826 /*----------------------------------------------------------------------------*/
827 /* Restore a given imlib context, somewhere after a call
828 to xwindow_context_save */
829 void
830 xwindow_context_restore(void)
832 context_backup * context;
834 /* Verify there is comething to restore */
835 if(!contextes || !contextes->pos) {
836 debug("No context to restore!\n");
837 return;
840 /* Commodity setting */
841 context=(context_backup*)contextes->content[contextes->pos-1];
843 /* Most frequently saved items are traited first, for optimisation sake */
844 #define CONTEXT_ACTION(mask, x ) \
845 if(context->context&(mask)) {\
846 x ;\
848 if(!(context->context&=~(mask))) goto end_of_restore_context
850 CONTEXT_ACTION(IMLIB_IMAGE,
851 imlib_context_set_image(context->image));
852 CONTEXT_ACTION(IMLIB_COLOR,
853 imlib_context_set_color(context->red,
854 context->green,
855 context->blue,
856 context->alpha));
857 CONTEXT_ACTION(IMLIB_BLEND,
858 imlib_context_set_blend(context->blend));
859 CONTEXT_ACTION(IMLIB_FONT,
860 imlib_context_set_font(context->font));
861 CONTEXT_ACTION(IMLIB_OPERATION,
862 imlib_context_set_operation(context->operation));
863 CONTEXT_ACTION(IMLIB_COLOR_RANGE,
864 imlib_context_set_color_range(context->color_range));
865 CONTEXT_ACTION(IMLIB_FILTER,
866 imlib_context_set_filter(context->filter));
867 #ifndef X_DISPLAY_MISSING
868 CONTEXT_ACTION(IMLIB_DISPLAY,
869 imlib_context_set_display(context->display));
870 CONTEXT_ACTION(IMLIB_VISUAL,
871 imlib_context_set_visual(context->visual));
872 CONTEXT_ACTION(IMLIB_COLORMAP,
873 imlib_context_set_colormap(context->colormap));
874 CONTEXT_ACTION(IMLIB_DRAWABLE,
875 imlib_context_set_drawable(context->drawable));
876 CONTEXT_ACTION(IMLIB_MASK,
877 imlib_context_set_mask(context->mask));
878 CONTEXT_ACTION(IMLIB_DITHER_MASK,
879 imlib_context_set_dither_mask(context->dither_mask));
880 #endif
881 CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
882 imlib_context_set_anti_alias(context->anti_alias));
883 CONTEXT_ACTION(IMLIB_DITHER,
884 imlib_context_set_dither(context->dither));
885 CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
886 imlib_context_set_color_modifier(context->color_modifier));
887 CONTEXT_ACTION(IMLIB_DIRECTION,
888 imlib_context_set_direction(context->direction));
889 CONTEXT_ACTION(IMLIB_ANGLE,
890 imlib_context_set_angle(context->angle));
891 #undef CONTEXT_ACTION
893 /* This code should never be reached ! */
894 debug("Error restoring context!\n");
896 end_of_restore_context:
897 vector_pop(contextes);
898 if(!contextes->pos)
899 contextes=vector_free(contextes);