Support for FontConfig 2.4
[adesklets.git] / src / xwindow.c
blob12ec3bd37a2f2599204de95716280d727f254b5d
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));
127 #ifdef HAVE_FONTCONFIG_FCFINI
128 FcFini();
129 #else
130 /* On FontConfig >= 2.4, this causes a segfault, probably due to the new
131 caching mechanism: we don't have to care, since FcFini() always exists,
132 and does the dirty dessalocation job just fine.
134 if (fs) FcFontSetDestroy(fs);
135 FcObjectSetDestroy(os);
136 #endif
138 #endif
139 imlib_add_path_to_font_path(".");
140 #ifdef DEBUG
141 imlib_add_path_to_font_path("../sharedata");
142 #endif
145 /*----------------------------------------------------------------------------*/
146 #ifndef X_DISPLAY_MISSING
148 int
149 xwindow_non_fatal_error_handler(Display * display , XErrorEvent * ev)
151 char buffer[1024];
153 if(!display) return 0;
155 /* Print out error description */
156 if (!XGetErrorText(display,ev->error_code,buffer,sizeof(buffer)))
157 fprintf(stderr,"Error: with X protocol on display `%s'\n%s\n",
158 XDisplayName(NULL),buffer);
159 /* Save error description */
160 memcpy(&xerror_event,ev,sizeof(XErrorEvent));
161 return 0;
164 /*----------------------------------------------------------------------------*/
165 void
166 xwindow_error_reset(void)
168 memset(&xerror_event,0,sizeof(XErrorEvent));
171 /*----------------------------------------------------------------------------*/
173 xwindow_error_check(void)
175 return xerror_event.error_code==0;
178 /*----------------------------------------------------------------------------*/
179 /* Sends back dimensions of given window. */
181 xwindow_window_size(Display * display, Window window,
182 uint * width_return, uint * height_return)
184 int dummy;
185 Window root;
186 return display && window &&
187 XGetGeometry(display, window, &root,
188 &dummy, &dummy, width_return, height_return,
189 (uint*)&dummy,(uint*)&dummy);
192 /*----------------------------------------------------------------------------*/
193 /* Return 1 if given coordinates changed since last call.
194 Note: only works with one set of coordinates */
196 xwindow_window_moved_or_resized(int new_x, int new_y,
197 int new_width, int new_height)
199 static int x=-1, y=-1, width=-1, height=-1;
200 int result;
201 result=!(x==new_x && y==new_y && width==new_width && height==new_height);
202 x=new_x;y=new_y;width=new_width;height=new_height;
203 return result;
206 /*----------------------------------------------------------------------------*/
207 /* Returns 1 if background has changed since last call, 0 otherwise.
208 This is enlightment mechanism. Go read:
209 http://gershwin.ens.fr/vdaniel/Doc-Locale/Outils-Gnu-Linux/Eterm-0.9/#trans
210 NOTE: this will always returns 0 when this mechanism is not supported.
212 int
213 xwindow_updated_background(Display * display, Window root, Atom id)
215 int result=0;
216 static Pixmap old_pixmap = None;
217 Pixmap pixmap = None;
218 Atom act_type;
219 int act_format;
220 unsigned long nitems, bytes_after;
221 unsigned char *prop = NULL;
223 if (!(display && root)) return 0;
225 if(id==None) id=XInternAtom(display,"_XROOTPMAP_ID", True);
226 if(id!=None &&
227 XGetWindowProperty(display, root, id, 0, 1, False, XA_PIXMAP,
228 &act_type, &act_format, &nitems, &bytes_after,
229 &prop)==Success &&
230 prop) {
231 pixmap = *((Pixmap *)prop);
232 result=(old_pixmap!=pixmap);
233 XFree(prop);
236 old_pixmap=pixmap;
237 return result;
240 /*----------------------------------------------------------------------------*/
241 /* Routine to grab the background in Imlib_Image.
242 Returns NULL if it fails, Reference to output Imlib_Image otherwise.
244 Imlib_Image
245 xwindow_grab_background(Display * display, int screen, Window window)
247 int x, y;
248 XEvent ev;
249 Window src;
250 XWindowAttributes attr;
251 Imlib_Image background=NULL;
253 if (!(display && window)) return NULL;
255 if(XGetWindowAttributes(display,window,&attr) &&
256 /* Avoid reparenting coordinates translation problem */
257 XTranslateCoordinates(display,window,RootWindow(display,screen),
258 0, 0, &x, &y, &src)) {
259 /* The trick is to create an Overrideredirect window overlapping our
260 window with background type of Parent relative and then grab it.
261 It seems overkill, but:
262 - XGetImage() on root get all viewable children windows embedded.
263 - XCopyArea() cause potential synchronisation problems depending
264 on backing store settings of root window: playing around
265 with GraphicsExpose events is not quicker nor simpler.
267 This idea was taken from aterm source base. See src/pixmap.c
268 in core distribution (http://aterm.sourceforge.net/).
270 if((src=XCreateWindow(display,
271 RootWindow(display,screen),
272 x, y, attr.width, attr.height,
274 CopyFromParent, CopyFromParent, CopyFromParent,
275 CWBackPixmap|CWBackingStore|
276 CWOverrideRedirect|CWEventMask,
277 &XDefaultWindowAttributes))) {
278 xwindow_context_save(IMLIB_DRAWABLE|IMLIB_IMAGE);
279 XGrabServer(display);
280 XMapRaised(display,src);
281 XSync(display,False);
283 XWindowEvent(display, src, ExposureMask, &ev);
284 while(ev.type!=Expose);
285 imlib_context_set_drawable(src);
286 background=imlib_create_image_from_drawable(0,0,0,
287 attr.width,attr.height,0);
288 XUngrabServer(display);
289 XDestroyWindow(display,src);
291 /* Make sure image has an alpha channel */
292 imlib_context_set_image(background);
293 imlib_image_set_has_alpha(1);
295 /* Restore context */
296 xwindow_context_restore();
299 return background;
302 /*----------------------------------------------------------------------------*/
303 /* Redraw updates rectangles onto window by copying background image at same
304 position.
306 void
307 xwindow_update_window(Window window, Imlib_Updates * updates,
308 Imlib_Image background, Imlib_Image foreground,
309 int transparency_flag)
311 int x,y,width,height;
312 Imlib_Image image;
313 Imlib_Updates update;
315 /* Verify there is something to update */
316 if(window && *updates) {
317 /* Save context states */
318 xwindow_context_save(IMLIB_IMAGE|IMLIB_COLOR|IMLIB_OPERATION|
319 IMLIB_BLEND|IMLIB_COLOR_MODIFIER|IMLIB_FILTER|
320 IMLIB_DRAWABLE);
322 /* Pre-loop settings */
323 imlib_context_set_drawable(window);
324 imlib_context_set_blend(0);
325 imlib_context_set_color_modifier(NULL);
326 imlib_context_set_filter(NULL);
327 if(transparency_flag) {
328 imlib_context_set_operation(IMLIB_OP_COPY);
329 } else
330 imlib_context_set_image(foreground);
332 /* Loop over updates */
333 for(update=*updates;
334 update;
335 update=imlib_updates_get_next(update)) {
336 imlib_updates_get_coordinates(update,&x,&y,(int*)&width,(int*)&height);
337 if (transparency_flag) {
338 if((image=imlib_create_image(width,height))) {
339 imlib_context_set_image(image);
341 /* Make sur the alpha channel is detected */
342 imlib_image_set_has_alpha(1);
344 /* Fill image wih full opaque black, then copy
345 background over */
346 imlib_context_set_color(0,0,0,255);
347 imlib_image_fill_rectangle(0,0,width,height);
348 imlib_blend_image_onto_image(background,0,
349 x,y,width,height,
350 0,0,width,height);
352 /* Blend foreground over background */
353 imlib_context_set_blend(1);
354 imlib_blend_image_onto_image(foreground,1,
355 x,y,width,height,
356 0,0,width,height);
358 /* Copy image to drawable and free it */
359 imlib_context_set_blend(0);
360 imlib_render_image_on_drawable(x,y);
361 imlib_free_image();
363 } else
364 /* Otherwise, just copy foreground, without alteration */
365 imlib_render_image_part_on_drawable_at_size(x,y,width,height,
366 x,y,width,height);
369 /* Restore initial context states */
370 xwindow_context_restore();
374 /*----------------------------------------------------------------------------*/
375 /* This move a window using outline rectangles if a window is mapped, and
376 updates cfgfile_item params accordingly. This is used by adesklets
377 if we created an `override_notify' window, and that therefore cannot take
378 advantage of any windows manager. Returns 1 if the window has been moved,
379 0 othermize.
380 NOTE: The window is not remmaped at the end if the move was sucessfull:
381 it is the duty of the caller to do so.
384 xwindow_move_window(Display * display, Window root, Window window,
385 cfgfile_item * params)
387 int dummy, grab_x, grab_y, old_x, old_y, x=0, y=0, result=0;
388 uint screen_width, screen_height;
389 XWindowAttributes attr;
390 XGCValues xgcvalues;
391 Window dummy_window;
392 GC gc;
393 Cursor cursor;
394 XEvent ev;
396 if (!(display && window)) return 0;
398 /* Test that main window is mapped,
399 and if screen size could be known */
400 if(XGetWindowAttributes(display,window,&attr) &&
401 attr.map_state!=IsUnmapped &&
402 xwindow_window_size(display,root,&screen_width,&screen_height)) {
403 /* Initialize a graphics context for the root window behind ours */
404 xgcvalues.function=GXxor;
405 xgcvalues.foreground=WhitePixel(display,params->scr);
406 xwindow_error_reset();
407 gc=XCreateGC(display,root,GCFunction|GCForeground,&xgcvalues);
408 /* Initialize cursor */
409 cursor = XCreateFontCursor(display,XC_fleur);
410 /* Initialize old coordinates */
411 old_x=attr.x; old_y=attr.y;
412 /* Unmap the window */
413 if (xwindow_error_check() &&
414 XUnmapWindow(display,window)) {
415 /* Query, then grab the pointer */
416 if(XQueryPointer(display, window, &dummy_window,
417 &dummy_window, &grab_x, &grab_y,
418 &dummy, &dummy, (uint*)&dummy) &&
419 XGrabPointer(display,root,True,
420 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
421 GrabModeAsync,GrabModeAsync,
422 root, cursor, 0)==GrabSuccess) {
423 /* Draw initial rectangle */
424 XDrawRectangle(display,root,gc,
425 attr.x,attr.y,attr.width-1,attr.height-1);
426 dummy=0;
427 do {
428 XWindowEvent(display,root,
429 PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
430 &ev);
431 switch(ev.type) {
432 case ButtonPress:
433 dummy=1;
434 break;
435 case ButtonRelease:
436 /* We want a button press in our window before we take
437 this into account: the idea is that we want to ignore
438 button release event from menu */
439 if(dummy) {
440 /* Erase final rectangle */
441 XDrawRectangle(display,root,gc,
442 old_x,old_y,attr.width-1,attr.height-1);
443 result=1;
445 break;
446 case MotionNotify:
447 /* Compute new coordinates. */
448 x=attr.x+(ev.xmotion.x-grab_x);
449 y=attr.y+(ev.xmotion.y-grab_y);
450 /* Rectifies it */
451 x=((x+attr.width)<screen_width)?x:screen_width-attr.width;
452 y=((y+attr.height)<screen_height)?y:screen_height-attr.height;
453 x=(x>0)?x:0;
454 y=(y>0)?y:0;
455 /* Draw rectangles: we use a GCxor function for
456 not having to remember background data. */
457 if ((x!=old_x) || (y!=old_y)) {
458 XDrawRectangle(display,root,gc,
459 old_x,old_y,attr.width-1,attr.height-1);
460 XDrawRectangle(display,root,gc,
461 x,y,attr.width-1,attr.height-1);
463 /* Save coordinates */
464 old_x=x; old_y=y;
465 break;
467 } while(!result);
468 XUngrabPointer(display,0);
469 if(old_x!=params->x || old_y!=params->y)
470 result=XMoveWindow(display,window,x,y);
472 /* Save new coordinates if it changed, remap the window otherwize */
473 if(old_x!=params->x||old_y!=params->y) {
474 params->x=old_x;
475 params->y=old_y;
476 } else
477 XMapWindow(display,window);
480 return result;
483 /*----------------------------------------------------------------------------*/
485 xwindow_resize_window(Display * display, Window window, cfgfile_item * item,
486 int width, int height, int force_update)
488 int x,y, result=0;
489 uint screen_width, screen_height;
490 XSizeHints * hints;
491 XWindowAttributes attr;
493 if (!(display && window)) return 0;
495 if (width>0 && height>=0 && XGetWindowAttributes(display, window, &attr)) {
496 if (force_update || width!=attr.width || height!=attr.height) {
497 if (attr.override_redirect) {
498 /* Unmanaged window: boundaries check */
499 screen_width=WidthOfScreen(ScreenOfDisplay(display,item->scr));
500 screen_height=HeightOfScreen(ScreenOfDisplay(display,item->scr));
501 x=item->x;
502 y=item->y;
503 x=(x+width>screen_width)?screen_width-width:x;
504 y=(y+height>screen_height)?screen_height-height:y;
506 if (x>=0 && y>=0)
507 if (XMoveResizeWindow(display,window,
508 x,y,(uint)width,(uint)height))
509 result=1;
510 } else {
511 /* Managed window: no boundary check */
512 xwindow_error_reset();
513 XResizeWindow(display,window,(uint)width,(uint)height);
514 if(xwindow_error_check()) {
515 /* WM_Hints settings */
516 if ((hints=XAllocSizeHints())) {
517 hints->min_width=hints->max_width=(uint)width;
518 hints->min_height=hints->max_height=(uint)height;
519 hints->flags=PMinSize|PMaxSize;
520 XSetWMNormalHints(display,window,hints);
521 XFree(hints);
523 result=1;
526 } else
527 if (!force_update) result=1;
529 return result;
532 #ifdef WM_DETECTION_OLD_STYLE
533 /*----------------------------------------------------------------------------*/
534 /* Here is a function that recursively calls itself (up to a limit) to find
535 the window ID of the KDE desktop to draw on. This is the hierarchy we're
536 trying to traverse:
538 -> The root window
539 0 -> window with name="KDE Desktop"
540 1 -> window with no name
541 2 -> window with name="KDE Desktop" & _NET_WM_WINDOW_TYPE_DESKTOP
542 3 -> window with no name and width >= width of screen
544 The last window in the hierarchy is the one to draw to. The
545 numbers show the value of the `depth' argument.
547 NOTE: This code was copied from xpenguins source code base -
548 http://xpenguins.seul.org/
550 static Window
551 xwindow_get_kde_desktop(Display *display, int screen, Window window,
552 Atom atom, char *atomname, int depth)
554 char *name = NULL;
555 unsigned char *wintype = NULL;
556 Window winreturn = 0;
557 unsigned long nitems, bytesafter;
558 Atom actual_type;
559 int actual_format;
560 Window rootReturn, parentReturn, *children;
561 unsigned int nChildren;
562 char go_deeper = 0;
563 if (XFetchName(display, window, &name)) {
564 if (strcasecmp(name, "KDE Desktop") == 0) {
565 /* Presumably either at depth 0 or 2 */
566 if (XGetWindowProperty(display, window, atom, 0, 1,
567 False, XA_ATOM,
568 &actual_type, &actual_format,
569 &nitems, &bytesafter,
570 &wintype) == Success
571 && wintype) {
572 char *tmpatomname = XGetAtomName(display, *((Atom*)wintype));
573 if (tmpatomname) {
574 if (strcmp(atomname, tmpatomname) == 0 && depth == 2) {
575 /* OK, at depth 2 */
576 go_deeper = 1;
578 XFree((char *) tmpatomname);
581 else if (depth < 2) {
582 go_deeper = 1;
585 else if (depth == 1) {
586 go_deeper = 1;
588 XFree((char *) name);
590 else if (depth == 1) {
591 go_deeper = 1;
593 /* If go_deeper is 1 then there is a possibility that the background
594 * window is a descendant of the current window; otherwise we're
595 * barking up the wrong tree. */
596 if (go_deeper && XQueryTree(display, window, &rootReturn,
597 &parentReturn, &children,
598 &nChildren)) {
599 int i;
600 for (i = 0; i < nChildren; ++i) {
601 /* children[i] is now at depth 3 */
602 if (depth == 2) {
603 XWindowAttributes attributes;
604 if (XGetWindowAttributes(display, children[i], &attributes)) {
605 if (attributes.width >= DisplayWidth(display, screen)/2
606 && attributes.height > 0) {
607 /* Found it! */
608 winreturn = children[i];
609 break;
613 else if ((winreturn = xwindow_get_kde_desktop(display, screen,
614 children[i],
615 atom, atomname,
616 depth+1))) {
617 break;
620 XFree((char *) children);
622 return winreturn;
625 /*----------------------------------------------------------------------------*/
626 /* Looks for the Nautilus desktop window to draw to, given the toplevel
627 window of the Nautilus desktop. Basically recursively calls itself
628 looking for subwindows the same size as the root window.
630 NOTE: This code was copied verbatim from xpenguins-2.2 source code base -
631 http://xpenguins.seul.org/
633 static Window
634 xwindow_get_nautilus_desktop(Display *display, int screen, Window window,
635 int depth)
637 Window rootReturn, parentReturn, *children;
638 Window winreturn = window;
639 unsigned int nChildren;
641 if (depth > 5) {
642 return ((Window) 0);
644 else if (XQueryTree(display, window, &rootReturn, &parentReturn,
645 &children, &nChildren)) {
646 int i;
647 for (i = 0; i < nChildren; ++i) {
648 XWindowAttributes attributes;
649 if (XGetWindowAttributes(display, children[i], &attributes)) {
650 if (attributes.width == DisplayWidth(display, screen)
651 && attributes.height == DisplayHeight(display, screen)) {
652 /* Found a possible desktop window */
653 winreturn = xwindow_get_nautilus_desktop(display, screen,
654 children[i], depth+1);
658 XFree((char *) children);
660 return winreturn;
662 #endif /* WM_DETECTION_OLD_STYLE */
664 /*----------------------------------------------------------------------------*/
665 /* Returns the root window, or the fake root window depending on
666 WM. Autodetect fake root for Xfce4, nautilus and KDE.
668 Window
669 xwindow_get_root_window(Display * display, int scr)
671 #ifdef WM_DETECTION_OLD_STYLE
672 int i;
673 unsigned long dummy;
674 Window rootReturn, parentReturn, *children;
675 unsigned int nChildren;
676 Window result = 0;
677 Window root = RootWindow(display,scr),
678 * toplevel = NULL;
679 Atom TYPE,
680 NAUTILUS_DESKTOP_WINDOW_ID = XInternAtom(display,
681 "NAUTILUS_DESKTOP_WINDOW_ID",
682 False);
684 if (XGetWindowProperty(display, root,
685 NAUTILUS_DESKTOP_WINDOW_ID,
686 0, 1, False, XA_WINDOW,
687 &TYPE,
688 (int*)((void*)&dummy),
689 &dummy,
690 &dummy,
691 (unsigned char **)((void*)&toplevel)) == Success
692 && toplevel)
693 result = xwindow_get_nautilus_desktop(display,scr,*toplevel,0);
695 /* Next look for a virtual root or a KDE Desktop */
696 if (!result
697 && XQueryTree(display, root, &rootReturn, &parentReturn,
698 &children, &nChildren)) {
699 Atom _NET_WM_WINDOW_TYPE = XInternAtom(display,
700 "_NET_WM_WINDOW_TYPE",
701 False);
702 Atom __SWM_VROOT = XInternAtom(display, "__SWM_VROOT", False);
704 for (i=0; i<nChildren && !result; ++i) {
705 Window *toplevel = (Window *) 0;
706 if (XGetWindowProperty(display, children[i],
707 __SWM_VROOT, 0, 1, False, XA_WINDOW,
708 &TYPE, (int*) ((void*)&dummy),
709 &dummy, &dummy,
710 (unsigned char **)((void*)&toplevel)) == Success
711 && toplevel)
712 /* KDE < 2.1 */
713 result = *toplevel;
714 else
715 /* KDE >= 2.1 */
716 result = xwindow_get_kde_desktop(display, scr, children[i],
717 _NET_WM_WINDOW_TYPE,
718 "_NET_WM_WINDOW_TYPE_DESKTOP",
719 0);
721 XFree((char *) children);
724 return (result)?result:root;
725 #else
726 uint window = 0;
727 char * root_env;
728 XWindowAttributes xattr;
730 /* Try reading the ADESKLETS_ROOT environment variable to identify the root */
731 if ((root_env=getenv("ADESKLETS_ROOT")) &&
732 sscanf(root_env,"%x", &window)==1)
733 if (XGetWindowAttributes(display, (Window)window, &xattr)==0) {
734 debug("Invalid 0x%x Windows given as root!", window);
735 window=0;
738 /* Use the specified window as root, or the real root otherwise */
739 return (window)?(Window)window:RootWindow(display, scr);
740 #endif /* WM_DETECTION_OLD_STYLE */
743 #endif /* X_MISSING_DISPLAY , far, far above! */
745 /*----------------------------------------------------------------------------*/
746 /* Save selected elements of imlib2 context for future restoration.
747 Note: This uses a vector `contextes' of context_backup references,
748 used like a stack (last-in, first-out): this lead to correct
749 recursive call of the function pairs xwindow_context_save().
750 and xwindow_context_restore().
752 void
753 xwindow_context_save(long mycontext)
755 context_backup * context;
757 /* Contextes initialisation */
758 if(!contextes && (!(contextes=vector_init()))) {
759 debug("Error initialising contexes!\n");
760 return;
763 /* New context initialisation */
764 if(!(context=(context_backup*)malloc(sizeof(context_backup)))) {
765 debug("Error initialising new context!\n");
766 return;
769 /* Save present context */
770 context->context=mycontext;
772 #ifdef X_DISPLAY_MISSING
773 mycontext&=~(IMLIB_DISPLAY|IMLIB_VISUAL|IMLIB_COLORMAP|IMLIB_DRAWABLE|
774 IMLIB_MASK|IMLIB_DITHER_MASK);
775 #endif
777 /* Most frequently saved items are traited first, for optimisation sake */
778 #define CONTEXT_ACTION(mask, x ) \
779 if(mycontext&(mask)) {\
780 x ;\
782 if(!(mycontext&=~(mask))) goto end_of_context_save
784 CONTEXT_ACTION(IMLIB_IMAGE,
785 context->image=imlib_context_get_image());
786 CONTEXT_ACTION(IMLIB_COLOR,
787 imlib_context_get_color(&context->red,
788 &context->green,
789 &context->blue,
790 &context->alpha));
791 CONTEXT_ACTION(IMLIB_BLEND,
792 context->blend=imlib_context_get_blend());
793 CONTEXT_ACTION(IMLIB_FONT,
794 context->font=imlib_context_get_font());
795 CONTEXT_ACTION(IMLIB_OPERATION,
796 context->operation=imlib_context_get_operation());
797 CONTEXT_ACTION(IMLIB_COLOR_RANGE,
798 context->color_range=imlib_context_get_color_range());
799 CONTEXT_ACTION(IMLIB_FILTER,
800 context->filter=imlib_context_get_filter());
801 #ifndef X_DISPLAY_MISSING
802 CONTEXT_ACTION(IMLIB_DISPLAY,
803 context->display=imlib_context_get_display());
804 CONTEXT_ACTION(IMLIB_VISUAL,
805 context->visual=imlib_context_get_visual());
806 CONTEXT_ACTION(IMLIB_COLORMAP,
807 context->colormap=imlib_context_get_colormap());
808 CONTEXT_ACTION(IMLIB_DRAWABLE,
809 context->drawable=imlib_context_get_drawable());
810 CONTEXT_ACTION(IMLIB_MASK,
811 context->mask=imlib_context_get_mask());
812 CONTEXT_ACTION(IMLIB_DITHER_MASK,
813 context->dither_mask=imlib_context_get_dither_mask());
814 #endif
815 CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
816 context->anti_alias=imlib_context_get_anti_alias());
817 CONTEXT_ACTION(IMLIB_DITHER,
818 context->dither=imlib_context_get_dither());
819 CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
820 context->color_modifier=
821 imlib_context_get_color_modifier());
822 CONTEXT_ACTION(IMLIB_DIRECTION,
823 context->direction=imlib_context_get_direction());
824 CONTEXT_ACTION(IMLIB_ANGLE,
825 context->angle=imlib_context_get_angle());
826 #undef CONTEXT_ACTION
828 /* This code should never be reached ! */
829 debug("Error in creating new context!\n");
831 end_of_context_save:
832 vector_push(contextes,context);
835 /*----------------------------------------------------------------------------*/
836 /* Restore a given imlib context, somewhere after a call
837 to xwindow_context_save */
838 void
839 xwindow_context_restore(void)
841 context_backup * context;
843 /* Verify there is comething to restore */
844 if(!contextes || !contextes->pos) {
845 debug("No context to restore!\n");
846 return;
849 /* Commodity setting */
850 context=(context_backup*)contextes->content[contextes->pos-1];
852 /* Most frequently saved items are traited first, for optimisation sake */
853 #define CONTEXT_ACTION(mask, x ) \
854 if(context->context&(mask)) {\
855 x ;\
857 if(!(context->context&=~(mask))) goto end_of_restore_context
859 CONTEXT_ACTION(IMLIB_IMAGE,
860 imlib_context_set_image(context->image));
861 CONTEXT_ACTION(IMLIB_COLOR,
862 imlib_context_set_color(context->red,
863 context->green,
864 context->blue,
865 context->alpha));
866 CONTEXT_ACTION(IMLIB_BLEND,
867 imlib_context_set_blend(context->blend));
868 CONTEXT_ACTION(IMLIB_FONT,
869 imlib_context_set_font(context->font));
870 CONTEXT_ACTION(IMLIB_OPERATION,
871 imlib_context_set_operation(context->operation));
872 CONTEXT_ACTION(IMLIB_COLOR_RANGE,
873 imlib_context_set_color_range(context->color_range));
874 CONTEXT_ACTION(IMLIB_FILTER,
875 imlib_context_set_filter(context->filter));
876 #ifndef X_DISPLAY_MISSING
877 CONTEXT_ACTION(IMLIB_DISPLAY,
878 imlib_context_set_display(context->display));
879 CONTEXT_ACTION(IMLIB_VISUAL,
880 imlib_context_set_visual(context->visual));
881 CONTEXT_ACTION(IMLIB_COLORMAP,
882 imlib_context_set_colormap(context->colormap));
883 CONTEXT_ACTION(IMLIB_DRAWABLE,
884 imlib_context_set_drawable(context->drawable));
885 CONTEXT_ACTION(IMLIB_MASK,
886 imlib_context_set_mask(context->mask));
887 CONTEXT_ACTION(IMLIB_DITHER_MASK,
888 imlib_context_set_dither_mask(context->dither_mask));
889 #endif
890 CONTEXT_ACTION(IMLIB_ANTI_ALIAS,
891 imlib_context_set_anti_alias(context->anti_alias));
892 CONTEXT_ACTION(IMLIB_DITHER,
893 imlib_context_set_dither(context->dither));
894 CONTEXT_ACTION(IMLIB_COLOR_MODIFIER,
895 imlib_context_set_color_modifier(context->color_modifier));
896 CONTEXT_ACTION(IMLIB_DIRECTION,
897 imlib_context_set_direction(context->direction));
898 CONTEXT_ACTION(IMLIB_ANGLE,
899 imlib_context_set_angle(context->angle));
900 #undef CONTEXT_ACTION
902 /* This code should never be reached ! */
903 debug("Error restoring context!\n");
905 end_of_restore_context:
906 vector_pop(contextes);
907 if(!contextes->pos)
908 contextes=vector_free(contextes);