517fcac706ae0b81cdfdc8341967a7d975730370
[framework/uifw/ecore.git] / src / lib / ecore_x / xlib / ecore_x_window.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 #include "Ecore.h"
5 #include "ecore_x_private.h"
6 #include "Ecore_X.h"
7 #include "Ecore_X_Atoms.h"
8
9 static int             ignore_num = 0;
10 static Ecore_X_Window *ignore_list = NULL;
11
12 /**
13  * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions
14  *
15  * Functions that can be used to create an X window.
16  */
17
18 /**
19  * Creates a new window.
20  * @param   parent The parent window to use.  If @p parent is @c 0, the root
21  *                 window of the default display is used.
22  * @param   x      X position.
23  * @param   y      Y position.
24  * @param   w      Width.
25  * @param   h      Height.
26  * @return  The new window handle.
27  * @ingroup Ecore_X_Window_Create_Group
28  */
29 EAPI Ecore_X_Window
30 ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h)
31 {
32    Window               win;
33    XSetWindowAttributes attr;
34    
35    if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp);
36    attr.backing_store         = NotUseful;
37    attr.override_redirect     = False;
38    attr.border_pixel          = 0;
39    attr.background_pixmap     = None;
40    attr.bit_gravity            = NorthWestGravity;
41    attr.win_gravity            = NorthWestGravity;
42    attr.save_under            = False;
43    attr.do_not_propagate_mask = NoEventMask;
44    attr.event_mask            = KeyPressMask |
45                                 KeyReleaseMask |
46                                 ButtonPressMask |
47                                 ButtonReleaseMask |
48                                 EnterWindowMask |
49                                 LeaveWindowMask |
50                                 PointerMotionMask |
51                                 ExposureMask |
52                                 VisibilityChangeMask |
53                                 StructureNotifyMask |
54                                 FocusChangeMask |
55                                 PropertyChangeMask |
56                                 ColormapChangeMask;
57    win = XCreateWindow(_ecore_x_disp, parent,
58                        x, y, w, h, 0,
59                        CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
60                        InputOutput, 
61                        CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
62                        CWBackingStore |
63                        CWOverrideRedirect | 
64 /*                     CWColormap | */
65                        CWBorderPixel |
66                        CWBackPixmap | 
67                        CWSaveUnder | 
68                        CWDontPropagate | 
69                        CWEventMask |
70                        CWBitGravity |
71                        CWWinGravity,
72                        &attr);
73
74    if (parent == DefaultRootWindow(_ecore_x_disp)) ecore_x_window_defaults_set(win);
75    return win;
76 }
77
78 /**
79  * Creates a window with the override redirect attribute set to @c True.
80  * @param   parent The parent window to use.  If @p parent is @c 0, the root
81  *                 window of the default display is used.
82  * @param   x      X position.
83  * @param   y      Y position.
84  * @param   w      Width.
85  * @param   h      Height.
86  * @return  The new window handle.
87  * @ingroup Ecore_X_Window_Create_Group
88  */
89 EAPI Ecore_X_Window
90 ecore_x_window_override_new(Ecore_X_Window parent, int x, int y, int w, int h)
91 {
92    Window               win;
93    XSetWindowAttributes attr;
94    
95    if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp);
96    attr.backing_store         = NotUseful;
97    attr.override_redirect     = True;
98    attr.border_pixel          = 0;
99    attr.background_pixmap     = None;
100    attr.bit_gravity           = NorthWestGravity;
101    attr.win_gravity           = NorthWestGravity;
102    attr.save_under            = False;
103    attr.do_not_propagate_mask = NoEventMask;
104    attr.event_mask            = KeyPressMask |
105                                 KeyReleaseMask |
106                                 ButtonPressMask |
107                                 ButtonReleaseMask |
108                                 EnterWindowMask |
109                                 LeaveWindowMask |
110                                 PointerMotionMask |
111                                 ExposureMask |
112                                 VisibilityChangeMask |
113                                 StructureNotifyMask |
114                                 FocusChangeMask |
115                                 PropertyChangeMask |
116                                 ColormapChangeMask;
117    win = XCreateWindow(_ecore_x_disp, parent,
118                        x, y, w, h, 0,
119                        CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
120                        InputOutput, 
121                        CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
122                        CWBackingStore |
123                        CWOverrideRedirect | 
124 /*                     CWColormap | */
125                        CWBorderPixel |
126                        CWBackPixmap | 
127                        CWSaveUnder | 
128                        CWDontPropagate | 
129                        CWEventMask |
130                        CWBitGravity |
131                        CWWinGravity,
132                        &attr);
133    return win;
134 }
135
136 /**
137  * Creates a new input window.
138  * @param   parent The parent window to use.    If @p parent is @c 0, the root
139  *                 window of the default display is used.
140  * @param   x      X position.
141  * @param   y      Y position.
142  * @param   w      Width.
143  * @param   h      Height.
144  * @return  The new window.
145  * @ingroup Ecore_X_Window_Create_Group
146  */
147 EAPI Ecore_X_Window
148 ecore_x_window_input_new(Ecore_X_Window parent, int x, int y, int w, int h)
149 {
150    Window               win;
151    XSetWindowAttributes attr;
152    
153    if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp);
154    attr.override_redirect     = True;
155    attr.do_not_propagate_mask = NoEventMask;
156    attr.event_mask            = KeyPressMask |
157                                 KeyReleaseMask |
158                                 ButtonPressMask |
159                                 ButtonReleaseMask |
160                                 EnterWindowMask |
161                                 LeaveWindowMask |
162                                 PointerMotionMask |
163                                 ExposureMask |
164                                 VisibilityChangeMask |
165                                 StructureNotifyMask |
166                                 FocusChangeMask |
167                                 PropertyChangeMask |
168                                 ColormapChangeMask;
169    win = XCreateWindow(_ecore_x_disp, parent,
170                        x, y, w, h, 0,
171                        CopyFromParent, 
172                        InputOnly,
173                        CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
174                        CWOverrideRedirect | 
175                        CWDontPropagate | 
176                        CWEventMask,
177                        &attr);
178
179    if (parent == DefaultRootWindow(_ecore_x_disp))
180      {
181      }
182    return win;
183 }
184
185 /**
186  * @defgroup Evas_X_Window_Properties_Group X Window Property Functions
187  *
188  * Functions that set window properties.
189  */
190
191 /**
192  * Sets the default properties for the given window.
193  *
194  * The default properties set for the window are @c WM_CLIENT_MACHINE and
195  * @c _NET_WM_PID.
196  *
197  * @param   win The given window.
198  * @ingroup Evas_X_Window_Properties_Groups
199  */
200 EAPI void
201 ecore_x_window_defaults_set(Ecore_X_Window win)
202 {
203    long pid;
204    char buf[MAXHOSTNAMELEN];
205    char *hostname[1];
206    int argc;
207    char **argv;
208    XTextProperty xprop;
209
210    /*
211     * Set WM_CLIENT_MACHINE.
212     */
213    gethostname(buf, MAXHOSTNAMELEN);
214    buf[MAXHOSTNAMELEN - 1] = '\0';
215    hostname[0] = buf;
216    /* The ecore function uses UTF8 which Xlib may not like (especially
217     * with older clients) */
218    /* ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE,
219                                   (char *)buf); */
220    if (XStringListToTextProperty(hostname, 1, &xprop))
221      {
222         XSetWMClientMachine(_ecore_x_disp, win, &xprop);
223         XFree(xprop.value);
224      }
225
226    /*
227     * Set _NET_WM_PID
228     */
229    pid = getpid();
230    ecore_x_netwm_pid_set(win, pid);
231
232    ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL);
233
234    ecore_app_args_get(&argc, &argv);
235    ecore_x_icccm_command_set(win, argc, argv);
236 }
237
238 EAPI void
239 ecore_x_window_configure(Ecore_X_Window win,
240                          Ecore_X_Window_Configure_Mask mask,
241                          int x, int y, int w, int h,
242                          int border_width, Ecore_X_Window sibling,
243                          int stack_mode)
244 {
245    XWindowChanges xwc;
246
247    if (!win)
248       return;
249
250    xwc.x = x;
251    xwc.y = y;
252    xwc.width = w;
253    xwc.height = h;
254    xwc.border_width = border_width;
255    xwc.sibling = sibling;
256    xwc.stack_mode = stack_mode;
257
258    XConfigureWindow(_ecore_x_disp, win, mask, &xwc);
259 }
260
261 /**
262  * @defgroup Evas_X_Window_Destroy_Group X Window Destroy Functions
263  *
264  * Functions to destroy X windows.
265  */
266
267 /**
268  * Deletes the given window.
269  * @param   win The given window.
270  * @ingroup Evas_X_Window_Destroy_Group
271  */
272 EAPI void
273 ecore_x_window_del(Ecore_X_Window win)
274 {
275    /* sorry sir, deleting the root window doesn't sound like
276     * a smart idea.
277     */
278    if (win)
279       XDestroyWindow(_ecore_x_disp, win);
280 }
281
282 /**
283  * Set if a window should be ignored.
284  * @param   win The given window.
285  * @param   ignore if to ignore
286  */
287 EAPI void
288 ecore_x_window_ignore_set(Ecore_X_Window win, int ignore)
289 {
290    int i, j;
291
292    if (ignore)
293      {
294         if (ignore_list)
295           {
296              for (i = 0; i < ignore_num; i++)
297                {
298                   if (win == ignore_list[i])
299                     return;
300                }
301              ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window));
302              if (!ignore_list) return;
303              ignore_list[ignore_num++] = win;
304           }
305         else
306           {
307              ignore_num = 0;
308              ignore_list = malloc(sizeof(Ecore_X_Window));
309              ignore_list[ignore_num++] = win;
310           }
311      }
312    else
313      {
314         if (!ignore_list) return;
315         for (i = 0, j = 0; i < ignore_num; i++)
316           {
317              if (win != ignore_list[i])
318                ignore_list[i] = ignore_list[j++];
319              else
320                ignore_num--;
321           }
322         ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
323      }
324 }
325
326 /**
327  * Get the ignore list
328  * @param   num number of windows in the list
329  * @return  list of windows to ignore
330  */
331 EAPI Ecore_X_Window *
332 ecore_x_window_ignore_list(int *num)
333 {
334    if (num) *num = ignore_num;
335    return ignore_list;
336 }
337
338 /**
339  * Sends a delete request to the given window.
340  * @param   win The given window.
341  * @ingroup Evas_X_Window_Destroy_Group
342  */
343 EAPI void
344 ecore_x_window_delete_request_send(Ecore_X_Window win)
345 {
346    XEvent xev;
347
348    /* sorry sir, deleting the root window doesn't sound like
349     * a smart idea.
350     */
351    if (!win)
352       return;
353
354    xev.xclient.type = ClientMessage;
355    xev.xclient.display = _ecore_x_disp;
356    xev.xclient.window = win;
357    xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
358    xev.xclient.format = 32;
359    xev.xclient.data.l[0] = ECORE_X_ATOM_WM_DELETE_WINDOW;
360    xev.xclient.data.l[1] = CurrentTime;
361
362    XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
363 }
364
365 /**
366  * @defgroup Evas_X_Window_Visibility_Group X Window Visibility Functions
367  *
368  * Functions to access and change the visibility of X windows.
369  */
370
371 /**
372  * Shows a window.
373  *
374  * Synonymous to "mapping" a window in X Window System terminology.
375  *
376  * @param   win The window to show.
377  * @ingroup Evas_X_Window_Visibility
378  */
379 EAPI void
380 ecore_x_window_show(Ecore_X_Window win)
381 {
382    XMapWindow(_ecore_x_disp, win);
383 }
384
385 /**
386  * Hides a window.
387  *
388  * Synonymous to "unmapping" a window in X Window System terminology.
389  *
390  * @param   win The window to hide.
391  * @ingroup Evas_X_Window_Visibility
392  */
393 EAPI void
394 ecore_x_window_hide(Ecore_X_Window win)
395 {
396    XEvent xev;
397    Window root;
398    int idum;
399    unsigned int uidum;
400
401    /* ICCCM: SEND unmap event... */
402    root = win;
403    if (ScreenCount(_ecore_x_disp) == 1)
404      root = DefaultRootWindow(_ecore_x_disp);
405    else
406      XGetGeometry(_ecore_x_disp, win, &root, &idum, &idum, &uidum, &uidum, &uidum, &uidum);
407    xev.xunmap.type = UnmapNotify;
408    xev.xunmap.serial = 0;
409    xev.xunmap.send_event = True;
410    xev.xunmap.display = _ecore_x_disp;
411    xev.xunmap.event = root;
412    xev.xunmap.window = win;
413    xev.xunmap.from_configure = False;
414    XSendEvent(_ecore_x_disp, xev.xunmap.event, False,
415               SubstructureRedirectMask | SubstructureNotifyMask, &xev);
416    XUnmapWindow(_ecore_x_disp, win);
417 }
418
419 /**
420  * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions
421  *
422  * Functions that change or retrieve the geometry of X windows.
423  */
424
425 /**
426  * Moves a window to the position @p x, @p y.
427  *
428  * The position is relative to the upper left hand corner of the
429  * parent window.
430  *
431  * @param   win The window to move.
432  * @param   x   X position.
433  * @param   y   Y position.
434  * @ingroup Ecore_X_Window_Geometry_Group
435  */
436 EAPI void
437 ecore_x_window_move(Ecore_X_Window win, int x, int y)
438 {
439    XMoveWindow(_ecore_x_disp, win, x, y);
440 }
441
442 /**
443  * Resizes a window.
444  * @param   win The window to resize.
445  * @param   w   New width of the window.
446  * @param   h   New height of the window.
447  * @ingroup Ecore_X_Window_Geometry_Group
448  */
449 EAPI void
450 ecore_x_window_resize(Ecore_X_Window win, int w, int h)
451 {
452    if (w < 1) w = 1;
453    if (h < 1) h = 1;
454    XResizeWindow(_ecore_x_disp, win, w, h);
455 }
456
457 /**
458  * Moves and resizes a window.
459  * @param   win The window to move and resize.
460  * @param   x   New X position of the window.
461  * @param   y   New Y position of the window.
462  * @param   w   New width of the window.
463  * @param   h   New height of the window.
464  * @ingroup Ecore_X_Window_Geometry_Group
465  */
466 EAPI void
467 ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h)
468 {
469    if (w < 1) w = 1;
470    if (h < 1) h = 1;
471    XMoveResizeWindow(_ecore_x_disp, win, x, y, w, h);
472 }
473
474 /**
475  * @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions
476  *
477  * Functions that give the focus to an X Window.
478  */
479
480 /**
481  * Sets the focus to the window @p win.
482  * @param   win The window to focus.
483  * @ingroup Ecore_X_Window_Focus_Functions
484  */
485 EAPI void
486 ecore_x_window_focus(Ecore_X_Window win)
487 {
488    if (win == 0) win = DefaultRootWindow(_ecore_x_disp);   
489 //   XSetInputFocus(_ecore_x_disp, win, RevertToNone, CurrentTime);
490    XSetInputFocus(_ecore_x_disp, win, RevertToPointerRoot, CurrentTime);
491 }
492
493 /**
494  * Sets the focus to the given window at a specific time.
495  * @param   win The window to focus.
496  * @param   t   When to set the focus to the window.
497  * @ingroup Ecore_X_Window_Focus_Functions
498  */
499 EAPI void
500 ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time t)
501 {
502    if (win == 0) win = DefaultRootWindow(_ecore_x_disp);   
503 //   XSetInputFocus(_ecore_x_disp, win, RevertToNone, t);
504    XSetInputFocus(_ecore_x_disp, win, PointerRoot, t);
505 }
506
507 /**
508  * gets the focus to the window @p win.
509  * @return  The window that has focus.
510  * @ingroup Ecore_X_Window_Focus_Functions
511  */
512 EAPI Ecore_X_Window
513 ecore_x_window_focus_get(void)
514 {
515    Window win;
516    int revert_mode;
517    
518    win = 0;
519    
520    XGetInputFocus(_ecore_x_disp, &win, &revert_mode);
521    return win;
522 }
523
524 /**
525  * @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions
526  *
527  * Functions that change the Z order of X windows.
528  */
529
530 /**
531  * Raises the given window.
532  * @param   win The window to raise.
533  * @ingroup Ecore_X_Window_Z_Order_Group
534  */
535 EAPI void
536 ecore_x_window_raise(Ecore_X_Window win)
537 {
538    XRaiseWindow(_ecore_x_disp, win);
539 }
540
541 /**
542  * Lowers the given window.
543  * @param   win The window to lower.
544  * @ingroup Ecore_X_Window_Z_Order_Group
545  */
546 EAPI void
547 ecore_x_window_lower(Ecore_X_Window win)
548 {
549    XLowerWindow(_ecore_x_disp, win);
550 }
551
552 /**
553  * @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions
554  *
555  * Functions that retrieve or changes the parent window of a window.
556  */
557
558 /**
559  * Moves a window to within another window at a given position.
560  * @param   win        The window to reparent.
561  * @param   new_parent The new parent window.
562  * @param   x          X position within new parent window.
563  * @param   y          Y position within new parent window.
564  * @ingroup Ecore_X_Window_Parent_Group
565  */
566 EAPI void
567 ecore_x_window_reparent(Ecore_X_Window win, Ecore_X_Window new_parent, int x, int y)
568 {
569    if (new_parent == 0) new_parent = DefaultRootWindow(_ecore_x_disp);   
570    XReparentWindow(_ecore_x_disp, win, new_parent, x, y);
571 }
572
573 /**
574  * Retrieves the size of the given window.
575  * @param   win The given window.
576  * @param   w   Pointer to an integer into which the width is to be stored.
577  * @param   h   Pointer to an integer into which the height is to be stored.
578  * @ingroup Ecore_X_Window_Geometry_Group
579  */
580 EAPI void
581 ecore_x_window_size_get(Ecore_X_Window win, int *w, int *h)
582 {
583    int dummy_x, dummy_y;
584    
585    if (win == 0) 
586       win = DefaultRootWindow(_ecore_x_disp);
587
588    ecore_x_drawable_geometry_get(win, &dummy_x, &dummy_y, w, h);
589 }
590
591 /**
592  * Retrieves the geometry of the given window.
593  * @param   win The given window.
594  * @param   x   Pointer to an integer in which the X position is to be stored.
595  * @param   y   Pointer to an integer in which the Y position is to be stored.
596  * @param   w   Pointer to an integer in which the width is to be stored.
597  * @param   h   Pointer to an integer in which the height is to be stored.
598  * @ingroup Ecore_X_Window_Geometry_Group
599  */
600 EAPI void
601 ecore_x_window_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h)
602 {
603    if (!win)
604       win = DefaultRootWindow(_ecore_x_disp);
605
606    ecore_x_drawable_geometry_get(win, x, y, w, h);
607 }
608
609 /**
610  * Retrieves the width of the border of the given window.
611  * @param   win The given window.
612  * @return  Width of the border of @p win.
613  * @ingroup Ecore_X_Window_Geometry_Group
614  */
615 EAPI int
616 ecore_x_window_border_width_get(Ecore_X_Window win)
617 {
618    /* doesn't make sense to call this on a root window */
619    if (!win)
620       return 0;
621
622    return ecore_x_drawable_border_width_get(win);
623 }
624
625 /**
626  * Sets the width of the border of the given window.
627  * @param   win The given window.
628  * @param   width The new border width.
629  * @ingroup Ecore_X_Window_Geometry_Group
630  */
631 EAPI void
632 ecore_x_window_border_width_set(Ecore_X_Window win, int width)
633 {
634    /* doesn't make sense to call this on a root window */
635    if (!win)
636       return;
637
638    XSetWindowBorderWidth (_ecore_x_disp, win, width);
639 }
640
641 /**
642  * Retrieves the depth of the given window.
643  * @param  win The given window.
644  * @return Depth of the window.
645  */
646 EAPI int
647 ecore_x_window_depth_get(Ecore_X_Window win)
648 {
649    return ecore_x_drawable_depth_get(win);
650 }
651   
652 /**
653  * To be documented.
654  *
655  * FIXME: To be fixed.
656  */
657 EAPI void
658 ecore_x_window_cursor_show(Ecore_X_Window win, int show)
659 {
660    if (win == 0) win = DefaultRootWindow(_ecore_x_disp);
661    if (!show)
662      {
663         Cursor              c;
664         XColor              cl;
665         Pixmap              p, m;
666         GC                  gc;
667         XGCValues           gcv;
668         
669         p = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
670         m = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
671         gc = XCreateGC(_ecore_x_disp, m, 0, &gcv);
672         XSetForeground(_ecore_x_disp, gc, 0);
673         XDrawPoint(_ecore_x_disp, m, gc, 0, 0);
674         XFreeGC(_ecore_x_disp, gc);
675         c = XCreatePixmapCursor(_ecore_x_disp, p, m, &cl, &cl, 0, 0);
676         XDefineCursor(_ecore_x_disp, win, c);
677         XFreeCursor(_ecore_x_disp, c);
678         XFreePixmap(_ecore_x_disp, p);
679         XFreePixmap(_ecore_x_disp, m);
680      }
681    else
682      {
683         XDefineCursor(_ecore_x_disp, win, 0);   
684      }
685 }
686
687 EAPI void
688 ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor c)
689 {
690    if (c == 0)
691      XUndefineCursor(_ecore_x_disp, win);
692    else
693      XDefineCursor(_ecore_x_disp, win, c);
694 }
695
696 /**
697  * Finds out whether the given window is currently visible.
698  * @param   win The given window.
699  * @return  1 if the window is visible, otherwise 0.
700  * @ingroup Ecore_X_Window_Visibility_Group
701  */
702 EAPI int
703 ecore_x_window_visible_get(Ecore_X_Window win)
704 {
705    XWindowAttributes attr;
706
707    return (XGetWindowAttributes(_ecore_x_disp, win, &attr) &&
708            (attr.map_state == IsViewable));
709 }
710
711
712
713 typedef struct _Shadow Shadow;
714 struct _Shadow
715 {
716    Shadow         *parent;
717    Shadow        **children;
718    Window          win;
719    int             children_num;
720    short           x, y;
721    unsigned short  w, h;
722 };
723
724 static int shadow_count = 0;
725 static Shadow **shadow_base = NULL;
726 static int shadow_num = 0;
727
728 static Shadow *
729 _ecore_x_window_tree_walk(Window win)
730 {
731    Window           *list = NULL;
732    Window            parent_win = 0, root_win = 0;
733    int               i, j;
734    unsigned int      num;
735    Shadow           *s, **sl;
736    XWindowAttributes att;
737
738    if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return NULL;
739 //   if (att.class == InputOnly) return NULL;
740    if (att.map_state != IsViewable) return NULL;
741    
742    s = calloc(1, sizeof(Shadow));
743    if (!s) return NULL;
744    s->win = win;
745    s->x = att.x;
746    s->y = att.y;
747    s->w = att.width;
748    s->h = att.height;
749    if (XQueryTree(_ecore_x_disp, s->win, &root_win, &parent_win,
750                    &list, &num))
751      {
752         s->children = calloc(1, sizeof(Shadow *) * num);
753         if (s->children)
754           {
755              s->children_num = num;
756              for (i = 0; i < num; i++)
757                {
758                   s->children[i] = _ecore_x_window_tree_walk(list[i]);
759                   if (s->children[i]) s->children[i]->parent = s;
760                }
761              /* compress list down */
762              j = 0;
763              for (i = 0; i < num; i++)
764                {
765                   if (s->children[i])
766                     {
767                        s->children[j] = s->children[i];
768                        j++;
769                     }
770                }
771              if (j == 0)
772                {
773                   free(s->children);
774                   s->children = NULL;
775                   s->children_num = 0;
776                }
777              else
778                {
779                   s->children_num = j;
780                   sl = realloc(s->children, sizeof(Shadow *) * j);
781                   if (sl) s->children = sl;
782                }
783           }
784      }
785    return s;
786 }
787
788 static void
789 _ecore_x_window_tree_shadow_free1(Shadow *s)
790 {
791    int i;
792
793    if (!s) return;
794    if (s->children)
795      {
796         for (i = 0; i < s->children_num; i++)
797           {
798              if (s->children[i])
799                _ecore_x_window_tree_shadow_free1(s->children[i]);
800           }
801         free(s->children);
802      }
803    free(s);
804 }
805
806 static void
807 _ecore_x_window_tree_shadow_free(void)
808 {
809    int i;
810    
811    if (!shadow_base) return;
812    for (i = 0; i < shadow_num; i++)
813      {
814         if (!shadow_base[i]) continue;
815         _ecore_x_window_tree_shadow_free1(shadow_base[i]);
816      }
817    free(shadow_base);
818    shadow_base = NULL;
819    shadow_num = 0;
820 }
821
822 static void
823 _ecore_x_window_tree_shadow_populate(void)
824 {
825    Ecore_X_Window   *roots;
826    int               i, num;
827    
828    roots = ecore_x_window_root_list(&num);
829    if (roots)
830      {
831         shadow_base = calloc(1, sizeof(Shadow *) * num);
832         if (shadow_base)
833           {
834              shadow_num = num;
835              for (i = 0; i < num; i++)
836                shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
837           }
838         free(roots);
839      }
840 }
841
842 static void
843 _ecore_x_window_tree_shadow_start(void)
844 {
845    shadow_count++;
846    if (shadow_count > 1) return;
847    _ecore_x_window_tree_shadow_populate();
848 }
849
850 static void
851 _ecore_x_window_tree_shadow_stop(void)
852 {
853    shadow_count--;
854    if (shadow_count != 0) return;
855    _ecore_x_window_tree_shadow_free();
856 }
857
858 Shadow *
859 _ecore_x_window_shadow_tree_find_shadow(Shadow *s, Window win)
860 {
861    Shadow *ss;
862    int i;
863
864    if (s->win == win) return s;
865    if (s->children)
866      {
867         for (i = 0; i < s->children_num; i++)
868           {
869              if (!s->children[i]) continue;
870              if ((ss = _ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
871                return ss;
872           }
873      }
874    return NULL;
875 }
876
877 Shadow *
878 _ecore_x_window_shadow_tree_find(Window base)
879 {
880    Shadow *s;
881    int i;
882
883    for (i = 0; i < shadow_num; i++)
884      {
885         if (!shadow_base[i]) continue;
886         if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
887           return s;
888      }
889    return NULL;
890 }
891
892 static Window
893 _ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, int bx, int by, int x, int y,
894                                              Ecore_X_Window *skip, int skip_num)
895 {
896    Window child;
897    int i, j;
898    int wx, wy;
899    
900    wx = s->x + bx;
901    wy = s->y + by;
902    if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
903      return 0;
904    if (s->children)
905      {
906         int skipit = 0;
907         
908         for (i = s->children_num - 1; i >= 0; --i)
909           {
910              if (!s->children[i]) continue;
911              skipit = 0;
912              if (skip)
913                {
914                   for (j = 0; j < skip_num; j++)
915                     {
916                        if (s->children[i]->win == skip[j])
917                          {
918                             skipit = 1;
919                             goto onward;
920                          }
921                     }
922                }
923              onward:
924              if (!skipit)
925                {
926                   if ((child = _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num)))
927                     {
928                        return child;
929                     }
930                }
931           }
932      }
933    return s->win;
934 }
935
936 static Window
937 _ecore_x_window_shadow_tree_at_xy_get(Window base, int bx, int by, int x, int y,
938                                       Ecore_X_Window *skip, int skip_num)
939 {
940    Shadow *s;
941    
942    if (!shadow_base)
943      {
944         _ecore_x_window_tree_shadow_populate();
945         if (!shadow_base) return 0;
946      }
947    s = _ecore_x_window_shadow_tree_find(base);
948    if (!s) return 0;
949    return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num);
950 }
951
952 /**
953  * Retrieves the top, visible window at the given location,
954  * but skips the windows in the list. This uses a shadow tree built from the
955  * window tree that is only updated the first time
956  * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
957  * it is called after a  ecore_x_window_shadow_tree_flush()
958  * @param   base The base window to start searching from (normally root).
959  * @param   x The given X position.
960  * @param   y The given Y position.
961  * @return  The window at that position.
962  * @ingroup Ecore_X_Window_Geometry_Group
963  */
964 EAPI Ecore_X_Window
965 ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y, Ecore_X_Window *skip, int skip_num)
966 {
967    return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num);
968 }
969
970 /**
971  * Retrieves the parent window a given window has. This uses the shadow window
972  * tree.
973  * @param   root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
974  * @param   win The window to get the parent window of
975  * @return  The parent window of @p win
976  * @ingroup Ecore_X_Window_Geometry_Group
977  */
978 EAPI Ecore_X_Window
979 ecore_x_window_shadow_parent_get(Ecore_X_Window root, Ecore_X_Window win)
980 {
981    Shadow *s;
982    int i;
983    
984    if (!shadow_base)
985      {
986         _ecore_x_window_tree_shadow_populate();
987         if (!shadow_base) return 0;
988      }
989    for (i = 0; i < shadow_num; i++)
990      {
991         if (!shadow_base[i]) continue;
992         s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
993         if (s)
994           {
995              if (!s->parent) return 0;
996              return s->parent->win;
997           }
998      }
999    return 0;
1000 }
1001
1002 /**
1003  * Flushes the window shadow tree so nothing is stored.
1004  * @ingroup Ecore_X_Window_Geometry_Group
1005  */
1006 EAPI void
1007 ecore_x_window_shadow_tree_flush(void)
1008 {
1009    _ecore_x_window_tree_shadow_free();
1010 }
1011
1012 /**
1013  * Retrieves the root window a given window is on.
1014  * @param   win The window to get the root window of
1015  * @return  The root window of @p win
1016  * @ingroup Ecore_X_Window_Geometry_Group
1017  */
1018 EAPI Ecore_X_Window
1019 ecore_x_window_root_get(Ecore_X_Window win)
1020 {
1021    XWindowAttributes att;
1022
1023    if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0;
1024    return att.root;
1025 }
1026
1027 static Window
1028 _ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y,
1029                           Ecore_X_Window *skip, int skip_num)
1030 {
1031    Window           *list = NULL;
1032    Window            parent_win = 0, child = 0, root_win = 0;
1033    int               i, j, wx, wy, ww, wh;
1034    unsigned int      num;
1035
1036    if (!ecore_x_window_visible_get(base))
1037      return 0;
1038
1039    ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh);
1040    wx += bx;
1041    wy += by;
1042
1043    if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh))))
1044      return 0;
1045
1046    if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num))
1047      return base;
1048
1049    if (list)
1050      {
1051         int skipit = 0;
1052         
1053         for (i = num - 1; i >= 0; --i)
1054           {
1055              skipit = 0;
1056              
1057              if (skip)
1058                {
1059                   for (j = 0; j < skip_num; j++)
1060                     {
1061                        if (list[i] == skip[j])
1062                          {
1063                             skipit = 1;
1064                             goto onward;
1065                          }
1066                     }
1067                }
1068              onward:
1069              if (!skipit)
1070                {
1071                   if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, skip_num)))
1072                     {
1073                        XFree(list);
1074                        return child;
1075                     }
1076                }
1077           }
1078         XFree(list);
1079      }
1080    return base;
1081 }
1082
1083 /**
1084  * Retrieves the top, visible window at the given location.
1085  * @param   x The given X position.
1086  * @param   y The given Y position.
1087  * @return  The window at that position.
1088  * @ingroup Ecore_X_Window_Geometry_Group
1089  */
1090 EAPI Ecore_X_Window
1091 ecore_x_window_at_xy_get(int x, int y)
1092 {
1093    Ecore_X_Window    win, root;
1094    
1095    /* FIXME: Proper function to determine current root/virtual root
1096     * window missing here */
1097    root = DefaultRootWindow(_ecore_x_disp);
1098    
1099    ecore_x_grab();
1100    win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
1101    ecore_x_ungrab();
1102    
1103    return win ? win : root;
1104 }
1105
1106 /**
1107  * Retrieves the top, visible window at the given location,
1108  * but skips the windows in the list.
1109  * @param   x The given X position.
1110  * @param   y The given Y position.
1111  * @return  The window at that position.
1112  * @ingroup Ecore_X_Window_Geometry_Group
1113  */
1114 EAPI Ecore_X_Window
1115 ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num)
1116 {
1117    Ecore_X_Window    win, root;
1118    
1119    /* FIXME: Proper function to determine current root/virtual root
1120     * window missing here */
1121    root = DefaultRootWindow(_ecore_x_disp);
1122    
1123    ecore_x_grab();
1124    win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
1125    ecore_x_ungrab();
1126    
1127    return win ? win : root;
1128 }
1129
1130 EAPI Ecore_X_Window
1131 ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y)
1132 {
1133    Ecore_X_Window    win;
1134    
1135    ecore_x_grab();
1136    win = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0);
1137    ecore_x_ungrab();
1138    
1139    return win ? win : begin;
1140 }
1141
1142 /**
1143  * Retrieves the parent window of the given window.
1144  * @param   win The given window.
1145  * @return  The parent window of @p win.
1146  * @ingroup Ecore_X_Window_Parent_Group
1147  */
1148 EAPI Ecore_X_Window
1149 ecore_x_window_parent_get(Ecore_X_Window win)
1150 {
1151    Window         root, parent, *children = NULL;
1152    unsigned int   num;
1153
1154    if (!XQueryTree(_ecore_x_disp, win, &root, &parent, &children, &num))
1155       return 0;
1156    if (children)
1157       XFree(children);
1158
1159    return parent;
1160 }
1161
1162 /**
1163  * Sets the background color of the given window.
1164  * @param win   The given window
1165  * @param r     red value (0...65536, 16 bits)
1166  * @param g     green value (0...65536, 16 bits)
1167  * @param b     blue value (0...65536, 16 bits)
1168  */
1169 EAPI void
1170 ecore_x_window_background_color_set(Ecore_X_Window win, unsigned short r,
1171                                     unsigned short g, unsigned short b)
1172 {
1173    XSetWindowAttributes attr;
1174    Colormap map;
1175    XColor col;
1176
1177    col.red = r;
1178    col.green = g;
1179    col.blue = b;
1180
1181    map = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp));
1182    XAllocColor(_ecore_x_disp, map, &col);
1183
1184    attr.background_pixel = col.pixel;
1185    XChangeWindowAttributes(_ecore_x_disp, win, CWBackPixel, &attr);
1186 }
1187
1188 EAPI void
1189 ecore_x_window_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav)
1190 {
1191    XSetWindowAttributes att;
1192    
1193    att.win_gravity = grav;
1194    XChangeWindowAttributes(_ecore_x_disp, win, CWWinGravity, &att);
1195 }
1196
1197 EAPI void
1198 ecore_x_window_pixel_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav)
1199 {
1200    XSetWindowAttributes att;
1201    
1202    att.bit_gravity = grav;
1203    XChangeWindowAttributes(_ecore_x_disp, win, CWBitGravity, &att);
1204 }
1205
1206 EAPI void
1207 ecore_x_window_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pmap)
1208 {
1209    XSetWindowBackgroundPixmap(_ecore_x_disp, win, pmap);
1210 }
1211
1212 EAPI void
1213 ecore_x_window_area_clear(Ecore_X_Window win, int x, int y, int w, int h)
1214 {
1215    XClearArea(_ecore_x_disp, win, x, y, w, h, False);
1216 }
1217
1218 EAPI void
1219 ecore_x_window_area_expose(Ecore_X_Window win, int x, int y, int w, int h)
1220 {
1221    XClearArea(_ecore_x_disp, win, x, y, w, h, True);
1222 }
1223
1224 EAPI void
1225 ecore_x_window_override_set(Ecore_X_Window win, int override)
1226 {
1227    XSetWindowAttributes att;
1228    
1229    att.override_redirect = override;
1230    XChangeWindowAttributes(_ecore_x_disp, win, CWOverrideRedirect, &att);
1231 }
1232
1233 #ifdef ECORE_XRENDER   
1234 static Ecore_X_Window
1235 _ecore_x_window_argb_internal_new(Ecore_X_Window parent, int x, int y, int w, int h, int override, int saveunder)
1236 {
1237    Window                win;
1238    XSetWindowAttributes  attr;
1239    XWindowAttributes     att;
1240    XVisualInfo          *xvi;
1241    XVisualInfo           vi_in;
1242    int                   nvi, i, scr = 0;
1243    XRenderPictFormat    *fmt;
1244    Visual               *vis;
1245    
1246    if (parent == 0)
1247      {
1248         parent = DefaultRootWindow(_ecore_x_disp);
1249         scr = DefaultScreen(_ecore_x_disp);
1250      }
1251    else
1252      {
1253         /* ewww - round trip */
1254         XGetWindowAttributes(_ecore_x_disp, parent, &att);
1255         for (i = 0; i < ScreenCount(_ecore_x_disp); i++)
1256           {
1257              if (att.screen == ScreenOfDisplay(_ecore_x_disp, i))
1258                {
1259                   scr = i;
1260                   break;
1261                }
1262           }
1263      }
1264    vi_in.screen = scr;
1265    vi_in.depth = 32;
1266    vi_in.class = TrueColor;
1267    xvi = XGetVisualInfo(_ecore_x_disp,
1268                         VisualScreenMask |
1269                         VisualDepthMask |
1270                         VisualClassMask,
1271                         &vi_in,
1272                         &nvi);
1273    if (xvi == NULL) return 0;
1274    vis = NULL;
1275    for (i = 0; i < nvi; i++)
1276      {
1277         fmt = XRenderFindVisualFormat(_ecore_x_disp, xvi[i].visual);
1278         if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
1279           {
1280              vis = xvi[i].visual;
1281              break;
1282           }
1283      }
1284    XFree (xvi);
1285    
1286    attr.backing_store         = NotUseful;
1287    attr.override_redirect     = override;
1288    attr.colormap              = XCreateColormap(_ecore_x_disp, parent,
1289                                                 vis, AllocNone);
1290    attr.border_pixel          = 0;
1291    attr.background_pixmap     = None;
1292    attr.bit_gravity           = NorthWestGravity;
1293    attr.win_gravity           = NorthWestGravity;
1294    attr.save_under            = saveunder;
1295    attr.do_not_propagate_mask = NoEventMask;
1296    attr.event_mask            = KeyPressMask |
1297                                 KeyReleaseMask |
1298                                 ButtonPressMask |
1299                                 ButtonReleaseMask |
1300                                 EnterWindowMask |
1301                                 LeaveWindowMask |
1302                                 PointerMotionMask |
1303                                 ExposureMask |
1304                                 VisibilityChangeMask |
1305                                 StructureNotifyMask |
1306                                 FocusChangeMask |
1307                                 PropertyChangeMask |
1308                                 ColormapChangeMask;
1309    win = XCreateWindow(_ecore_x_disp, parent,
1310                        x, y, w, h, 0,
1311                        32, 
1312                        InputOutput, 
1313                        vis,
1314                        CWBackingStore |
1315                        CWOverrideRedirect | 
1316                        CWColormap |
1317                        CWBorderPixel |
1318                        CWBackPixmap | 
1319                        CWSaveUnder | 
1320                        CWDontPropagate | 
1321                        CWEventMask |
1322                        CWBitGravity |
1323                        CWWinGravity,
1324                        &attr);
1325    XFreeColormap(_ecore_x_disp, attr.colormap);
1326
1327    if (parent == DefaultRootWindow(_ecore_x_disp)) ecore_x_window_defaults_set(win);
1328    return win;
1329 }
1330 #endif
1331
1332 EAPI int
1333 ecore_x_window_argb_get(Ecore_X_Window win)
1334 {
1335 #ifdef ECORE_XRENDER   
1336    XWindowAttributes att;
1337    XRenderPictFormat *fmt;
1338    
1339    XGetWindowAttributes(_ecore_x_disp, win, &att);
1340    fmt = XRenderFindVisualFormat(_ecore_x_disp, att.visual);
1341    if (!fmt) return 0;
1342    if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask)) return 1;
1343    return 0;
1344 #else
1345    return 0;
1346 #endif   
1347 }
1348
1349 /**
1350  * Creates a new window.
1351  * @param   parent The parent window to use.  If @p parent is @c 0, the root
1352  *                 window of the default display is used.
1353  * @param   x      X position.
1354  * @param   y      Y position.
1355  * @param   w      Width.
1356  * @param   h      Height.
1357  * @return  The new window handle.
1358  * @ingroup Ecore_X_Window_Create_Group
1359  */
1360 EAPI Ecore_X_Window
1361 ecore_x_window_manager_argb_new(Ecore_X_Window parent, int x, int y, int w, int h)
1362 {
1363 #ifdef ECORE_XRENDER   
1364    return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
1365 #else
1366    return 0;
1367 #endif   
1368 }
1369
1370 /**
1371  * Creates a new window.
1372  * @param   parent The parent window to use.  If @p parent is @c 0, the root
1373  *                 window of the default display is used.
1374  * @param   x      X position.
1375  * @param   y      Y position.
1376  * @param   w      Width.
1377  * @param   h      Height.
1378  * @return  The new window handle.
1379  * @ingroup Ecore_X_Window_Create_Group
1380  */
1381 EAPI Ecore_X_Window
1382 ecore_x_window_argb_new(Ecore_X_Window parent, int x, int y, int w, int h)
1383 {
1384 #ifdef ECORE_XRENDER   
1385    return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 0, 0);
1386 #else
1387    return 0;
1388 #endif   
1389 }
1390
1391 /**
1392  * Creates a window with the override redirect attribute set to @c True.
1393  * @param   parent The parent window to use.  If @p parent is @c 0, the root
1394  *                 window of the default display is used.
1395  * @param   x      X position.
1396  * @param   y      Y position.
1397  * @param   w      Width.
1398  * @param   h      Height.
1399  * @return  The new window handle.
1400  * @ingroup Ecore_X_Window_Create_Group
1401  */
1402 EAPI Ecore_X_Window
1403 ecore_x_window_override_argb_new(Ecore_X_Window parent, int x, int y, int w, int h)
1404 {
1405 #ifdef ECORE_XRENDER   
1406    return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
1407 #else
1408    return 0;
1409 #endif   
1410 }