1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4 
5 #include <stdlib.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8 
9 #include "Ecore.h"
10 #include "ecore_x_private.h"
11 #include "Ecore_X.h"
12 #include "Ecore_X_Atoms.h"
13 
14 static int ignore_num = 0;
15 static Ecore_X_Window *ignore_list = NULL;
16 
17 /**
18  * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions
19  * @ingroup Ecore_X_Group
20  *
21  * Functions that can be used to create an X window.
22  */
23 
24 EAPI Ecore_X_Window
ecore_x_window_full_new(Ecore_X_Window parent,int x,int y,int w,int h,Ecore_X_Visual * visual,Ecore_X_Colormap colormap,int depth,Eina_Bool override)25 ecore_x_window_full_new(Ecore_X_Window parent,
26                         int x,
27                         int y,
28                         int w,
29                         int h,
30                         Ecore_X_Visual *visual,
31                         Ecore_X_Colormap colormap,
32                         int depth,
33                         Eina_Bool override)
34 {
35    Window win;
36    XSetWindowAttributes attr;
37 
38    LOGFN;
39    if (parent == 0)
40      parent = DefaultRootWindow(_ecore_x_disp);
41 
42    attr.backing_store = NotUseful;
43    attr.override_redirect = override;
44    attr.border_pixel = 0;
45    attr.background_pixmap = None;
46    attr.bit_gravity = NorthWestGravity;
47    attr.win_gravity = NorthWestGravity;
48    attr.save_under = False;
49    attr.do_not_propagate_mask = NoEventMask;
50    attr.colormap = (Colormap)colormap;
51    attr.event_mask = KeyPressMask |
52      KeyReleaseMask |
53      ButtonPressMask |
54      ButtonReleaseMask |
55      EnterWindowMask |
56      LeaveWindowMask |
57      PointerMotionMask |
58      ExposureMask |
59      VisibilityChangeMask |
60      StructureNotifyMask |
61      FocusChangeMask |
62      PropertyChangeMask |
63      ColormapChangeMask;
64    win = XCreateWindow(_ecore_x_disp, parent,
65                        x, y, w, h, 0,
66                        depth,
67                        InputOutput,
68                        (Visual *)visual,
69                        CWBackingStore |
70                        CWOverrideRedirect |
71                        (colormap ? CWColormap : 0) |
72                        CWBorderPixel |
73                        CWBackPixmap |
74                        CWSaveUnder |
75                        CWDontPropagate |
76                        CWEventMask |
77                        CWBitGravity |
78                        CWWinGravity,
79                        &attr);
80    if (_ecore_xlib_sync) ecore_x_sync();
81    if (parent == DefaultRootWindow(_ecore_x_disp))
82      ecore_x_window_defaults_set(win);
83 
84    return win;
85 }
86 
87 /**
88  * Creates a new window.
89  * @param   parent The parent window to use.  If @p parent is @c 0, the root
90  *                 window of the default display is used.
91  * @param   x      X position.
92  * @param   y      Y position.
93  * @param   w      Width.
94  * @param   h      Height.
95  * @return  The new window handle.
96  * @ingroup Ecore_X_Window_Create_Group
97  */
98 EAPI Ecore_X_Window
ecore_x_window_new(Ecore_X_Window parent,int x,int y,int w,int h)99 ecore_x_window_new(Ecore_X_Window parent,
100                    int x,
101                    int y,
102                    int w,
103                    int h)
104 {
105    Window win;
106    XSetWindowAttributes attr;
107 
108    LOGFN;
109    if (parent == 0)
110      parent = DefaultRootWindow(_ecore_x_disp);
111 
112    attr.backing_store = NotUseful;
113    attr.override_redirect = False;
114    attr.border_pixel = 0;
115    attr.background_pixmap = None;
116    attr.bit_gravity = NorthWestGravity;
117    attr.win_gravity = NorthWestGravity;
118    attr.save_under = False;
119    attr.do_not_propagate_mask = NoEventMask;
120    attr.event_mask = KeyPressMask |
121      KeyReleaseMask |
122      ButtonPressMask |
123      ButtonReleaseMask |
124      EnterWindowMask |
125      LeaveWindowMask |
126      PointerMotionMask |
127      ExposureMask |
128      VisibilityChangeMask |
129      StructureNotifyMask |
130      FocusChangeMask |
131      PropertyChangeMask |
132      ColormapChangeMask;
133    win = XCreateWindow(_ecore_x_disp, parent,
134                        x, y, w, h, 0,
135                        CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
136                        InputOutput,
137                        CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
138                        CWBackingStore |
139                        CWOverrideRedirect |
140 /*		       CWColormap | */
141                        CWBorderPixel |
142                        CWBackPixmap |
143                        CWSaveUnder |
144                        CWDontPropagate |
145                        CWEventMask |
146                        CWBitGravity |
147                        CWWinGravity,
148                        &attr);
149    if (_ecore_xlib_sync) ecore_x_sync();
150    if (parent == DefaultRootWindow(_ecore_x_disp))
151      ecore_x_window_defaults_set(win);
152 
153    return win;
154 }
155 
156 /**
157  * Creates a window with the override redirect attribute set to @c True.
158  * @param   parent The parent window to use.  If @p parent is @c 0, the root
159  *                 window of the default display is used.
160  * @param   x      X position.
161  * @param   y      Y position.
162  * @param   w      Width.
163  * @param   h      Height.
164  * @return  The new window handle.
165  * @ingroup Ecore_X_Window_Create_Group
166  */
167 EAPI Ecore_X_Window
ecore_x_window_override_new(Ecore_X_Window parent,int x,int y,int w,int h)168 ecore_x_window_override_new(Ecore_X_Window parent,
169                             int x,
170                             int y,
171                             int w,
172                             int h)
173 {
174    Window win;
175    XSetWindowAttributes attr;
176 
177    LOGFN;
178    if (parent == 0)
179      parent = DefaultRootWindow(_ecore_x_disp);
180 
181    attr.backing_store = NotUseful;
182    attr.override_redirect = True;
183    attr.border_pixel = 0;
184    attr.background_pixmap = None;
185    attr.bit_gravity = NorthWestGravity;
186    attr.win_gravity = NorthWestGravity;
187    attr.save_under = False;
188    attr.do_not_propagate_mask = NoEventMask;
189    attr.event_mask = KeyPressMask |
190      KeyReleaseMask |
191      ButtonPressMask |
192      ButtonReleaseMask |
193      EnterWindowMask |
194      LeaveWindowMask |
195      PointerMotionMask |
196      ExposureMask |
197      VisibilityChangeMask |
198      StructureNotifyMask |
199      FocusChangeMask |
200      PropertyChangeMask |
201      ColormapChangeMask;
202    win = XCreateWindow(_ecore_x_disp, parent,
203                        x, y, w, h, 0,
204                        CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
205                        InputOutput,
206                        CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
207                        CWBackingStore |
208                        CWOverrideRedirect |
209 /*		       CWColormap | */
210                        CWBorderPixel |
211                        CWBackPixmap |
212                        CWSaveUnder |
213                        CWDontPropagate |
214                        CWEventMask |
215                        CWBitGravity |
216                        CWWinGravity,
217                        &attr);
218    if (_ecore_xlib_sync) ecore_x_sync();
219    return win;
220 }
221 
222 /**
223  * Creates a new input window.
224  * @param   parent The parent window to use.    If @p parent is @c 0, the root
225  *                 window of the default display is used.
226  * @param   x      X position.
227  * @param   y      Y position.
228  * @param   w      Width.
229  * @param   h      Height.
230  * @return  The new window.
231  * @ingroup Ecore_X_Window_Create_Group
232  */
233 EAPI Ecore_X_Window
ecore_x_window_input_new(Ecore_X_Window parent,int x,int y,int w,int h)234 ecore_x_window_input_new(Ecore_X_Window parent,
235                          int x,
236                          int y,
237                          int w,
238                          int h)
239 {
240    Window win;
241    XSetWindowAttributes attr;
242 
243    LOGFN;
244    if (parent == 0)
245      parent = DefaultRootWindow(_ecore_x_disp);
246 
247    attr.override_redirect = True;
248    attr.do_not_propagate_mask = NoEventMask;
249    attr.event_mask = KeyPressMask |
250      KeyReleaseMask |
251      ButtonPressMask |
252      ButtonReleaseMask |
253      EnterWindowMask |
254      LeaveWindowMask |
255      PointerMotionMask |
256      ExposureMask |
257      VisibilityChangeMask |
258      StructureNotifyMask |
259      FocusChangeMask |
260      PropertyChangeMask |
261      ColormapChangeMask;
262    win = XCreateWindow(_ecore_x_disp, parent,
263                        x, y, w, h, 0,
264                        CopyFromParent,
265                        InputOnly,
266                        CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
267                        CWOverrideRedirect |
268                        CWDontPropagate |
269                        CWEventMask,
270                        &attr);
271    if (_ecore_xlib_sync) ecore_x_sync();
272    if (parent == DefaultRootWindow(_ecore_x_disp))
273      {
274      }
275 
276    return win;
277 }
278 
279 /**
280  * @defgroup Ecore_X_Window_Properties_Group X Window Property Functions
281  * @ingroup Ecore_X_Group
282  *
283  * Functions that set window properties.
284  */
285 
286 /**
287  * Sets the default properties for the given window.
288  *
289  * The default properties set for the window are @c WM_CLIENT_MACHINE and
290  * @c _NET_WM_PID.
291  *
292  * @param   win The given window.
293  * @ingroup Ecore_X_Window_Properties_Group
294  */
295 EAPI void
ecore_x_window_defaults_set(Ecore_X_Window win)296 ecore_x_window_defaults_set(Ecore_X_Window win)
297 {
298    long pid;
299    char buf[MAXHOSTNAMELEN];
300    char *hostname[1];
301    int argc;
302    char **argv;
303    XTextProperty xprop;
304 
305    LOGFN;
306    /*
307     * Set WM_CLIENT_MACHINE.
308     */
309    gethostname(buf, MAXHOSTNAMELEN);
310    buf[MAXHOSTNAMELEN - 1] = '\0';
311    hostname[0] = buf;
312    /* The ecore function uses UTF8 which Xlib may not like (especially
313     * with older clients) */
314    /* ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE,
315                                   (char *)buf); */
316    if (XStringListToTextProperty(hostname, 1, &xprop))
317      {
318         XSetWMClientMachine(_ecore_x_disp, win, &xprop);
319         XFree(xprop.value);
320         if (_ecore_xlib_sync) ecore_x_sync();
321      }
322    if (_ecore_xlib_sync) ecore_x_sync();
323    /*
324     * Set _NET_WM_PID
325     */
326    pid = getpid();
327    ecore_x_netwm_pid_set(win, pid);
328 
329    ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL);
330 
331    ecore_app_args_get(&argc, &argv);
332    ecore_x_icccm_command_set(win, argc, argv);
333 }
334 
335 EAPI void
ecore_x_window_configure(Ecore_X_Window win,Ecore_X_Window_Configure_Mask mask,int x,int y,int w,int h,int border_width,Ecore_X_Window sibling,int stack_mode)336 ecore_x_window_configure(Ecore_X_Window win,
337                          Ecore_X_Window_Configure_Mask mask,
338                          int x,
339                          int y,
340                          int w,
341                          int h,
342                          int border_width,
343                          Ecore_X_Window sibling,
344                          int stack_mode)
345 {
346    XWindowChanges xwc;
347 
348    if (!win)
349      return;
350 
351    LOGFN;
352 
353    xwc.x = x;
354    xwc.y = y;
355    xwc.width = w;
356    xwc.height = h;
357    xwc.border_width = border_width;
358    xwc.sibling = sibling;
359    xwc.stack_mode = stack_mode;
360 
361    XConfigureWindow(_ecore_x_disp, win, mask, &xwc);
362    if (_ecore_xlib_sync) ecore_x_sync();
363 }
364 
365 /**
366  * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions
367  * @ingroup Ecore_X_Group
368  *
369  * Functions to destroy X windows.
370  */
371 
372 /**
373  * Deletes the given window.
374  * @param   win The given window.
375  * @ingroup Ecore_X_Window_Destroy_Group
376  */
377 EAPI void
ecore_x_window_free(Ecore_X_Window win)378 ecore_x_window_free(Ecore_X_Window win)
379 {
380    /* sorry sir, deleting the root window doesn't sound like
381     * a smart idea.
382     */
383    LOGFN;
384    if (!win) return;
385    XDestroyWindow(_ecore_x_disp, win);
386    if (_ecore_xlib_sync) ecore_x_sync();
387 }
388 
389 /**
390  * Set if a window should be ignored.
391  * @param   win The given window.
392  * @param   ignore if to ignore
393  */
394 EAPI void
ecore_x_window_ignore_set(Ecore_X_Window win,int ignore)395 ecore_x_window_ignore_set(Ecore_X_Window win,
396                           int ignore)
397 {
398    int i, j, cnt;
399    Ecore_X_Window *t;
400 
401    LOGFN;
402    if (ignore)
403      {
404         if (ignore_list)
405           {
406              for (i = 0; i < ignore_num; i++)
407                {
408                   if (win == ignore_list[i])
409                     return;
410                }
411              t = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window));
412              if (!t) return;
413              ignore_list = t;
414              ignore_list[ignore_num++] = win;
415           }
416         else
417           {
418              ignore_num = 0;
419              ignore_list = malloc(sizeof(Ecore_X_Window));
420              if (ignore_list)
421                ignore_list[ignore_num++] = win;
422           }
423      }
424    else
425      {
426         if (!ignore_list)
427           return;
428 
429         for (cnt = ignore_num, i = 0, j = 0; i < cnt; i++)
430           {
431              if (win != ignore_list[i])
432                ignore_list[j++] = ignore_list[i];
433              else
434                ignore_num--;
435           }
436 
437         if (ignore_num <= 0)
438           {
439              free(ignore_list);
440              ignore_list = NULL;
441              return;
442           }
443         t = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
444         if (t) ignore_list = t;
445      }
446 }
447 
448 /**
449  * Get the ignore list
450  * @param   num number of windows in the list
451  * @return  list of windows to ignore
452  */
453 EAPI Ecore_X_Window *
ecore_x_window_ignore_list(int * num)454 ecore_x_window_ignore_list(int *num)
455 {
456    if (num)
457      *num = ignore_num;
458 
459    return ignore_list;
460 }
461 
462 /**
463  * Sends a delete request to the given window.
464  * @param   win The given window.
465  * @ingroup Ecore_X_Window_Destroy_Group
466  */
467 EAPI void
ecore_x_window_delete_request_send(Ecore_X_Window win)468 ecore_x_window_delete_request_send(Ecore_X_Window win)
469 {
470    XEvent xev = { 0 };
471 
472    /* sorry sir, deleting the root window doesn't sound like
473     * a smart idea.
474     */
475    if (!win)
476      return;
477 
478    LOGFN;
479    xev.xclient.type = ClientMessage;
480    xev.xclient.display = _ecore_x_disp;
481    xev.xclient.window = win;
482    xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
483    xev.xclient.format = 32;
484    xev.xclient.data.l[0] = ECORE_X_ATOM_WM_DELETE_WINDOW;
485    xev.xclient.data.l[1] = CurrentTime;
486 
487    XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
488    if (_ecore_xlib_sync) ecore_x_sync();
489 }
490 
491 /**
492  * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions
493  * @ingroup Ecore_X_Group
494  *
495  * Functions to access and change the visibility of X windows.
496  */
497 
498 /**
499  * Shows a window.
500  *
501  * Synonymous to "mapping" a window in X Window System terminology.
502  *
503  * @param   win The window to show.
504  * @ingroup Ecore_X_Window_Visibility
505  */
506 EAPI void
ecore_x_window_show(Ecore_X_Window win)507 ecore_x_window_show(Ecore_X_Window win)
508 {
509    LOGFN;
510    XMapWindow(_ecore_x_disp, win);
511    if (_ecore_xlib_sync) ecore_x_sync();
512 }
513 
514 /**
515  * Hides a window.
516  *
517  * Synonymous to "unmapping" a window in X Window System terminology.
518  *
519  * @param   win The window to hide.
520  * @ingroup Ecore_X_Window_Visibility
521  */
522 EAPI void
ecore_x_window_hide(Ecore_X_Window win)523 ecore_x_window_hide(Ecore_X_Window win)
524 {
525    XEvent xev = { 0 };
526    Window root;
527    int idum;
528    unsigned int uidum;
529 
530    /* ICCCM: SEND unmap event... */
531    LOGFN;
532    root = win;
533    if (ScreenCount(_ecore_x_disp) == 1)
534      root = DefaultRootWindow(_ecore_x_disp);
535    else
536      XGetGeometry(_ecore_x_disp,
537                   win,
538                   &root,
539                   &idum,
540                   &idum,
541                   &uidum,
542                   &uidum,
543                   &uidum,
544                   &uidum);
545 
546    XUnmapWindow(_ecore_x_disp, win);
547    xev.xunmap.type = UnmapNotify;
548    xev.xunmap.serial = 0;
549    xev.xunmap.send_event = True;
550    xev.xunmap.display = _ecore_x_disp;
551    xev.xunmap.event = root;
552    xev.xunmap.window = win;
553    xev.xunmap.from_configure = False;
554    XSendEvent(_ecore_x_disp, xev.xunmap.event, False,
555               SubstructureRedirectMask | SubstructureNotifyMask, &xev);
556    if (_ecore_xlib_sync) ecore_x_sync();
557 }
558 
559 /**
560  * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions
561  * @ingroup Ecore_X_Group
562  *
563  * Functions that change or retrieve the geometry of X windows.
564  */
565 
566 /**
567  * Moves a window to the position @p x, @p y.
568  *
569  * The position is relative to the upper left hand corner of the
570  * parent window.
571  *
572  * @param   win The window to move.
573  * @param   x   X position.
574  * @param   y   Y position.
575  * @ingroup Ecore_X_Window_Geometry_Group
576  */
577 EAPI void
ecore_x_window_move(Ecore_X_Window win,int x,int y)578 ecore_x_window_move(Ecore_X_Window win,
579                     int x,
580                     int y)
581 {
582    LOGFN;
583    XMoveWindow(_ecore_x_disp, win, x, y);
584    if (_ecore_xlib_sync) ecore_x_sync();
585 }
586 
587 /**
588  * Resizes a window.
589  * @param   win The window to resize.
590  * @param   w   New width of the window.
591  * @param   h   New height of the window.
592  * @ingroup Ecore_X_Window_Geometry_Group
593  */
594 EAPI void
ecore_x_window_resize(Ecore_X_Window win,int w,int h)595 ecore_x_window_resize(Ecore_X_Window win,
596                       int w,
597                       int h)
598 {
599    LOGFN;
600    if (w < 1)
601      w = 1;
602 
603    if (h < 1)
604      h = 1;
605 
606    XResizeWindow(_ecore_x_disp, win, w, h);
607    if (_ecore_xlib_sync) ecore_x_sync();
608 }
609 
610 /**
611  * Moves and resizes a window.
612  * @param   win The window to move and resize.
613  * @param   x   New X position of the window.
614  * @param   y   New Y position of the window.
615  * @param   w   New width of the window.
616  * @param   h   New height of the window.
617  * @ingroup Ecore_X_Window_Geometry_Group
618  */
619 EAPI void
ecore_x_window_move_resize(Ecore_X_Window win,int x,int y,int w,int h)620 ecore_x_window_move_resize(Ecore_X_Window win,
621                            int x,
622                            int y,
623                            int w,
624                            int h)
625 {
626    LOGFN;
627    if (w < 1)
628      w = 1;
629 
630    if (h < 1)
631      h = 1;
632 
633    XMoveResizeWindow(_ecore_x_disp, win, x, y, w, h);
634    if (_ecore_xlib_sync) ecore_x_sync();
635 }
636 
637 /**
638  * @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions
639  * @ingroup Ecore_X_Group
640  *
641  * Functions that give the focus to an X Window.
642  */
643 
644 /**
645  * Sets the focus to the window @p win.
646  * @param   win The window to focus.
647  * @ingroup Ecore_X_Window_Focus_Functions
648  */
649 EAPI void
ecore_x_window_focus(Ecore_X_Window win)650 ecore_x_window_focus(Ecore_X_Window win)
651 {
652    LOGFN;
653    if (win == 0)
654      win = DefaultRootWindow(_ecore_x_disp);  //   XSetInputFocus(_ecore_x_disp, win, RevertToNone, CurrentTime);
655 
656 //   XSetInputFocus(_ecore_x_disp, win, RevertToPointerRoot, CurrentTime);
657    XSetInputFocus(_ecore_x_disp, win, RevertToParent, CurrentTime);
658    if (_ecore_xlib_sync) ecore_x_sync();
659 }
660 
661 /**
662  * Sets the focus to the given window at a specific time.
663  * @param   win The window to focus.
664  * @param   t   When to set the focus to the window.
665  * @ingroup Ecore_X_Window_Focus_Functions
666  */
667 EAPI void
ecore_x_window_focus_at_time(Ecore_X_Window win,Ecore_X_Time t)668 ecore_x_window_focus_at_time(Ecore_X_Window win,
669                              Ecore_X_Time t)
670 {
671    LOGFN;
672    if (win == 0)
673      win = DefaultRootWindow(_ecore_x_disp);  //   XSetInputFocus(_ecore_x_disp, win, RevertToNone, t);
674 
675 //   XSetInputFocus(_ecore_x_disp, win, PointerRoot, t);
676    XSetInputFocus(_ecore_x_disp, win, RevertToParent, t);
677    if (_ecore_xlib_sync) ecore_x_sync();
678 }
679 
680 /**
681  * gets the window that has focus.
682  * @return  The window that has focus.
683  * @ingroup Ecore_X_Window_Focus_Functions
684  */
685 EAPI Ecore_X_Window
ecore_x_window_focus_get(void)686 ecore_x_window_focus_get(void)
687 {
688    Window win;
689    int revert_mode;
690 
691    LOGFN;
692    win = 0;
693    XGetInputFocus(_ecore_x_disp, &win, &revert_mode);
694    return win;
695 }
696 
697 /**
698  * @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions
699  * @ingroup Ecore_X_Group
700  *
701  * Functions that change the Z order of X windows.
702  */
703 
704 /**
705  * Raises the given window.
706  * @param   win The window to raise.
707  * @ingroup Ecore_X_Window_Z_Order_Group
708  */
709 EAPI void
ecore_x_window_raise(Ecore_X_Window win)710 ecore_x_window_raise(Ecore_X_Window win)
711 {
712    LOGFN;
713    XRaiseWindow(_ecore_x_disp, win);
714    if (_ecore_xlib_sync) ecore_x_sync();
715 }
716 
717 /**
718  * Lowers the given window.
719  * @param   win The window to lower.
720  * @ingroup Ecore_X_Window_Z_Order_Group
721  */
722 EAPI void
ecore_x_window_lower(Ecore_X_Window win)723 ecore_x_window_lower(Ecore_X_Window win)
724 {
725    LOGFN;
726    XLowerWindow(_ecore_x_disp, win);
727    if (_ecore_xlib_sync) ecore_x_sync();
728 }
729 
730 /**
731  * @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions
732  * @ingroup Ecore_X_Group
733  *
734  * Functions that retrieve or changes the parent window of a window.
735  */
736 
737 /**
738  * Moves a window to within another window at a given position.
739  * @param   win        The window to reparent.
740  * @param   new_parent The new parent window.
741  * @param   x          X position within new parent window.
742  * @param   y          Y position within new parent window.
743  * @ingroup Ecore_X_Window_Parent_Group
744  */
745 EAPI void
ecore_x_window_reparent(Ecore_X_Window win,Ecore_X_Window new_parent,int x,int y)746 ecore_x_window_reparent(Ecore_X_Window win,
747                         Ecore_X_Window new_parent,
748                         int x,
749                         int y)
750 {
751    LOGFN;
752    if (new_parent == 0)
753      new_parent = DefaultRootWindow(_ecore_x_disp);
754 
755    XReparentWindow(_ecore_x_disp, win, new_parent, x, y);
756    if (_ecore_xlib_sync) ecore_x_sync();
757 }
758 
759 /**
760  * Retrieves the size of the given window.
761  * @param   win The given window.
762  * @param   w   Pointer to an integer into which the width is to be stored.
763  * @param   h   Pointer to an integer into which the height is to be stored.
764  * @ingroup Ecore_X_Window_Geometry_Group
765  */
766 EAPI void
ecore_x_window_size_get(Ecore_X_Window win,int * w,int * h)767 ecore_x_window_size_get(Ecore_X_Window win,
768                         int *w,
769                         int *h)
770 {
771    int dummy_x, dummy_y;
772 
773    LOGFN;
774    if (win == 0)
775      win = DefaultRootWindow(_ecore_x_disp);
776 
777    ecore_x_drawable_geometry_get(win, &dummy_x, &dummy_y, w, h);
778    if (_ecore_xlib_sync) ecore_x_sync();
779 }
780 
781 /**
782  * Retrieves the geometry of the given window.
783  *
784  * Note that the x & y coordinates are relative to your parent.  In
785  * particular for reparenting window managers - relative to you window border.
786  * If you want screen coordinates either walk the window tree to the root,
787  * else for ecore_evas applications see ecore_evas_geometry_get().  Elementary
788  * applications can use elm_win_screen_position_get().
789  *
790  * @param   win The given window.
791  * @param   x   Pointer to an integer in which the X position is to be stored.
792  * @param   y   Pointer to an integer in which the Y position is to be stored.
793  * @param   w   Pointer to an integer in which the width is to be stored.
794  * @param   h   Pointer to an integer in which the height is to be stored.
795  * @ingroup Ecore_X_Window_Geometry_Group
796  */
797 EAPI void
ecore_x_window_geometry_get(Ecore_X_Window win,int * x,int * y,int * w,int * h)798 ecore_x_window_geometry_get(Ecore_X_Window win,
799                             int *x,
800                             int *y,
801                             int *w,
802                             int *h)
803 {
804    LOGFN;
805    if (!win)
806      win = DefaultRootWindow(_ecore_x_disp);
807 
808    ecore_x_drawable_geometry_get(win, x, y, w, h);
809    if (_ecore_xlib_sync) ecore_x_sync();
810 }
811 
812 /**
813  * Retrieves the width of the border of the given window.
814  * @param   win The given window.
815  * @return  Width of the border of @p win.
816  * @ingroup Ecore_X_Window_Geometry_Group
817  */
818 EAPI int
ecore_x_window_border_width_get(Ecore_X_Window win)819 ecore_x_window_border_width_get(Ecore_X_Window win)
820 {
821    int w;
822    LOGFN;
823    /* doesn't make sense to call this on a root window */
824    if (!win)
825      return 0;
826 
827    w = ecore_x_drawable_border_width_get(win);
828    if (_ecore_xlib_sync) ecore_x_sync();
829    return w;
830 }
831 
832 /**
833  * Sets the width of the border of the given window.
834  * @param   win The given window.
835  * @param   width The new border width.
836  * @ingroup Ecore_X_Window_Geometry_Group
837  */
838 EAPI void
ecore_x_window_border_width_set(Ecore_X_Window win,int width)839 ecore_x_window_border_width_set(Ecore_X_Window win,
840                                 int width)
841 {
842    LOGFN;
843    /* doesn't make sense to call this on a root window */
844    if (!win)
845      return;
846 
847    XSetWindowBorderWidth (_ecore_x_disp, win, width);
848    if (_ecore_xlib_sync) ecore_x_sync();
849 }
850 
851 /**
852  * Retrieves the depth of the given window.
853  * @param  win The given window.
854  * @return Depth of the window.
855  */
856 EAPI int
ecore_x_window_depth_get(Ecore_X_Window win)857 ecore_x_window_depth_get(Ecore_X_Window win)
858 {
859    int d;
860    LOGFN;
861    d = ecore_x_drawable_depth_get(win);
862    if (_ecore_xlib_sync) ecore_x_sync();
863    return d;
864 }
865 
866 /**
867  * @brief Show the cursor on a window of type Ecore_X_Window.
868  * @param win The window for which the cursor will be showed.
869  * @param show Enables the show of the cursor on the window if equals EINA_TRUE, disables if equals EINA_FALSE.
870  */
871 EAPI void
ecore_x_window_cursor_show(Ecore_X_Window win,Eina_Bool show)872 ecore_x_window_cursor_show(Ecore_X_Window win,
873                            Eina_Bool show)
874 {
875    LOGFN;
876    if (win == 0)
877      win = DefaultRootWindow(_ecore_x_disp);
878 
879    if (!show)
880      {
881         Cursor c;
882         XColor cl;
883         Pixmap p, m;
884         GC gc;
885         XGCValues gcv;
886 
887         p = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
888         if (_ecore_xlib_sync) ecore_x_sync();
889         m = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
890         if (_ecore_xlib_sync) ecore_x_sync();
891         gc = XCreateGC(_ecore_x_disp, m, 0, &gcv);
892         if (_ecore_xlib_sync) ecore_x_sync();
893         XSetForeground(_ecore_x_disp, gc, 0);
894         if (_ecore_xlib_sync) ecore_x_sync();
895         XDrawPoint(_ecore_x_disp, m, gc, 0, 0);
896         if (_ecore_xlib_sync) ecore_x_sync();
897         XFreeGC(_ecore_x_disp, gc);
898         c = XCreatePixmapCursor(_ecore_x_disp, p, m, &cl, &cl, 0, 0);
899         if (_ecore_xlib_sync) ecore_x_sync();
900         XDefineCursor(_ecore_x_disp, win, c);
901         XFreeCursor(_ecore_x_disp, c);
902         XFreePixmap(_ecore_x_disp, p);
903         XFreePixmap(_ecore_x_disp, m);
904 }
905    else
906      XDefineCursor(_ecore_x_disp, win, 0);
907    if (_ecore_xlib_sync) ecore_x_sync();
908 }
909 
910 EAPI void
ecore_x_window_cursor_set(Ecore_X_Window win,Ecore_X_Cursor c)911 ecore_x_window_cursor_set(Ecore_X_Window win,
912                           Ecore_X_Cursor c)
913 {
914 #ifdef ECORE_XI2
915    int devid;
916 #endif
917 
918    LOGFN;
919 #ifdef ECORE_XI2
920    XIGetClientPointer(_ecore_x_disp, None, &devid);
921    if (c == 0)
922      XIUndefineCursor(_ecore_x_disp, devid, win);
923    else
924      XIDefineCursor(_ecore_x_disp, devid, win, c);
925 #else
926    if (c == 0)
927      XUndefineCursor(_ecore_x_disp, win);
928    else
929      XDefineCursor(_ecore_x_disp, win, c);
930 #endif
931    if (_ecore_xlib_sync) ecore_x_sync();
932 }
933 
934 /**
935  * Finds out whether the given window is currently visible.
936  * @param   win The given window.
937  * @return  1 if the window is visible, otherwise 0.
938  * @ingroup Ecore_X_Window_Visibility_Group
939  */
940 EAPI int
ecore_x_window_visible_get(Ecore_X_Window win)941 ecore_x_window_visible_get(Ecore_X_Window win)
942 {
943    Eina_Bool ret;
944    XWindowAttributes attr;
945 
946    LOGFN;
947    ret = (XGetWindowAttributes(_ecore_x_disp, win, &attr) &&
948           (attr.map_state == IsViewable));
949    if (_ecore_xlib_sync) ecore_x_sync();
950    return ret;
951 }
952 
953 typedef struct _Shadow Shadow;
954 struct _Shadow
955 {
956    Shadow        *parent;
957    Shadow       **children;
958    Window         win;
959    int            children_num;
960    short          x, y;
961    unsigned short w, h;
962 };
963 
964 static Shadow **shadow_base = NULL;
965 static int shadow_num = 0;
966 
967 static Shadow *
_ecore_x_window_tree_walk(Window win)968 _ecore_x_window_tree_walk(Window win)
969 {
970    Window *list = NULL;
971    Window parent_win = 0, root_win = 0;
972    unsigned int num;
973    Shadow *s, **sl;
974    XWindowAttributes att;
975    Eina_Bool ret;
976 
977    ret = (XGetWindowAttributes(_ecore_x_disp, win, &att) && (att.map_state == IsViewable));
978    if (_ecore_xlib_sync) ecore_x_sync();
979    if (!ret) return NULL; //   if (att.class == InputOnly) return NULL;
980 
981    s = calloc(1, sizeof(Shadow));
982    if (!s)
983      return NULL;
984 
985    s->win = win;
986    s->x = att.x;
987    s->y = att.y;
988    s->w = att.width;
989    s->h = att.height;
990    if (XQueryTree(_ecore_x_disp, s->win, &root_win, &parent_win,
991                   &list, &num))
992      {
993         if (_ecore_xlib_sync) ecore_x_sync();
994         s->children = calloc(1, sizeof(Shadow *) * num);
995         if (s->children)
996           {
997              size_t i, j;
998              s->children_num = num;
999              for (i = 0; i < num; i++)
1000                {
1001                   s->children[i] = _ecore_x_window_tree_walk(list[i]);
1002                   if (s->children[i])
1003                     s->children[i]->parent = s;
1004                }
1005              /* compress list down */
1006              j = 0;
1007              for (i = 0; i < num; i++)
1008                {
1009                   if (s->children[i])
1010                     {
1011                        s->children[j] = s->children[i];
1012                        j++;
1013                     }
1014                }
1015              if (j == 0)
1016                {
1017                   free(s->children);
1018                   s->children = NULL;
1019                   s->children_num = 0;
1020                }
1021              else
1022                {
1023                   s->children_num = j;
1024                   sl = realloc(s->children, sizeof(Shadow *) * j);
1025                   if (sl)
1026                     s->children = sl;
1027                }
1028           }
1029      }
1030 
1031    if (list)
1032      XFree(list);
1033 
1034    return s;
1035 }
1036 
1037 static void
_ecore_x_window_tree_shadow_free1(Shadow * s)1038 _ecore_x_window_tree_shadow_free1(Shadow *s)
1039 {
1040    int i;
1041 
1042    if (!s)
1043      return;
1044 
1045    if (s->children)
1046      {
1047         for (i = 0; i < s->children_num; i++)
1048           {
1049              if (s->children[i])
1050                _ecore_x_window_tree_shadow_free1(s->children[i]);
1051           }
1052         free(s->children);
1053      }
1054 
1055    free(s);
1056 }
1057 
1058 static void
_ecore_x_window_tree_shadow_free(void)1059 _ecore_x_window_tree_shadow_free(void)
1060 {
1061    int i;
1062 
1063    if (!shadow_base)
1064      return;
1065 
1066    for (i = 0; i < shadow_num; i++)
1067      {
1068         if (!shadow_base[i])
1069           continue;
1070 
1071         _ecore_x_window_tree_shadow_free1(shadow_base[i]);
1072      }
1073    free(shadow_base);
1074    shadow_base = NULL;
1075    shadow_num = 0;
1076 }
1077 
1078 static void
_ecore_x_window_tree_shadow_populate(void)1079 _ecore_x_window_tree_shadow_populate(void)
1080 {
1081    Ecore_X_Window *roots;
1082    int i, num;
1083 
1084    roots = ecore_x_window_root_list(&num);
1085    if (roots)
1086      {
1087         shadow_base = calloc(1, sizeof(Shadow *) * num);
1088         if (shadow_base)
1089           {
1090              shadow_num = num;
1091              for (i = 0; i < num; i++)
1092                shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
1093           }
1094 
1095         free(roots);
1096      }
1097 }
1098 
1099 /*
1100    static int shadow_count = 0;
1101 
1102    static void
1103    _ecore_x_window_tree_shadow_start(void)
1104    {
1105    shadow_count++;
1106    if (shadow_count > 1) return;
1107    _ecore_x_window_tree_shadow_populate();
1108    }
1109 
1110    static void
1111    _ecore_x_window_tree_shadow_stop(void)
1112    {
1113    shadow_count--;
1114    if (shadow_count != 0) return;
1115    _ecore_x_window_tree_shadow_free();
1116    }
1117  */
1118 
1119 static Shadow *
_ecore_x_window_shadow_tree_find_shadow(Shadow * s,Window win)1120 _ecore_x_window_shadow_tree_find_shadow(Shadow *s,
1121                                         Window win)
1122 {
1123    Shadow *ss;
1124    int i;
1125 
1126    if (s->win == win)
1127      return s;
1128 
1129    if (s->children)
1130      for (i = 0; i < s->children_num; i++)
1131        {
1132           if (!s->children[i])
1133             continue;
1134 
1135           if ((ss =
1136                  _ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
1137             return ss;
1138        }
1139 
1140    return NULL;
1141 }
1142 
1143 static Shadow *
_ecore_x_window_shadow_tree_find(Window base)1144 _ecore_x_window_shadow_tree_find(Window base)
1145 {
1146    Shadow *s;
1147    int i;
1148 
1149    for (i = 0; i < shadow_num; i++)
1150      {
1151         if (!shadow_base[i])
1152           continue;
1153 
1154         if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
1155           return s;
1156      }
1157    return NULL;
1158 }
1159 
1160 static int
_inside_rects(Shadow * s,int x,int y,int bx,int by,Ecore_X_Rectangle * rects,int num)1161 _inside_rects(Shadow *s,
1162               int x,
1163               int y,
1164               int bx,
1165               int by,
1166               Ecore_X_Rectangle *rects,
1167               int num)
1168 {
1169    int i, inside;
1170 
1171    if (!rects) return 0;
1172    inside = 0;
1173    for (i = 0; i < num; i++)
1174      {
1175         if ((x >= s->x + bx + rects[i].x) &&
1176             (y >= s->y + by + rects[i].y) &&
1177             (x < (int)(s->x + bx + rects[i].x + rects[i].width)) &&
1178             (y < (int)(s->y + by + rects[i].y + rects[i].height)))
1179           {
1180              inside = 1;
1181              break;
1182           }
1183      }
1184    free(rects);
1185    return inside;
1186 }
1187 
1188 static Window
_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow * s,int bx,int by,int x,int y,Ecore_X_Window * skip,int skip_num)1189 _ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s,
1190                                              int bx,
1191                                              int by,
1192                                              int x,
1193                                              int y,
1194                                              Ecore_X_Window *skip,
1195                                              int skip_num)
1196 {
1197    Window child;
1198    int i, j;
1199    int wx, wy;
1200 
1201    wx = s->x + bx;
1202    wy = s->y + by;
1203    if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
1204      return 0;
1205 
1206    /* FIXME: get shape */
1207    {
1208       int num;
1209       Ecore_X_Rectangle *rects;
1210 
1211       num = 0;
1212       rects = ecore_x_window_shape_rectangles_get(s->win, &num);
1213       if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0;
1214       num = 0;
1215       rects = ecore_x_window_shape_input_rectangles_get(s->win, &num);
1216       if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0;
1217    }
1218 
1219    if (s->children)
1220      {
1221         int skipit = 0;
1222 
1223         for (i = s->children_num - 1; i >= 0; --i)
1224           {
1225              if (!s->children[i])
1226                continue;
1227 
1228              skipit = 0;
1229              if (skip)
1230                for (j = 0; j < skip_num; j++)
1231                  {
1232                     if (s->children[i]->win == skip[j])
1233                       {
1234                          skipit = 1;
1235                          goto onward;
1236                       }
1237                  }
1238 
1239 onward:
1240              if (!skipit)
1241                if ((child =
1242                       _ecore_x_window_shadow_tree_at_xy_get_shadow(s->
1243                                                                    children[i
1244                                                                    ], wx, wy,
1245                                                                    x, y, skip,
1246                                                                    skip_num)))
1247                  return child;
1248           }
1249      }
1250 
1251    return s->win;
1252 }
1253 
1254 static Window
_ecore_x_window_shadow_tree_at_xy_get(Window base,int bx,int by,int x,int y,Ecore_X_Window * skip,int skip_num)1255 _ecore_x_window_shadow_tree_at_xy_get(Window base,
1256                                       int bx,
1257                                       int by,
1258                                       int x,
1259                                       int y,
1260                                       Ecore_X_Window *skip,
1261                                       int skip_num)
1262 {
1263    Shadow *s;
1264 
1265    if (!shadow_base)
1266      {
1267         _ecore_x_window_tree_shadow_populate();
1268         if (!shadow_base)
1269           return 0;
1270      }
1271 
1272    s = _ecore_x_window_shadow_tree_find(base);
1273    if (!s)
1274      return 0;
1275 
1276    return _ecore_x_window_shadow_tree_at_xy_get_shadow(s,
1277                                                        bx,
1278                                                        by,
1279                                                        x,
1280                                                        y,
1281                                                        skip,
1282                                                        skip_num);
1283 }
1284 
1285 /**
1286  * Retrieves the top, visible window at the given location,
1287  * but skips the windows in the list. This uses a shadow tree built from the
1288  * window tree that is only updated the first time
1289  * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
1290  * it is called after a  ecore_x_window_shadow_tree_flush()
1291  * @param   base The base window to start searching from (normally root).
1292  * @param   x The given X position.
1293  * @param   y The given Y position.
1294  * @param   skip The list of windows to be skipped.
1295  * @param   skip_num The number of windows to be skipped.
1296  * @return  The window at that position.
1297  * @ingroup Ecore_X_Window_Geometry_Group
1298  */
1299 EAPI Ecore_X_Window
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)1300 ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base,
1301                                                int x,
1302                                                int y,
1303                                                Ecore_X_Window *skip,
1304                                                int skip_num)
1305 {
1306    LOGFN;
1307    return _ecore_x_window_shadow_tree_at_xy_get(base,
1308                                                 0,
1309                                                 0,
1310                                                 x,
1311                                                 y,
1312                                                 skip,
1313                                                 skip_num);
1314 }
1315 
1316 /**
1317  * Retrieves the parent window a given window has. This uses the shadow window
1318  * tree.
1319  * @param   root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
1320  * @param   win The window to get the parent window of
1321  * @return  The parent window of @p win
1322  * @ingroup Ecore_X_Window_Geometry_Group
1323  */
1324 EAPI Ecore_X_Window
ecore_x_window_shadow_parent_get(Ecore_X_Window root EINA_UNUSED,Ecore_X_Window win)1325 ecore_x_window_shadow_parent_get(Ecore_X_Window root EINA_UNUSED,
1326                                  Ecore_X_Window win)
1327 {
1328    Shadow *s;
1329    int i;
1330 
1331    LOGFN;
1332    if (!shadow_base)
1333      {
1334         _ecore_x_window_tree_shadow_populate();
1335         if (!shadow_base)
1336           return 0;
1337      }
1338 
1339    for (i = 0; i < shadow_num; i++)
1340      {
1341         if (!shadow_base[i])
1342           continue;
1343 
1344         s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
1345         if (s)
1346           {
1347              if (!s->parent)
1348                return 0;
1349 
1350              return s->parent->win;
1351           }
1352      }
1353    return 0;
1354 }
1355 
1356 /**
1357  * Flushes the window shadow tree so nothing is stored.
1358  * @ingroup Ecore_X_Window_Geometry_Group
1359  */
1360 EAPI void
ecore_x_window_shadow_tree_flush(void)1361 ecore_x_window_shadow_tree_flush(void)
1362 {
1363    LOGFN;
1364    _ecore_x_window_tree_shadow_free();
1365 }
1366 
1367 /**
1368  * Retrieves the root window a given window is on.
1369  * @param   win The window to get the root window of
1370  * @return  The root window of @p win
1371  * @ingroup Ecore_X_Window_Geometry_Group
1372  */
1373 EAPI Ecore_X_Window
ecore_x_window_root_get(Ecore_X_Window win)1374 ecore_x_window_root_get(Ecore_X_Window win)
1375 {
1376    XWindowAttributes att;
1377 
1378    LOGFN;
1379    if (!XGetWindowAttributes(_ecore_x_disp, win, &att))
1380      return 0;
1381 
1382    return att.root;
1383 }
1384 
1385 static Window
_ecore_x_window_at_xy_get(Window base,int bx,int by,int x,int y,Ecore_X_Window * skip,int skip_num)1386 _ecore_x_window_at_xy_get(Window base,
1387                           int bx,
1388                           int by,
1389                           int x,
1390                           int y,
1391                           Ecore_X_Window *skip,
1392                           int skip_num)
1393 {
1394    Window *list = NULL;
1395    Window parent_win = 0, child = 0, root_win = 0;
1396    int i, j, wx, wy, ww, wh;
1397    unsigned int num;
1398 
1399    LOGFN;
1400    if (!ecore_x_window_visible_get(base))
1401      return 0;
1402 
1403    LOGFN;
1404    ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh);
1405    wx += bx;
1406    wy += by;
1407 
1408    if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh))))
1409      return 0;
1410 
1411    LOGFN;
1412    if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num))
1413      return base;
1414 
1415    if (list)
1416      {
1417         int skipit = 0;
1418 
1419         for (i = num - 1; i >= 0; --i)
1420           {
1421              skipit = 0;
1422 
1423              if (skip)
1424                for (j = 0; j < skip_num; j++)
1425                  {
1426                     if (list[i] == skip[j])
1427                       {
1428                          skipit = 1;
1429                          goto onward;
1430                       }
1431                  }
1432 
1433 onward:
1434              if (!skipit)
1435                if ((child =
1436                       _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip,
1437                                                 skip_num)))
1438                  {
1439                     XFree(list);
1440                     return child;
1441                  }
1442           }
1443         XFree(list);
1444      }
1445 
1446    return base;
1447 }
1448 
1449 /**
1450  * Retrieves the top, visible window at the given location.
1451  * @param   x The given X position.
1452  * @param   y The given Y position.
1453  * @return  The window at that position.
1454  * @ingroup Ecore_X_Window_Geometry_Group
1455  */
1456 EAPI Ecore_X_Window
ecore_x_window_at_xy_get(int x,int y)1457 ecore_x_window_at_xy_get(int x,
1458                          int y)
1459 {
1460    Ecore_X_Window win, root;
1461 
1462    LOGFN;
1463    /* FIXME: Proper function to determine current root/virtual root
1464     * window missing here */
1465    root = DefaultRootWindow(_ecore_x_disp);
1466 
1467    ecore_x_grab();
1468    win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
1469    ecore_x_ungrab();
1470 
1471    return win ? win : root;
1472 }
1473 
1474 /**
1475  * Retrieves the top, visible window at the given location,
1476  * but skips the windows in the list.
1477  * @param   x The given X position.
1478  * @param   y The given Y position.
1479  * @param   skip The list of windows to be skipped.
1480  * @param   skip_num The number of windows to be skipped.
1481  * @return  The window at that position.
1482  * @ingroup Ecore_X_Window_Geometry_Group
1483  */
1484 EAPI Ecore_X_Window
ecore_x_window_at_xy_with_skip_get(int x,int y,Ecore_X_Window * skip,int skip_num)1485 ecore_x_window_at_xy_with_skip_get(int x,
1486                                    int y,
1487                                    Ecore_X_Window *skip,
1488                                    int skip_num)
1489 {
1490    Ecore_X_Window win, root;
1491 
1492    LOGFN;
1493    /* FIXME: Proper function to determine current root/virtual root
1494     * window missing here */
1495    root = DefaultRootWindow(_ecore_x_disp);
1496 
1497    ecore_x_grab();
1498    win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
1499    ecore_x_ungrab();
1500 
1501    return win ? win : root;
1502 }
1503 
1504 EAPI Ecore_X_Window
ecore_x_window_at_xy_begin_get(Ecore_X_Window begin,int x,int y)1505 ecore_x_window_at_xy_begin_get(Ecore_X_Window begin,
1506                                int x,
1507                                int y)
1508 {
1509    Ecore_X_Window win;
1510 
1511    LOGFN;
1512    ecore_x_grab();
1513    win = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0);
1514    ecore_x_ungrab();
1515 
1516    return win ? win : begin;
1517 }
1518 
1519 /**
1520  * Retrieves the parent window of the given window.
1521  * @param   win The given window.
1522  * @return  The parent window of @p win.
1523  * @ingroup Ecore_X_Window_Parent_Group
1524  */
1525 EAPI Ecore_X_Window
ecore_x_window_parent_get(Ecore_X_Window win)1526 ecore_x_window_parent_get(Ecore_X_Window win)
1527 {
1528    Window root, parent, *children = NULL;
1529    unsigned int num;
1530    Eina_Bool success;
1531 
1532    LOGFN;
1533    success = XQueryTree(_ecore_x_disp, win, &root, &parent, &children, &num);
1534    if (_ecore_xlib_sync) ecore_x_sync();
1535    if (!success) return 0;
1536 
1537    if (children)
1538      XFree(children);
1539 
1540    return parent;
1541 }
1542 
1543 /**
1544  * Sets the background color of the given window.
1545  * @param win   The given window
1546  * @param r     red value (0...65536, 16 bits)
1547  * @param g     green value (0...65536, 16 bits)
1548  * @param b     blue value (0...65536, 16 bits)
1549  */
1550 EAPI void
ecore_x_window_background_color_set(Ecore_X_Window win,unsigned short r,unsigned short g,unsigned short b)1551 ecore_x_window_background_color_set(Ecore_X_Window win,
1552                                     unsigned short r,
1553                                     unsigned short g,
1554                                     unsigned short b)
1555 {
1556    XSetWindowAttributes attr;
1557    Colormap map;
1558    XColor col;
1559 
1560    LOGFN;
1561    col.red = r;
1562    col.green = g;
1563    col.blue = b;
1564 
1565    map = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp));
1566    XAllocColor(_ecore_x_disp, map, &col);
1567 
1568    attr.background_pixel = col.pixel;
1569    XChangeWindowAttributes(_ecore_x_disp, win, CWBackPixel, &attr);
1570    if (_ecore_xlib_sync) ecore_x_sync();
1571 }
1572 
1573 EAPI void
ecore_x_window_gravity_set(Ecore_X_Window win,Ecore_X_Gravity grav)1574 ecore_x_window_gravity_set(Ecore_X_Window win,
1575                            Ecore_X_Gravity grav)
1576 {
1577    XSetWindowAttributes att;
1578 
1579    LOGFN;
1580    att.win_gravity = grav;
1581    XChangeWindowAttributes(_ecore_x_disp, win, CWWinGravity, &att);
1582    if (_ecore_xlib_sync) ecore_x_sync();
1583 }
1584 
1585 EAPI void
ecore_x_window_pixel_gravity_set(Ecore_X_Window win,Ecore_X_Gravity grav)1586 ecore_x_window_pixel_gravity_set(Ecore_X_Window win,
1587                                  Ecore_X_Gravity grav)
1588 {
1589    XSetWindowAttributes att;
1590 
1591    LOGFN;
1592    att.bit_gravity = grav;
1593    XChangeWindowAttributes(_ecore_x_disp, win, CWBitGravity, &att);
1594    if (_ecore_xlib_sync) ecore_x_sync();
1595 }
1596 
1597 EAPI void
ecore_x_window_pixmap_set(Ecore_X_Window win,Ecore_X_Pixmap pmap)1598 ecore_x_window_pixmap_set(Ecore_X_Window win,
1599                           Ecore_X_Pixmap pmap)
1600 {
1601    LOGFN;
1602    XSetWindowBackgroundPixmap(_ecore_x_disp, win, pmap);
1603    if (_ecore_xlib_sync) ecore_x_sync();
1604 }
1605 
1606 EAPI void
ecore_x_window_area_clear(Ecore_X_Window win,int x,int y,int w,int h)1607 ecore_x_window_area_clear(Ecore_X_Window win,
1608                           int x,
1609                           int y,
1610                           int w,
1611                           int h)
1612 {
1613    LOGFN;
1614    XClearArea(_ecore_x_disp, win, x, y, w, h, False);
1615    if (_ecore_xlib_sync) ecore_x_sync();
1616 }
1617 
1618 EAPI void
ecore_x_window_area_expose(Ecore_X_Window win,int x,int y,int w,int h)1619 ecore_x_window_area_expose(Ecore_X_Window win,
1620                            int x,
1621                            int y,
1622                            int w,
1623                            int h)
1624 {
1625    LOGFN;
1626    XClearArea(_ecore_x_disp, win, x, y, w, h, True);
1627    if (_ecore_xlib_sync) ecore_x_sync();
1628 }
1629 
1630 EAPI void
ecore_x_window_override_set(Ecore_X_Window win,Eina_Bool override)1631 ecore_x_window_override_set(Ecore_X_Window win,
1632                             Eina_Bool override)
1633 {
1634    XSetWindowAttributes att;
1635 
1636    LOGFN;
1637    att.override_redirect = override;
1638    XChangeWindowAttributes(_ecore_x_disp, win, CWOverrideRedirect, &att);
1639    if (_ecore_xlib_sync) ecore_x_sync();
1640 }
1641 
1642 #ifdef ECORE_XRENDER
1643 static Ecore_X_Window
_ecore_x_window_argb_internal_new(Ecore_X_Window parent,int x,int y,int w,int h,Eina_Bool override,Eina_Bool saveunder)1644 _ecore_x_window_argb_internal_new(Ecore_X_Window parent,
1645                                   int x,
1646                                   int y,
1647                                   int w,
1648                                   int h,
1649                                   Eina_Bool override,
1650                                   Eina_Bool saveunder)
1651 {
1652    Window win;
1653    XSetWindowAttributes attr;
1654    XWindowAttributes att;
1655    XVisualInfo *xvi;
1656    XVisualInfo vi_in;
1657    int nvi, i, scr = 0;
1658    XRenderPictFormat *fmt;
1659    Visual *vis;
1660 
1661    if (parent == 0)
1662      {
1663         parent = DefaultRootWindow(_ecore_x_disp);
1664         scr = DefaultScreen(_ecore_x_disp);
1665      }
1666    else
1667      {
1668         /* ewww - round trip */
1669         if (XGetWindowAttributes(_ecore_x_disp, parent, &att))
1670           {
1671              if (_ecore_xlib_sync) ecore_x_sync();
1672              for (i = 0; i < ScreenCount(_ecore_x_disp); i++)
1673                {
1674                   if (att.screen == ScreenOfDisplay(_ecore_x_disp, i))
1675                     {
1676                        scr = i;
1677                        break;
1678                     }
1679                }
1680           }
1681      }
1682 
1683    vi_in.screen = scr;
1684    vi_in.depth = 32;
1685    vi_in.class = TrueColor;
1686    xvi = XGetVisualInfo(_ecore_x_disp,
1687                         VisualScreenMask |
1688                         VisualDepthMask |
1689                         VisualClassMask,
1690                         &vi_in,
1691                         &nvi);
1692    if (_ecore_xlib_sync) ecore_x_sync();
1693    if (!xvi)
1694      return 0;
1695 
1696    vis = NULL;
1697    for (i = 0; i < nvi; i++)
1698      {
1699         fmt = XRenderFindVisualFormat(_ecore_x_disp, xvi[i].visual);
1700         if (_ecore_xlib_sync) ecore_x_sync();
1701         if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
1702           {
1703              vis = xvi[i].visual;
1704              break;
1705           }
1706      }
1707    XFree (xvi);
1708 
1709    attr.backing_store = NotUseful;
1710    attr.override_redirect = override;
1711    attr.colormap = XCreateColormap(_ecore_x_disp, parent,
1712                                    vis, AllocNone);
1713    attr.border_pixel = 0;
1714    attr.background_pixmap = None;
1715    attr.bit_gravity = NorthWestGravity;
1716    attr.win_gravity = NorthWestGravity;
1717    attr.save_under = saveunder;
1718    attr.do_not_propagate_mask = NoEventMask;
1719    attr.event_mask = KeyPressMask |
1720      KeyReleaseMask |
1721      ButtonPressMask |
1722      ButtonReleaseMask |
1723      EnterWindowMask |
1724      LeaveWindowMask |
1725      PointerMotionMask |
1726      ExposureMask |
1727      VisibilityChangeMask |
1728      StructureNotifyMask |
1729      FocusChangeMask |
1730      PropertyChangeMask |
1731      ColormapChangeMask;
1732    win = XCreateWindow(_ecore_x_disp, parent,
1733                        x, y, w, h, 0,
1734                        32,
1735                        InputOutput,
1736                        vis,
1737                        CWBackingStore |
1738                        CWOverrideRedirect |
1739                        CWColormap |
1740                        CWBorderPixel |
1741                        CWBackPixmap |
1742                        CWSaveUnder |
1743                        CWDontPropagate |
1744                        CWEventMask |
1745                        CWBitGravity |
1746                        CWWinGravity,
1747                        &attr);
1748    if (_ecore_xlib_sync) ecore_x_sync();
1749 
1750    if (parent == DefaultRootWindow(_ecore_x_disp))
1751      ecore_x_window_defaults_set(win);
1752 
1753    return win;
1754 }
1755 
1756 #endif /* ifdef ECORE_XRENDER */
1757 
1758 EAPI int
ecore_x_window_argb_get(Ecore_X_Window win)1759 ecore_x_window_argb_get(Ecore_X_Window win)
1760 {
1761 #ifdef ECORE_XRENDER
1762    XWindowAttributes att;
1763    XRenderPictFormat *fmt;
1764    Eina_Bool ret;
1765 
1766    att.visual = 0;
1767    ret = XGetWindowAttributes(_ecore_x_disp, win, &att);
1768    if (_ecore_xlib_sync) ecore_x_sync();
1769    if (!ret) return 0;
1770 
1771    fmt = XRenderFindVisualFormat(_ecore_x_disp, att.visual);
1772    if (_ecore_xlib_sync) ecore_x_sync();
1773    if (!fmt)
1774      return 0;
1775 
1776    if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
1777      return 1;
1778 
1779    return 0;
1780 #else /* ifdef ECORE_XRENDER */
1781    return 0;
1782 #endif /* ifdef ECORE_XRENDER */
1783 }
1784 
1785 /**
1786  * Creates a new window.
1787  * @param   parent The parent window to use.  If @p parent is @c 0, the root
1788  *                 window of the default display is used.
1789  * @param   x      X position.
1790  * @param   y      Y position.
1791  * @param   w      Width.
1792  * @param   h      Height.
1793  * @return  The new window handle.
1794  * @ingroup Ecore_X_Window_Create_Group
1795  */
1796 EAPI Ecore_X_Window
ecore_x_window_manager_argb_new(Ecore_X_Window parent,int x,int y,int w,int h)1797 ecore_x_window_manager_argb_new(Ecore_X_Window parent,
1798                                 int x,
1799                                 int y,
1800                                 int w,
1801                                 int h)
1802 {
1803 #ifdef ECORE_XRENDER
1804    LOGFN;
1805    return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
1806 #else /* ifdef ECORE_XRENDER */
1807    return 0;
1808 #endif /* ifdef ECORE_XRENDER */
1809 }
1810 
1811 /**
1812  * Creates a new window.
1813  * @param   parent The parent window to use.  If @p parent is @c 0, the root
1814  *                 window of the default display is used.
1815  * @param   x      X position.
1816  * @param   y      Y position.
1817  * @param   w      Width.
1818  * @param   h      Height.
1819  * @return  The new window handle.
1820  * @ingroup Ecore_X_Window_Create_Group
1821  */
1822 EAPI Ecore_X_Window
ecore_x_window_argb_new(Ecore_X_Window parent,int x,int y,int w,int h)1823 ecore_x_window_argb_new(Ecore_X_Window parent,
1824                         int x,
1825                         int y,
1826                         int w,
1827                         int h)
1828 {
1829 #ifdef ECORE_XRENDER
1830    LOGFN;
1831    return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 0, 0);
1832 #else /* ifdef ECORE_XRENDER */
1833    return 0;
1834 #endif /* ifdef ECORE_XRENDER */
1835 }
1836 
1837 /**
1838  * Creates a window with the override redirect attribute set to @c True.
1839  * @param   parent The parent window to use.  If @p parent is @c 0, the root
1840  *                 window of the default display is used.
1841  * @param   x      X position.
1842  * @param   y      Y position.
1843  * @param   w      Width.
1844  * @param   h      Height.
1845  * @return  The new window handle.
1846  * @ingroup Ecore_X_Window_Create_Group
1847  */
1848 EAPI Ecore_X_Window
ecore_x_window_override_argb_new(Ecore_X_Window parent,int x,int y,int w,int h)1849 ecore_x_window_override_argb_new(Ecore_X_Window parent,
1850                                  int x,
1851                                  int y,
1852                                  int w,
1853                                  int h)
1854 {
1855 #ifdef ECORE_XRENDER
1856    LOGFN;
1857    return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
1858 #else /* ifdef ECORE_XRENDER */
1859    return 0;
1860 #endif /* ifdef ECORE_XRENDER */
1861 }
1862 
1863 EAPI Ecore_X_Window
ecore_x_window_permanent_new(Ecore_X_Window parent,Ecore_X_Atom unique_atom)1864 ecore_x_window_permanent_new(Ecore_X_Window parent, Ecore_X_Atom unique_atom)
1865 {
1866    Display *disp;
1867    Window win, win2, realwin = 0;
1868    Atom type_ret;
1869    int format_ret;
1870    unsigned long ldata, bytes_after, num_ret, *datap;
1871    unsigned char *prop_ret;
1872 
1873    LOGFN;
1874    disp = XOpenDisplay(DisplayString(_ecore_x_disp));
1875    if (!disp) return 0;
1876 
1877    XGrabServer(disp);
1878    if (XGetWindowProperty(disp, parent, unique_atom, 0, 0x7fffffff,
1879                           False, XA_WINDOW, &type_ret, &format_ret,
1880                           &num_ret, &bytes_after, &prop_ret) == Success)
1881      {
1882         if (prop_ret)
1883           {
1884              if ((format_ret == 32) && (type_ret == XA_WINDOW) &&
1885                  (num_ret == 1))
1886                {
1887                   datap = (unsigned long *)prop_ret;
1888                   win = (Window)(*datap);
1889                   XFree(prop_ret);
1890                   if (XGetWindowProperty(disp, win, unique_atom, 0, 0x7fffffff,
1891                                          False, XA_WINDOW, &type_ret, &format_ret,
1892                                          &num_ret, &bytes_after, &prop_ret) == Success)
1893                     {
1894                        if (prop_ret)
1895                          {
1896                             if ((format_ret == 32) && (type_ret == XA_WINDOW) &&
1897                                 (num_ret == 1))
1898                               {
1899                                  datap = (unsigned long *)prop_ret;
1900                                  win2 = (Window)(*datap);
1901                                  XFree(prop_ret);
1902                                  if (win2 == win) realwin = win;
1903                               }
1904                             else XFree(prop_ret);
1905                          }
1906                     }
1907                }
1908              else XFree(prop_ret);
1909           }
1910      }
1911    if (realwin != 0)
1912      {
1913         XUngrabServer(disp);
1914         XFlush(disp);
1915         XCloseDisplay(disp);
1916         return realwin;
1917      }
1918    win = XCreateSimpleWindow(disp, parent, -77, -77, 7, 7, 0, 0, 0);
1919    ldata = (unsigned long)win;
1920    XChangeProperty(disp, win, unique_atom, XA_WINDOW, 32,
1921                    PropModeReplace, (unsigned char *)(&ldata), 1);
1922    XChangeProperty(disp, parent, unique_atom, XA_WINDOW, 32,
1923                    PropModeReplace, (unsigned char *)(&ldata), 1);
1924    XSetCloseDownMode(disp, RetainPermanent);
1925    XUngrabServer(disp);
1926    XFlush(disp);
1927    XCloseDisplay(disp);
1928    return win;
1929 }
1930