Support for password authentification in adesklets_submit
[adesklets.git] / src / xwindow.c
blob5000ea3a00a8ed32cab587b941e202797046edae
1 /*--- xwindow.c ----------------------------------------------------------------
2 Copyright (C) 2004, 2005, 2006 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 && XGetWindowAttributes(display, window, &attr)) {
488 if (force_update || width!=attr.width || height!=attr.height) {
489 if (attr.override_redirect) {
490 /* Unmanaged window: boundaries check */
491 screen_width=WidthOfScreen(ScreenOfDisplay(display,item->scr));
492 screen_height=HeightOfScreen(ScreenOfDisplay(display,item->scr));
493 x=item->x;
494 y=item->y;
495 x=(x+width>screen_width)?screen_width-width:x;
496 y=(y+height>screen_height)?screen_height-height:y;
498 if (x>=0 && y>=0)
499 if (XMoveResizeWindow(display,window,
500 x,y,(uint)width,(uint)height))
501 result=1;
502 } else {
503 /* Managed window: no boundary check */
504 xwindow_error_reset();
505 XResizeWindow(display,window,(uint)width,(uint)height);
506 if(xwindow_error_check()) {
507 /* WM_Hints settings */
508 if ((hints=XAllocSizeHints())) {
509 hints->min_width=hints->max_width=(uint)width;
510 hints->min_height=hints->max_height=(uint)height;
511 hints->flags=PMinSize|PMaxSize;
512 XSetWMNormalHints(display,window,hints);
513 XFree(hints);
515 result=1;
518 } else
519 if (!force_update) result=1;
521 return result;
524 #ifdef WM_DETECTION_OLD_STYLE
525 /*----------------------------------------------------------------------------*/
526 /* Here is a function that recursively calls itself (up to a limit) to find
527 the window ID of the KDE desktop to draw on. This is the hierarchy we're
528 trying to traverse:
530 -> The root window
531 0 -> window with name="KDE Desktop"
532 1 -> window with no name
533 2 -> window with name="KDE Desktop" & _NET_WM_WINDOW_TYPE_DESKTOP
534 3 -> window with no name and width >= width of screen
536 The last window in the hierarchy is the one to draw to. The
537 numbers show the value of the `depth' argument.
539 NOTE: This code was copied from xpenguins source code base -
540 http://xpenguins.seul.org/
542 static Window
543 xwindow_get_kde_desktop(Display *display, int screen, Window window,
544 Atom atom, char *atomname, int depth)
546 char *name = NULL;
547 unsigned char *wintype = NULL;
548 Window winreturn = 0;
549 unsigned long nitems, bytesafter;
550 Atom actual_type;
551 int actual_format;
552 Window rootReturn, parentReturn, *children;
553 unsigned int nChildren;
554 char go_deeper = 0;
555 if (XFetchName(display, window, &name)) {
556 if (strcasecmp(name, "KDE Desktop") == 0) {
557 /* Presumably either at depth 0 or 2 */
558 if (XGetWindowProperty(display, window, atom, 0, 1,
559 False, XA_ATOM,
560 &actual_type, &actual_format,
561 &nitems, &bytesafter,
562 &wintype) == Success
563 && wintype) {
564 char *tmpatomname = XGetAtomName(display, *((Atom*)wintype));
565 if (tmpatomname) {
566 if (strcmp(atomname, tmpatomname) == 0 && depth == 2) {
567 /* OK, at depth 2 */
568 go_deeper = 1;
570 XFree((char *) tmpatomname);
573 else if (depth < 2) {
574 go_deeper = 1;
577 else if (depth == 1) {
578 go_deeper = 1;
580 XFree((char *) name);
582 else if (depth == 1) {
583 go_deeper = 1;
585 /* If go_deeper is 1 then there is a possibility that the background
586 * window is a descendant of the current window; otherwise we're
587 * barking up the wrong tree. */
588 if (go_deeper && XQueryTree(display, window, &rootReturn,
589 &parentReturn, &children,
590 &nChildren)) {
591 int i;
592 for (i = 0; i < nChildren; ++i) {
593 /* children[i] is now at depth 3 */
594 if (depth == 2) {
595 XWindowAttributes attributes;
596 if (XGetWindowAttributes(display, children[i], &attributes)) {
597 if (attributes.width >= DisplayWidth(display, screen)/2
598 && attributes.height > 0) {
599 /* Found it! */
600 winreturn = children[i];
601 break;
605 else if ((winreturn = xwindow_get_kde_desktop(display, screen,
606 children[i],
607 atom, atomname,
608 depth+1))) {
609 break;
612 XFree((char *) children);
614 return winreturn;
617 /*----------------------------------------------------------------------------*/
618 /* Looks for the Nautilus desktop window to draw to, given the toplevel
619 window of the Nautilus desktop. Basically recursively calls itself
620 looking for subwindows the same size as the root window.
622 NOTE: This code was copied verbatim from xpenguins-2.2 source code base -
623 http://xpenguins.seul.org/
625 static Window
626 xwindow_get_nautilus_desktop(Display *display, int screen, Window window,
627 int depth)
629 Window rootReturn, parentReturn, *children;
630 Window winreturn = window;
631 unsigned int nChildren;
633 if (depth > 5) {
634 return ((Window) 0);
636 else if (XQueryTree(display, window, &rootReturn, &parentReturn,
637 &children, &nChildren)) {
638 int i;
639 for (i = 0; i < nChildren; ++i) {
640 XWindowAttributes attributes;
641 if (XGetWindowAttributes(display, children[i], &attributes)) {
642 if (attributes.width == DisplayWidth(display, screen)
643 && attributes.height == DisplayHeight(display, screen)) {
644 /* Found a possible desktop window */
645 winreturn = xwindow_get_nautilus_desktop(display, screen,
646 children[i], depth+1);
650 XFree((char *) children);
652 return winreturn;
654 #endif /* WM_DETECTION_OLD_STYLE */
656 /*----------------------------------------------------------------------------*/
657 /* Returns the root window, or the fake root window depending on
658 WM. Autodetect fake root for Xfce4, nautilus and KDE.
660 Window
661 xwindow_get_root_window(Display * display, int scr)
663 #ifdef WM_DETECTION_OLD_STYLE
664 int i;
665 unsigned long dummy;
666 Window rootReturn, parentReturn, *children;
667 unsigned int nChildren;
668 Window result = 0;
669 Window root = RootWindow(display,scr),
670 * toplevel = NULL;
671 Atom TYPE,
672 NAUTILUS_DESKTOP_WINDOW_ID = XInternAtom(display,
673 "NAUTILUS_DESKTOP_WINDOW_ID",
674 False);
676 if (XGetWindowProperty(display, root,
677 NAUTILUS_DESKTOP_WINDOW_ID,
678 0, 1, False, XA_WINDOW,
679 &TYPE,
680 (int*)((void*)&dummy),
681 &dummy,
682 &dummy,
683 (unsigned char **)((void*)&toplevel)) == Success
684 && toplevel)
685 result = xwindow_get_nautilus_desktop(display,scr,*toplevel,0);
687 /* Next look for a virtual root or a KDE Desktop */
688 if (!result
689 && XQueryTree(display, root, &rootReturn, &parentReturn,
690 &children, &nChildren)) {
691 Atom _NET_WM_WINDOW_TYPE = XInternAtom(display,
692 "_NET_WM_WINDOW_TYPE",
693 False);
694 Atom __SWM_VROOT = XInternAtom(display, "__SWM_VROOT", False);
696 for (i=0; i<nChildren && !result; ++i) {
697 Window *toplevel = (Window *) 0;
698 if (XGetWindowProperty(display, children[i],
699 __SWM_VROOT, 0, 1, False, XA_WINDOW,
700 &TYPE, (int*) ((void*)&dummy),
701 &dummy, &dummy,
702 (unsigned char **)((void*)&toplevel)) == Success
703 && toplevel)
704 /* KDE < 2.1 */
705 result = *toplevel;
706 else
707 /* KDE >= 2.1 */
708 result = xwindow_get_kde_desktop(display, scr, children[i],
709 _NET_WM_WINDOW_TYPE,
710 "_NET_WM_WINDOW_TYPE_DESKTOP",
711 0);
713 XFree((char *) children);
716 return (result)?result:root;
717 #else
718 uint window = 0;
719 char * root_env;
720 XWindowAttributes xattr;
722 /* Try reading the ADESKLETS_ROOT environment variable to identify the root */
723 if ((root_env=getenv("ADESKLETS_ROOT")) &&
724 sscanf(root_env,"%x", &window)==1)
725 if (XGetWindowAttributes(display, (Window)window, &xattr)==0) {
726 debug("Invalid 0x%x Windows given as root!", window);
727 window=0;
730 /* Use the specified window as root, or the real root otherwise */
731 return (window)?(Window)window:RootWindow(display, scr);
732 #endif /* WM_DETECTION_OLD_STYLE */
735 #endif /* X_MISSING_DISPLAY , far, far above! */
737 /*----------------------------------------------------------------------------*/
738 /* Save selected elements of imlib2 context for future restoration.
739 Note: This uses a vector `contextes' of context_backup references,
740 used like a stack (last-in, first-out): this lead to correct
741 recursive call of the function pairs xwindow_context_save().
742 and xwindow_context_restore().
744 void
745 xwindow_context_save(long mycontext)
747 context_backup * context;
749 /* Contextes initialisation */
750 if(!contextes && (!(contextes=vector_init()))) {
751 debug("Error initialising contexes!\n");
752 return;
755 /* New context initialisation */
756 if(!(context=(context_backup*)malloc(sizeof(context_backup)))) {
757 debug("Error initialising new context!\n");
758 return;
761 /* Save present context */
762 context->context=mycontext;
764 #ifdef X_DISPLAY_MISSING
765 mycontext&=~(IMLIB_DISPLAY|IMLIB_VISUAL|IMLIB_COLORMAP|IMLIB_DRAWABLE|
766 IMLIB_MASK|IMLIB_DITHER_MASK);
767 #endif
769 /* Most frequently saved items are traited first, for optimisation sake */
770 #define CONTEXT_ACTION(mask, x ) \
771 if(mycontext&(mask)) {\
772 x ;\
774 if(!(mycontext&=~(mask))) goto end_of_context_save
776 CONTEXT_ACTION(IMLIB_IMAGE,
777 context->image=imlib_context_get_image());
778 CONTEXT_ACTION(IMLIB_COLOR,
779 imlib_context_get_color(&context->red,
780 &context->green,
781 &context->blue,
782 &context->alpha));
783 CONTEXT_ACTION(IMLIB_BLEND,
784 context->blend=imlib_context_get_blend());
785 CONTEXT_ACTION(IMLIB_FONT,
786 context->font=imlib_context_get_font());
787 CONTEXT_ACTION(IMLIB_OPERATION,
788 context->operation=imlib_context_get_operation());
789 CONTEXT_ACTION(IMLIB_COLOR_RANGE,
790 context->color_range=imlib_context_get_color_range());
791 CONTEXT_ACTION(IMLIB_FILTER,
792 context->filter=imlib_context_get_filter());
793 #ifndef X_DISPLAY_MISSING
794 CONTEXT_ACTION(IMLIB_DISPLAY,
795 context->display=imlib_context_get_display());
796 CONTEXT_ACTION(IMLIB_VISUAL,
797 context->visual=imlib_context_get_visual());
798 CONTEXT_ACTION(IMLIB_COLORMAP,
799 context->colormap=imlib_context_get_colormap());
800 CONTEXT_ACTION(IMLIB_DRAWABLE,
801 context->drawable=imlib_context_get_drawable());
802 CONTEXT_ACTION(IMLIB_MASK,
803 context->mask=imlib_context_get_mask());
804 CONTEXT_ACTION(IMLIB_DITHER_MASK,
805 context->dither_mask=imlib_context_get_dither_mask());
806 #endif
807 CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
808 context->anti_alias=imlib_context_get_anti_alias());
809 CONTEXT_ACTION(IMLIB_DITHER,
810 context->dither=imlib_context_get_dither());
811 CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
812 context->color_modifier=
813 imlib_context_get_color_modifier());
814 CONTEXT_ACTION(IMLIB_DIRECTION,
815 context->direction=imlib_context_get_direction());
816 CONTEXT_ACTION(IMLIB_ANGLE,
817 context->angle=imlib_context_get_angle());
818 #undef CONTEXT_ACTION
820 /* This code should never be reached ! */
821 debug("Error in creating new context!\n");
823 end_of_context_save:
824 vector_push(contextes,context);
827 /*----------------------------------------------------------------------------*/
828 /* Restore a given imlib context, somewhere after a call
829 to xwindow_context_save */
830 void
831 xwindow_context_restore(void)
833 context_backup * context;
835 /* Verify there is comething to restore */
836 if(!contextes || !contextes->pos) {
837 debug("No context to restore!\n");
838 return;
841 /* Commodity setting */
842 context=(context_backup*)contextes->content[contextes->pos-1];
844 /* Most frequently saved items are traited first, for optimisation sake */
845 #define CONTEXT_ACTION(mask, x ) \
846 if(context->context&(mask)) {\
847 x ;\
849 if(!(context->context&=~(mask))) goto end_of_restore_context
851 CONTEXT_ACTION(IMLIB_IMAGE,
852 imlib_context_set_image(context->image));
853 CONTEXT_ACTION(IMLIB_COLOR,
854 imlib_context_set_color(context->red,
855 context->green,
856 context->blue,
857 context->alpha));
858 CONTEXT_ACTION(IMLIB_BLEND,
859 imlib_context_set_blend(context->blend));
860 CONTEXT_ACTION(IMLIB_FONT,
861 imlib_context_set_font(context->font));
862 CONTEXT_ACTION(IMLIB_OPERATION,
863 imlib_context_set_operation(context->operation));
864 CONTEXT_ACTION(IMLIB_COLOR_RANGE,
865 imlib_context_set_color_range(context->color_range));
866 CONTEXT_ACTION(IMLIB_FILTER,
867 imlib_context_set_filter(context->filter));
868 #ifndef X_DISPLAY_MISSING
869 CONTEXT_ACTION(IMLIB_DISPLAY,
870 imlib_context_set_display(context->display));
871 CONTEXT_ACTION(IMLIB_VISUAL,
872 imlib_context_set_visual(context->visual));
873 CONTEXT_ACTION(IMLIB_COLORMAP,
874 imlib_context_set_colormap(context->colormap));
875 CONTEXT_ACTION(IMLIB_DRAWABLE,
876 imlib_context_set_drawable(context->drawable));
877 CONTEXT_ACTION(IMLIB_MASK,
878 imlib_context_set_mask(context->mask));
879 CONTEXT_ACTION(IMLIB_DITHER_MASK,
880 imlib_context_set_dither_mask(context->dither_mask));
881 #endif
882 CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
883 imlib_context_set_anti_alias(context->anti_alias));
884 CONTEXT_ACTION(IMLIB_DITHER,
885 imlib_context_set_dither(context->dither));
886 CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
887 imlib_context_set_color_modifier(context->color_modifier));
888 CONTEXT_ACTION(IMLIB_DIRECTION,
889 imlib_context_set_direction(context->direction));
890 CONTEXT_ACTION(IMLIB_ANGLE,
891 imlib_context_set_angle(context->angle));
892 #undef CONTEXT_ACTION
894 /* This code should never be reached ! */
895 debug("Error restoring context!\n");
897 end_of_restore_context:
898 vector_pop(contextes);
899 if(!contextes->pos)
900 contextes=vector_free(contextes);