update for beta release
[framework/uifw/e17.git] / src / bin / e_manager.c
1 #include "e.h"
2
3 /* local subsystem functions */
4 static void _e_manager_free(E_Manager *man);
5
6 static Eina_Bool _e_manager_cb_window_show_request(void *data, int ev_type, void *ev);
7 static Eina_Bool _e_manager_cb_window_configure(void *data, int ev_type, void *ev);
8 static Eina_Bool _e_manager_cb_key_up(void *data, int ev_type, void *ev);
9 static Eina_Bool _e_manager_cb_key_down(void *data, int ev_type, void *ev);
10 static Eina_Bool _e_manager_cb_frame_extents_request(void *data, int ev_type, void *ev);
11 static Eina_Bool _e_manager_cb_ping(void *data, int ev_type, void *ev);
12 static Eina_Bool _e_manager_cb_screensaver_notify(void *data, int ev_type, void *ev);
13 static Eina_Bool _e_manager_cb_client_message(void *data, int ev_type, void *ev);
14
15 static Eina_Bool _e_manager_frame_extents_free_cb(const Eina_Hash *hash __UNUSED__,
16                                                   const void *key __UNUSED__,
17                                                   void *data, void *fdata __UNUSED__);
18 static E_Manager *_e_manager_get_for_root(Ecore_X_Window root);
19 #if 0 /* use later - maybe */
20 static int _e_manager_cb_window_destroy(void *data, int ev_type, void *ev);
21 static int _e_manager_cb_window_hide(void *data, int ev_type, void *ev);
22 static int _e_manager_cb_window_reparent(void *data, int ev_type, void *ev);
23 static int _e_manager_cb_window_create(void *data, int ev_type, void *ev);
24 static int _e_manager_cb_window_configure_request(void *data, int ev_type, void *ev);
25 static int _e_manager_cb_window_gravity(void *data, int ev_type, void *ev);
26 static int _e_manager_cb_window_stack(void *data, int ev_type, void *ev);
27 static int _e_manager_cb_window_stack_request(void *data, int ev_type, void *ev);
28 static int _e_manager_cb_window_property(void *data, int ev_type, void *ev);
29 static int _e_manager_cb_window_colormap(void *data, int ev_type, void *ev);
30 static int _e_manager_cb_window_shape(void *data, int ev_type, void *ev);
31 static int _e_manager_cb_client_message(void *data, int ev_type, void *ev);
32 #endif
33
34 /* local subsystem globals */
35
36 typedef struct _Frame_Extents Frame_Extents;
37
38 struct _Frame_Extents
39 {
40    int l, r, t, b;
41 };
42
43 static Eina_List *managers = NULL;
44 static Eina_Hash *frame_extents = NULL;
45 static Ecore_Timer *timer_post_screensaver_lock = NULL;
46
47 /* externally accessible functions */
48 EINTERN int
49 e_manager_init(void)
50 {
51    ecore_x_screensaver_event_listen_set(1);
52    frame_extents = eina_hash_string_superfast_new(NULL);
53    return 1;
54 }
55
56 EINTERN int
57 e_manager_shutdown(void)
58 {
59    E_FREE_LIST(managers, e_object_del);
60
61    if (frame_extents)
62      {
63         eina_hash_foreach(frame_extents, _e_manager_frame_extents_free_cb, NULL);
64         eina_hash_free(frame_extents);
65         frame_extents = NULL;
66      }
67
68    if (timer_post_screensaver_lock)
69      {
70         ecore_timer_del(timer_post_screensaver_lock);
71         timer_post_screensaver_lock = NULL;
72      }
73
74    return 1;
75 }
76
77 EAPI Eina_List *
78 e_manager_list(void)
79 {
80    return managers;
81 }
82
83 EAPI E_Manager *
84 e_manager_new(Ecore_X_Window root, int num)
85 {
86    E_Manager *man;
87
88    if (!ecore_x_window_manage(root)) return NULL;
89    ecore_x_window_background_color_set(root, 0, 0, 0);
90    man = E_OBJECT_ALLOC(E_Manager, E_MANAGER_TYPE, _e_manager_free);
91    if (!man) return NULL;
92    managers = eina_list_append(managers, man);
93    man->root = root;
94    man->num = num;
95    ecore_x_window_size_get(man->root, &(man->w), &(man->h));
96    if (e_config->use_virtual_roots)
97      {
98         man->win = ecore_x_window_override_new(man->root, man->x, man->y, man->w, man->h);
99         ecore_x_icccm_title_set(man->win, "Enlightenment Manager");
100         ecore_x_netwm_name_set(man->win, "Enlightenment Manager");
101         ecore_x_window_raise(man->win);
102      }
103    else
104      {
105         man->win = man->root;
106      }
107
108    man->handlers = 
109      eina_list_append(man->handlers, 
110                       ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, 
111                                               _e_manager_cb_window_show_request, 
112                                               man));
113    man->handlers = 
114      eina_list_append(man->handlers, 
115                       ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, 
116                                               _e_manager_cb_window_configure, 
117                                               man));
118    man->handlers = 
119      eina_list_append(man->handlers, 
120                       ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, 
121                                               _e_manager_cb_key_down, 
122                                               man));
123    man->handlers = 
124      eina_list_append(man->handlers, 
125                       ecore_event_handler_add(ECORE_EVENT_KEY_UP, 
126                                               _e_manager_cb_key_up, 
127                                               man));
128    man->handlers = 
129      eina_list_append(man->handlers, 
130                       ecore_event_handler_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, 
131                                               _e_manager_cb_frame_extents_request, 
132                                               man));
133    man->handlers = 
134      eina_list_append(man->handlers, 
135                       ecore_event_handler_add(ECORE_X_EVENT_PING, 
136                                               _e_manager_cb_ping, 
137                                               man));
138    man->handlers = 
139      eina_list_append(man->handlers, 
140                       ecore_event_handler_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, 
141                                               _e_manager_cb_screensaver_notify, 
142                                               man));
143    man->handlers = 
144      eina_list_append(man->handlers, 
145                       ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, 
146                                               _e_manager_cb_client_message, 
147                                               man));
148
149    man->pointer = e_pointer_window_new(man->root, 1);
150
151    return man;
152 }
153
154 EAPI void
155 e_manager_manage_windows(E_Manager *man)
156 {
157    Ecore_X_Window *windows;
158    int wnum;
159
160    /* a manager is designated for each root. lets get all the windows in
161       the managers root */
162    windows = ecore_x_window_children_get(man->root, &wnum);
163    if (windows)
164      {
165         int i;
166         const char *atom_names[] =
167           {
168              "_XEMBED_INFO",
169                "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
170                "KWM_DOCKWINDOW"
171           };
172         Ecore_X_Atom atoms[3];
173         Ecore_X_Atom atom_xmbed, atom_kde_netwm_systray, atom_kwm_dockwindow;
174         unsigned char *data = NULL;
175         int count;
176
177         ecore_x_atoms_get(atom_names, 3, atoms);
178         atom_xmbed = atoms[0];
179         atom_kde_netwm_systray = atoms[1];
180         atom_kwm_dockwindow = atoms[2];
181         for (i = 0; i < wnum; i++)
182           {
183              Ecore_X_Window_Attributes att;
184              unsigned int ret_val, deskxy[2];
185              int ret;
186
187              if (e_border_find_by_client_window(windows[i]))
188                continue;
189              ecore_x_window_attributes_get(windows[i], &att);
190              if ((att.override) || (att.input_only))
191                {
192                   if (att.override)
193                     {
194                        char *wname = NULL, *wclass = NULL;
195
196                        ecore_x_icccm_name_class_get(windows[i],
197                                                     &wname, &wclass);
198                        if ((wname) && (wclass) &&
199                            (!strcmp(wname, "E")) &&
200                            (!strcmp(wclass, "Init_Window")))
201                          {
202                             free(wname);
203                             free(wclass);
204                             man->initwin = windows[i];
205                          }
206                        else
207                          {
208                             if (wname) free(wname);
209                             if (wclass) free(wclass);
210                             continue;
211                          }
212                     }
213                   else
214                     continue;
215                }
216              /* XXX manage xembed windows as long as they are not override_redirect..
217               * if (!ecore_x_window_prop_property_get(windows[i],
218               *                                            atom_xmbed,
219               *                                            atom_xmbed, 32,
220               *                                            &data, &count))
221               *   data = NULL;
222               * if (!data) */
223                {
224                   if (!ecore_x_window_prop_property_get(windows[i],
225                                                         atom_kde_netwm_systray,
226                                                         atom_xmbed, 32,
227                                                         &data, &count))
228                     data = NULL;
229                }
230              if (!data)
231                {
232                   if (!ecore_x_window_prop_property_get(windows[i],
233                                                         atom_kwm_dockwindow,
234                                                         atom_kwm_dockwindow, 32,
235                                                         &data, &count))
236                     data = NULL;
237                }
238              if (data)
239                {
240                   free(data);
241                   data = NULL;
242                   continue;
243                }
244              ret = ecore_x_window_prop_card32_get(windows[i],
245                                                   E_ATOM_MANAGED,
246                                                   &ret_val, 1);
247
248              /* we have seen this window before */
249              if ((ret > -1) && (ret_val == 1))
250                {
251                   E_Container  *con = NULL;
252                   E_Zone       *zone = NULL;
253                   E_Desk       *desk = NULL;
254                   E_Border     *bd = NULL;
255                   unsigned int  id;
256                   char *path;
257                   Efreet_Desktop *desktop = NULL;
258
259                   /* get all information from window before it is
260                    * reset by e_border_new */
261                   ret = ecore_x_window_prop_card32_get(windows[i],
262                                                        E_ATOM_CONTAINER,
263                                                        &id, 1);
264                   if (ret == 1)
265                     con = e_container_number_get(man, id);
266                   if (!con)
267                     con = e_container_current_get(man);
268
269                   ret = ecore_x_window_prop_card32_get(windows[i],
270                                                        E_ATOM_ZONE,
271                                                        &id, 1);
272                   if (ret == 1)
273                     zone = e_container_zone_number_get(con, id);
274                   if (!zone)
275                     zone = e_zone_current_get(con);
276                   ret = ecore_x_window_prop_card32_get(windows[i],
277                                                        E_ATOM_DESK,
278                                                        deskxy, 2);
279                   if (ret == 2)
280                     desk = e_desk_at_xy_get(zone,
281                                             deskxy[0],
282                                             deskxy[1]);
283
284                   path = ecore_x_window_prop_string_get(windows[i],
285                                                         E_ATOM_DESKTOP_FILE);
286                   if (path)
287                     {
288                        desktop = efreet_desktop_get(path);
289                        free(path);
290                     }
291
292                     {
293                        bd = e_border_new(con, windows[i], 1, 0);
294                        if (bd)
295                          {
296                             bd->ignore_first_unmap = 1;
297                             /* FIXME:
298                              * It's enough to set the desk, the zone will
299                              * be set according to the desk */
300 //                          if (zone) e_border_zone_set(bd, zone);
301                             if (desk) e_border_desk_set(bd, desk);
302                             bd->desktop = desktop;
303                          }
304                     }
305                }
306              else if ((att.visible) && (!att.override) &&
307                       (!att.input_only))
308                {
309                   /* We have not seen this window, and X tells us it
310                    * should be seen */
311                   E_Container *con;
312                   E_Border *bd;
313
314                   con = e_container_current_get(man);
315                   bd = e_border_new(con, windows[i], 1, 0);
316                   if (bd)
317                     {
318                        bd->ignore_first_unmap = 1;
319                        e_border_show(bd);
320                     }
321                }
322           }
323         free(windows);
324      }
325 }
326
327 EAPI void
328 e_manager_show(E_Manager *man)
329 {
330    Eina_List *l;
331    E_Container *con;
332
333    E_OBJECT_CHECK(man);
334    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
335    if (man->visible) return;
336    EINA_LIST_FOREACH(man->containers, l, con)
337      {
338         e_container_show(con);
339      }
340    if (man->root != man->win)
341      {
342         Ecore_X_Window mwin;
343
344         mwin = e_menu_grab_window_get();
345         if (!mwin) mwin = man->initwin;
346         if (!mwin)
347           ecore_x_window_raise(man->win);
348         else
349           ecore_x_window_configure(man->win,
350                                    ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
351                                    ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
352                                    0, 0, 0, 0, 0,
353                                    mwin, ECORE_X_WINDOW_STACK_BELOW);
354         ecore_x_window_show(man->win);
355      }
356    man->visible = 1;
357 }
358
359 EAPI void
360 e_manager_hide(E_Manager *man)
361 {
362    Eina_List *l;
363    E_Container *con;
364
365    E_OBJECT_CHECK(man);
366    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
367    if (!man->visible) return;
368    EINA_LIST_FOREACH(man->containers, l, con)
369      {
370         e_container_hide(con);
371      }
372    if (man->root != man->win)
373      ecore_x_window_hide(man->win);
374    man->visible = 0;
375 }
376
377 EAPI void
378 e_manager_move(E_Manager *man, int x, int y)
379 {
380    E_OBJECT_CHECK(man);
381    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
382    if ((x == man->x) && (y == man->y)) return;
383    if (man->root != man->win)
384      {
385         man->x = x;
386         man->y = y;
387         ecore_x_window_move(man->win, man->x, man->y);
388      }
389 }
390
391 EAPI void
392 e_manager_resize(E_Manager *man, int w, int h)
393 {
394    Eina_List *l;
395    E_Container *con;
396
397    E_OBJECT_CHECK(man);
398    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
399    if ((w == man->w) && (h == man->h)) return;
400    man->w = w;
401    man->h = h;
402    if (man->root != man->win)
403      ecore_x_window_resize(man->win, man->w, man->h);
404
405    EINA_LIST_FOREACH(man->containers, l, con)
406      {
407         e_container_resize(con, man->w, man->h);
408      }
409
410    ecore_x_netwm_desk_size_set(man->root, man->w, man->h);
411 }
412
413 EAPI void
414 e_manager_move_resize(E_Manager *man, int x, int y, int w, int h)
415 {
416    Eina_List *l;
417    E_Container *con;
418
419    E_OBJECT_CHECK(man);
420    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
421    if ((x == man->x) && (y == man->y) && (w == man->w) && (h == man->h)) return;
422    if (man->root != man->win)
423      {
424         man->x = x;
425         man->y = y;
426      }
427    man->w = w;
428    man->h = h;
429    ecore_x_window_move_resize(man->win, man->x, man->y, man->w, man->h);
430
431    EINA_LIST_FOREACH(man->containers, l, con)
432      {
433         e_container_resize(con, man->w, man->h);
434      }
435 }
436
437 EAPI void
438 e_manager_raise(E_Manager *man)
439 {
440    E_OBJECT_CHECK(man);
441    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
442    if (man->root != man->win)
443      {
444         Ecore_X_Window mwin;
445
446         mwin = e_menu_grab_window_get();
447         if (!mwin) mwin = man->initwin;
448         if (!mwin)
449           ecore_x_window_raise(man->win);
450         else
451           ecore_x_window_configure(man->win,
452                                    ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
453                                    ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
454                                    0, 0, 0, 0, 0,
455                                    mwin, ECORE_X_WINDOW_STACK_BELOW);
456      }
457 }
458
459 EAPI void
460 e_manager_lower(E_Manager *man)
461 {
462    E_OBJECT_CHECK(man);
463    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
464    if (man->root != man->win)
465      ecore_x_window_lower(man->win);
466 }
467
468 EAPI E_Manager *
469 e_manager_current_get(void)
470 {
471    Eina_List *l;
472    E_Manager *man;
473    int x, y;
474
475    if (!managers) return NULL;
476    EINA_LIST_FOREACH(managers, l, man)
477      {
478         ecore_x_pointer_xy_get(man->win, &x, &y);
479         if (x == -1 && y == -1)
480           continue;
481         if (E_INSIDE(x, y, man->x, man->y, man->w, man->h))
482           return man;
483      }
484    return eina_list_data_get(managers);
485 }
486
487 EAPI E_Manager *
488 e_manager_number_get(int num)
489 {
490    Eina_List *l;
491    E_Manager *man;
492
493    if (!managers) return NULL;
494    EINA_LIST_FOREACH(managers, l, man)
495      {
496         if (man->num == num)
497           return man;
498      }
499    return NULL;
500 }
501
502 EAPI void
503 e_managers_keys_grab(void)
504 {
505    Eina_List *l;
506    E_Manager *man;
507
508    EINA_LIST_FOREACH(managers, l, man)
509      {
510         e_bindings_key_grab(E_BINDING_CONTEXT_ANY, man->root);
511      }
512 }
513
514 EAPI void
515 e_managers_keys_ungrab(void)
516 {
517    Eina_List *l;
518    E_Manager *man;
519
520    EINA_LIST_FOREACH(managers, l, man)
521      {
522         e_bindings_key_ungrab(E_BINDING_CONTEXT_ANY, man->root);
523      }
524 }
525
526
527
528
529
530
531
532 EAPI void
533 e_manager_comp_set(E_Manager *man, E_Manager_Comp *comp)
534 {
535    E_OBJECT_CHECK(man);
536    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
537    man->comp = comp;
538    e_msg_send("comp.manager", "change.comp", // name + info
539               0, // val
540               E_OBJECT(man), // obj
541               NULL, // msgdata
542               NULL, NULL); // afterfunc + afterdata
543 }
544
545 EAPI Evas *
546 e_manager_comp_evas_get(E_Manager *man)
547 {
548    E_OBJECT_CHECK(man);
549    E_OBJECT_TYPE_CHECK_RETURN(man, E_MANAGER_TYPE, NULL);
550    if (!man->comp) return NULL;
551    return man->comp->func.evas_get(man->comp->data, man);
552 }
553
554 EAPI void
555 e_manager_comp_evas_update(E_Manager *man)
556 {
557    E_OBJECT_CHECK(man);
558    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
559    if (!man->comp) return;
560    return man->comp->func.update(man->comp->data, man);
561 }
562
563 EAPI const Eina_List *
564 e_manager_comp_src_list(E_Manager *man)
565 {
566    return man->comp->func.src_list_get(man->comp->data, man);
567 }
568
569 EAPI E_Manager_Comp_Source*
570 e_manager_comp_src_get(E_Manager *man, Ecore_X_Window win)
571 {
572    return man->comp->func.src_get(man->comp->data, man, win);
573 }
574
575 EAPI Evas_Object *
576 e_manager_comp_src_image_get(E_Manager *man, E_Manager_Comp_Source *src)
577 {
578    return man->comp->func.src_image_get(man->comp->data, man, src);
579 }
580
581 EAPI Evas_Object *
582 e_manager_comp_src_shadow_get(E_Manager *man, E_Manager_Comp_Source *src)
583 {
584    return man->comp->func.src_shadow_get(man->comp->data, man, src);
585 }
586
587 EAPI Evas_Object *
588 e_manager_comp_src_image_mirror_add(E_Manager *man, E_Manager_Comp_Source *src)
589 {
590    return man->comp->func.src_image_mirror_add(man->comp->data, man, src);
591 }
592
593 EAPI Eina_Bool
594 e_manager_comp_src_visible_get(E_Manager *man, E_Manager_Comp_Source *src)
595 {
596    return man->comp->func.src_visible_get(man->comp->data, man, src);
597 }
598
599 EAPI void
600 e_manager_comp_src_hidden_set(E_Manager *man, E_Manager_Comp_Source *src, Eina_Bool hidden)
601 {
602    return man->comp->func.src_hidden_set(man->comp->data, man, src, hidden);
603 }
604
605 EAPI Eina_Bool
606 e_manager_comp_src_hidden_get(E_Manager *man, E_Manager_Comp_Source *src)
607 {
608    return man->comp->func.src_hidden_get(man->comp->data, man, src);
609 }
610
611 EAPI Ecore_X_Window
612 e_manager_comp_src_window_get(E_Manager *man, E_Manager_Comp_Source *src)
613 {
614    return man->comp->func.src_window_get(man->comp->data, man, src);
615 }
616
617 EAPI E_Popup *
618 e_manager_comp_src_popup_get(E_Manager *man, E_Manager_Comp_Source *src)
619 {
620    return man->comp->func.src_popup_get(man->comp->data, man, src);
621 }
622
623 EAPI E_Border *
624 e_manager_comp_src_border_get(E_Manager *man, E_Manager_Comp_Source *src)
625 {
626    return man->comp->func.src_border_get(man->comp->data, man, src);
627 }
628
629 #ifdef _F_COMP_SCREEN_LOCK_
630 EAPI void
631 e_manager_comp_screen_lock(E_Manager *man)
632 {
633    E_OBJECT_CHECK(man);
634    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
635    if (!man->comp) return;
636    return man->comp->func.screen_lock(man->comp->data, man);
637 }
638
639 EAPI void
640 e_manager_comp_screen_unlock(E_Manager *man)
641 {
642    E_OBJECT_CHECK(man);
643    E_OBJECT_TYPE_CHECK(man, E_MANAGER_TYPE);
644    if (!man->comp) return;
645    return man->comp->func.screen_unlock(man->comp->data, man);
646 }
647 #endif
648
649 #ifdef _F_COMP_INPUT_REGION_SET_
650 EAPI Eina_Bool
651 e_manager_comp_src_input_region_set(E_Manager *man, E_Manager_Comp_Source *src, int x, int y, int w, int h)
652 {
653    E_OBJECT_CHECK_RETURN(man, EINA_FALSE);
654    E_OBJECT_TYPE_CHECK_RETURN(man, E_MANAGER_TYPE, EINA_FALSE);
655    if (!man->comp) return EINA_FALSE;
656    E_OBJECT_CHECK_RETURN(src, EINA_FALSE);
657    return man->comp->func.src_input_region_set(man->comp->data, man, src, x, y, w, h);
658 }
659 #endif
660
661 #ifdef _F_COMP_MOVE_LOCK_
662 EAPI Eina_Bool
663 e_manager_comp_src_move_lock(E_Manager *man, E_Manager_Comp_Source *src)
664 {
665    E_OBJECT_CHECK_RETURN(man, EINA_FALSE);
666    E_OBJECT_TYPE_CHECK_RETURN(man, E_MANAGER_TYPE, EINA_FALSE);
667    if (!man->comp) return EINA_FALSE;
668    E_OBJECT_CHECK_RETURN(src, EINA_FALSE);
669    return man->comp->func.src_move_lock(man->comp->data, man, src);
670 }
671
672 EAPI Eina_Bool
673 e_manager_comp_src_move_unlock(E_Manager *man, E_Manager_Comp_Source *src)
674 {
675    E_OBJECT_CHECK_RETURN(man, EINA_FALSE);
676    E_OBJECT_TYPE_CHECK_RETURN(man, E_MANAGER_TYPE, EINA_FALSE);
677    if (!man->comp) return EINA_FALSE;
678    E_OBJECT_CHECK_RETURN(src, EINA_FALSE);
679    return man->comp->func.src_move_unlock(man->comp->data, man, src);
680 }
681 #endif
682
683 EAPI void
684 e_manager_comp_event_resize_send(E_Manager *man)
685 {
686    e_msg_send("comp.manager", "resize.comp", // name + info
687               0, // val
688               E_OBJECT(man), // obj
689               NULL, // msgdata
690               NULL, NULL); // afterfunc + afterdata
691 }
692
693 EAPI void
694 e_manager_comp_event_src_add_send(E_Manager *man, E_Manager_Comp_Source *src,
695                                   void (*afterfunc) (void *data, E_Manager *man, E_Manager_Comp_Source *src),
696                                   void *data)
697 {
698    e_msg_send("comp.manager", "add.src", // name + info
699               0, // val
700               E_OBJECT(man), // obj
701               src, // msgdata
702               (void (*)(void *, E_Object *, void *))afterfunc, data); // afterfunc + afterdata
703 }
704
705 EAPI void
706 e_manager_comp_event_src_del_send(E_Manager *man, E_Manager_Comp_Source *src,
707                                   void (*afterfunc) (void *data, E_Manager *man, E_Manager_Comp_Source *src),
708                                   void *data)
709 {
710    e_msg_send("comp.manager", "del.src", // name + info
711               0, // val
712               E_OBJECT(man), // obj
713               src, // msgdata
714               (void (*)(void *, E_Object *, void *))afterfunc, data); // afterfunc + afterdata
715 }
716
717 EAPI void
718 e_manager_comp_event_src_config_send(E_Manager *man, E_Manager_Comp_Source *src,
719                                      void (*afterfunc) (void *data, E_Manager *man, E_Manager_Comp_Source *src),
720                                      void *data)
721 {
722    e_msg_send("comp.manager", "config.src", // name + info
723               0, // val
724               E_OBJECT(man), // obj
725               src, // msgdata
726               (void (*)(void *, E_Object *, void *))afterfunc, data); // afterfunc + afterdata
727 }
728
729 EAPI void
730 e_manager_comp_event_src_visibility_send(E_Manager *man, E_Manager_Comp_Source *src,
731                                          void (*afterfunc) (void *data, E_Manager *man, E_Manager_Comp_Source *src),
732                                          void *data)
733 {
734    e_msg_send("comp.manager", "visibility.src", // name + info
735               0, // val
736               E_OBJECT(man), // obj
737               src, // msgdata
738               (void (*)(void *, E_Object *, void *))afterfunc, data); // afterfunc + afterdata
739 }
740
741
742
743
744
745 /* local subsystem functions */
746 static void
747 _e_manager_free(E_Manager *man)
748 {
749    Eina_List *l;
750
751    E_FREE_LIST(man->handlers, ecore_event_handler_del);
752    l = man->containers;
753    man->containers = NULL;
754    E_FREE_LIST(l, e_object_del);
755    if (man->root != man->win)
756      {
757         ecore_x_window_free(man->win);
758      }
759    if (man->pointer) e_object_del(E_OBJECT(man->pointer));
760    managers = eina_list_remove(managers, man);
761    free(man);
762 }
763
764 static Eina_Bool
765 _e_manager_cb_window_show_request(void *data, int ev_type __UNUSED__, void *ev)
766 {
767    E_Manager *man;
768    Ecore_X_Event_Window_Show_Request *e;
769
770    man = data;
771    e = ev;
772    if (e_stolen_win_get(e->win)) return 1;
773    if (ecore_x_window_parent_get(e->win) != man->root)
774      return ECORE_CALLBACK_PASS_ON;  /* try other handlers for this */
775
776      {
777         E_Container *con;
778         E_Border *bd;
779
780         con = e_container_current_get(man);
781         if (!e_border_find_by_client_window(e->win))
782           {
783              bd = e_border_new(con, e->win, 0, 0);
784              if (!bd)
785                ecore_x_window_show(e->win);
786           }
787      }
788    return ECORE_CALLBACK_PASS_ON;
789 }
790
791 static Eina_Bool
792 _e_manager_cb_window_configure(void *data, int ev_type __UNUSED__, void *ev)
793 {
794    E_Manager *man;
795    Ecore_X_Event_Window_Configure *e;
796
797    man = data;
798    e = ev;
799    if (e->win != man->root) return ECORE_CALLBACK_PASS_ON;
800    e_manager_resize(man, e->w, e->h);
801    return ECORE_CALLBACK_PASS_ON;
802 }
803
804 static Eina_Bool
805 _e_manager_cb_key_down(void *data, int ev_type __UNUSED__, void *ev)
806 {
807    E_Manager *man;
808    Ecore_Event_Key *e;
809
810    man = data;
811    e = ev;
812
813    if (e->event_window != man->root) return ECORE_CALLBACK_PASS_ON;
814    if (e->root_window != man->root) man = _e_manager_get_for_root(e->root_window);
815    if (e_bindings_key_down_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(man), ev))
816      return ECORE_CALLBACK_DONE;
817    return ECORE_CALLBACK_PASS_ON;
818 }
819
820 static Eina_Bool
821 _e_manager_cb_key_up(void *data, int ev_type __UNUSED__, void *ev)
822 {
823    E_Manager *man;
824    Ecore_Event_Key *e;
825
826    man = data;
827    e = ev;
828
829    if (e->event_window != man->root) return ECORE_CALLBACK_PASS_ON;
830    if (e->root_window != man->root) man = _e_manager_get_for_root(e->root_window);
831    if (e_bindings_key_up_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(man), ev))
832      return ECORE_CALLBACK_DONE;
833    return ECORE_CALLBACK_PASS_ON;
834 }
835
836 static Eina_Bool
837 _e_manager_cb_frame_extents_request(void *data, int ev_type __UNUSED__, void *ev)
838 {
839    E_Manager *man;
840    E_Container *con;
841    Ecore_X_Event_Frame_Extents_Request *e;
842    Ecore_X_Window_Type type;
843    Ecore_X_MWM_Hint_Decor decor;
844    Ecore_X_Window_State *state;
845    Frame_Extents *extents;
846    const char *border, *signal, *key;
847    int ok;
848    unsigned int i, num;
849
850    man = data;
851    con = e_container_current_get(man);
852    e = ev;
853
854    if (ecore_x_window_parent_get(e->win) != man->root) return ECORE_CALLBACK_PASS_ON;
855
856    /* TODO:
857     * * We need to check if we remember this window, and border locking is set
858     */
859    border = "default";
860    key = border;
861    ok = ecore_x_mwm_hints_get(e->win, NULL, &decor, NULL);
862    if ((ok) &&
863        (!(decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
864        (!(decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
865        (!(decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
866      {
867         border = "borderless";
868         key = border;
869      }
870
871    ok = ecore_x_netwm_window_type_get(e->win, &type);
872    if ((ok) &&
873        ((type == ECORE_X_WINDOW_TYPE_DESKTOP) ||
874         (type == ECORE_X_WINDOW_TYPE_DOCK)))
875      {
876         border = "borderless";
877         key = border;
878      }
879
880    signal = NULL;
881    ecore_x_netwm_window_state_get(e->win, &state, &num);
882    if (state)
883      {
884         int maximized = 0;
885
886         for (i = 0; i < num; i++)
887           {
888              switch (state[i])
889                {
890                 case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
891                   maximized++;
892                   break;
893                 case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
894                   maximized++;
895                   break;
896                 case ECORE_X_WINDOW_STATE_FULLSCREEN:
897                   border = "borderless";
898                   key = border;
899                   break;
900                 case ECORE_X_WINDOW_STATE_SHADED:
901                 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
902                 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
903                 case ECORE_X_WINDOW_STATE_HIDDEN:
904                 case ECORE_X_WINDOW_STATE_ICONIFIED:
905                 case ECORE_X_WINDOW_STATE_MODAL:
906                 case ECORE_X_WINDOW_STATE_STICKY:
907                 case ECORE_X_WINDOW_STATE_ABOVE:
908                 case ECORE_X_WINDOW_STATE_BELOW:
909                 case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
910                 case ECORE_X_WINDOW_STATE_UNKNOWN:
911                   break;
912                }
913           }
914         if ((maximized == 2) &&
915             (e_config->maximize_policy == E_MAXIMIZE_FULLSCREEN))
916           {
917              signal = "e,action,maximize,fullscreen";
918              key = "maximize,fullscreen";
919           }
920         free(state);
921      }
922
923    extents = eina_hash_find(frame_extents, key);
924    if (!extents)
925      {
926         extents = E_NEW(Frame_Extents, 1);
927         if (extents)
928           {
929              Evas_Object *o;
930              char buf[1024];
931
932              o = edje_object_add(con->bg_evas);
933              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", border);
934              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
935              if (ok)
936                {
937                   Evas_Coord x, y, w, h;
938
939                   if (signal)
940                     {
941                        edje_object_signal_emit(o, signal, "e");
942                        edje_object_message_signal_process(o);
943                     }
944
945                   evas_object_resize(o, 1000, 1000);
946                   edje_object_calc_force(o);
947                   edje_object_part_geometry_get(o, "e.swallow.client",
948                                                 &x, &y, &w, &h);
949                   extents->l = x;
950                   extents->r = 1000 - (x + w);
951                   extents->t = y;
952                   extents->b = 1000 - (y + h);
953                }
954              else
955                {
956                   extents->l = 0;
957                   extents->r = 0;
958                   extents->t = 0;
959                   extents->b = 0;
960                }
961              evas_object_del(o);
962              eina_hash_add(frame_extents, key, extents);
963           }
964      }
965
966    if (extents)
967      ecore_x_netwm_frame_size_set(e->win, extents->l, extents->r, extents->t, extents->b);
968
969    return ECORE_CALLBACK_PASS_ON;
970 }
971
972 static Eina_Bool
973 _e_manager_cb_ping(void *data, int ev_type __UNUSED__, void *ev)
974 {
975    E_Manager *man;
976    E_Border *bd;
977    Ecore_X_Event_Ping *e;
978
979    man = data;
980    e = ev;
981
982    if (e->win != man->root) return ECORE_CALLBACK_PASS_ON;
983
984    bd = e_border_find_by_client_window(e->event_win);
985    if (!bd) return ECORE_CALLBACK_PASS_ON;
986
987    bd->ping_ok = 1;
988    return ECORE_CALLBACK_PASS_ON;
989 }
990
991 static Eina_Bool
992 _e_manager_cb_timer_post_screensaver_lock(void *data __UNUSED__)
993 {
994    e_desklock_show_autolocked();
995    timer_post_screensaver_lock = NULL;
996    return ECORE_CALLBACK_CANCEL;
997 }
998
999 static Eina_Bool
1000 _e_manager_cb_screensaver_notify(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1001 {
1002    Ecore_X_Event_Screensaver_Notify *e = ev;
1003
1004    if (timer_post_screensaver_lock)
1005      {
1006         ecore_timer_del(timer_post_screensaver_lock);
1007         timer_post_screensaver_lock = NULL;
1008      }
1009
1010    if (e->on)
1011      {
1012         if (e_config->desklock_autolock_screensaver)
1013           {
1014              if (e_config->desklock_post_screensaver_time <= 1.0)
1015                {
1016                   e_desklock_show_autolocked();
1017                }
1018              else
1019                {
1020                   timer_post_screensaver_lock = ecore_timer_add
1021                     (e_config->desklock_post_screensaver_time,
1022                      _e_manager_cb_timer_post_screensaver_lock, NULL);
1023                }
1024           }
1025      }
1026    return ECORE_CALLBACK_PASS_ON;
1027 }
1028
1029
1030 #ifdef _F_WINDOW_GROUP_RAISE_
1031 static void
1032 _e_manager_windows_group_raise (E_Border* bd)
1033 {
1034    Ecore_X_Window leader_win;
1035    
1036    if (!bd) return;
1037
1038    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
1039       (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
1040       ((bd->parent) && 
1041       ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
1042       ((bd->parent->focused) &&
1043       (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))))
1044      {
1045         leader_win = bd->client.icccm.client_leader;
1046         if (leader_win)
1047           {
1048              Eina_List* border_list;
1049              Eina_List* restack_list;
1050              Eina_List *l;   
1051              E_Border *temp_bd;
1052              E_Border *top_bd;
1053              E_Border_List *bl;
1054
1055              restack_list = NULL;
1056              top_bd = NULL;
1057              bl = e_container_border_list_last(bd->zone->container);
1058              while ((temp_bd = e_container_border_list_prev(bl)))
1059                {
1060                   if (temp_bd->client.icccm.client_leader == leader_win)
1061                     {
1062                        restack_list = eina_list_prepend(restack_list, temp_bd);
1063                     }
1064                }
1065              e_container_border_list_free(bl);
1066
1067              if (restack_list)
1068                {
1069                   EINA_LIST_FREE (restack_list, temp_bd)
1070                     {
1071                        if (temp_bd->iconic)
1072                          {
1073                             if (e_config->clientlist_warp_to_iconified_desktop == 1)
1074                                e_desk_show(temp_bd->desk);
1075
1076                             if (!temp_bd->lock_user_iconify)
1077                                e_border_uniconify(temp_bd);
1078                          }
1079
1080                        if (!temp_bd->iconic) e_desk_show(temp_bd->desk);
1081                        if (!temp_bd->lock_user_stacking) e_border_raise(temp_bd);
1082
1083                        // set focus to top window
1084                        if (!temp_bd->lock_focus_out)
1085                          {
1086                             top_bd = temp_bd;
1087
1088                             if (e_config->focus_policy != E_FOCUS_CLICK)
1089                                ecore_x_pointer_warp(top_bd->zone->container->win, top_bd->x + (top_bd->w / 2), top_bd->y + (top_bd->h / 2));
1090                             
1091                             if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
1092                                e_border_focus_set(top_bd, 1, 1);
1093                             else
1094                               {
1095                                  Eina_List* l2;
1096                                  E_Border* temp_bd2;
1097                                  l2 = NULL;
1098                                  temp_bd2 = NULL;
1099
1100                                  bl = e_container_border_list_last(bd->zone->container);
1101                                  while ((temp_bd2 = e_container_border_list_prev(bl)))
1102                                    {
1103                                       if ((!temp_bd2->iconic) && (temp_bd2->visible) && (temp_bd2->desk == top_bd->desk) &&
1104                                          (temp_bd2->client.icccm.accepts_focus || temp_bd2->client.icccm.take_focus) &&
1105                                          (temp_bd2->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
1106                                          (temp_bd2->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
1107                                          (temp_bd2->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
1108                                          (temp_bd2->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
1109                                          (temp_bd2->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
1110                                         {
1111                                            if (top_bd == temp_bd2)
1112                                              {
1113                                                 e_border_focus_set(top_bd, 1, 1);
1114                                              }
1115                                             break;
1116                                         }
1117                                    }
1118                                  e_container_border_list_free(bl);
1119                               }
1120                          }
1121                     }
1122                }
1123           }
1124      }
1125 }
1126 #endif // group raise
1127
1128 static Eina_Bool
1129 _e_manager_cb_client_message(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1130 {
1131    Ecore_X_Event_Client_Message *e;
1132    E_Border *bd;
1133
1134    e = ev;
1135
1136    if (e->message_type == ECORE_X_ATOM_NET_ACTIVE_WINDOW)
1137      {
1138         bd = e_border_find_by_client_window(e->win);
1139         if ((bd) && (!bd->focused))
1140           {
1141 #if 0 /* notes */
1142              if (e->data.l[0] == 0 /* 0 == old, 1 == client, 2 == pager */)
1143                {
1144                   // FIXME: need config for the below - what to do given each
1145                   //  request (either do nothng, make app look urgent/want
1146                   //  attention or actiually flip to app as below is the
1147                   //  current default)
1148                   // if 0 == just make app demand attention somehow
1149                   // if 1 == just make app demand attention somehow
1150                   // if 2 == activate window as below
1151                }
1152              timestamp = e->data.l[1];
1153              requestor_id e->data.l[2];
1154 #endif
1155
1156 #ifdef _F_WINDOW_GROUP_RAISE_
1157              if (e->data.l[0] == 3) // 'e->data.l[0] == 3' means group raise
1158                {
1159                   if (bd->client.icccm.client_leader)
1160                     {
1161                        _e_manager_windows_group_raise (bd);
1162                        return ECORE_CALLBACK_PASS_ON;
1163                     }
1164                }
1165 #endif
1166
1167
1168 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1169              if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
1170                  (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
1171                  ((bd->parent) &&
1172                   ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
1173                    ((bd->parent->focused) &&
1174                             (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))))
1175 #else // original
1176              if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
1177                  ((bd->parent) &&
1178                   ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
1179                    ((bd->parent->focused) &&
1180                     (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))))
1181 #endif
1182                {
1183                   if (bd->iconic)
1184                     {
1185                        if (e_config->clientlist_warp_to_iconified_desktop == 1)
1186                          e_desk_show(bd->desk);
1187
1188                        if (!bd->lock_user_iconify)
1189                          e_border_uniconify(bd);
1190                     }
1191                   if ((!bd->iconic) && (!bd->sticky))
1192                     e_desk_show(bd->desk);
1193                   if (!bd->lock_user_stacking) e_border_raise(bd);
1194                   if (!bd->lock_focus_out)
1195                     {
1196                        /* XXX ooffice does send this request for
1197                        config dialogs when the main window gets focus.
1198                        causing the pointer to jump back and forth.  */
1199                        if ((e_config->focus_policy != E_FOCUS_CLICK) &&
1200                            !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
1201                          ecore_x_pointer_warp(bd->zone->container->win,
1202                                               bd->x + (bd->w / 2), bd->y + (bd->h / 2));
1203 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1204                        if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
1205                          e_border_focus_set(bd, 1, 1);
1206                        else
1207                          {
1208                             Eina_List* l = NULL;
1209                             E_Border* temp_bd = NULL;
1210                             E_Border_List *bl;
1211
1212                             bl = e_container_border_list_last(bd->zone->container);
1213                             while ((temp_bd = e_container_border_list_prev(bl)))
1214                               {
1215                                  if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
1216                                      (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
1217                                      (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
1218                                      (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
1219                                      (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
1220                                      (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
1221                                      (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
1222                                    {
1223                                       if (bd == temp_bd)
1224                                         {
1225                                            e_border_focus_set(bd, 1, 1);
1226                                         }
1227                                       break;
1228                                    }
1229                               }
1230                             e_container_border_list_free(bl);
1231                          }
1232 #else // original
1233                        e_border_focus_set(bd, 1, 1);
1234 #endif
1235                     }
1236                }
1237           }
1238      }
1239
1240    return ECORE_CALLBACK_PASS_ON;
1241 }
1242
1243 static Eina_Bool
1244 _e_manager_frame_extents_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__,
1245                                  void *data, void *fdata __UNUSED__)
1246 {
1247    free(data);
1248    return EINA_TRUE;
1249 }
1250
1251 static E_Manager *
1252 _e_manager_get_for_root(Ecore_X_Window root)
1253 {
1254    Eina_List *l;
1255    E_Manager *man;
1256
1257    if (!managers) return NULL;
1258    EINA_LIST_FOREACH(managers, l, man)
1259      {
1260         if (man->root == root)
1261           return man;
1262      }
1263    return eina_list_data_get(managers);
1264 }
1265
1266
1267 #if 0 /* use later - maybe */
1268 static int _e_manager_cb_window_destroy(void *data, int ev_type, void *ev){return 1;}
1269 static int _e_manager_cb_window_hide(void *data, int ev_type, void *ev){return 1;}
1270 static int _e_manager_cb_window_reparent(void *data, int ev_type, void *ev){return 1;}
1271 static int _e_manager_cb_window_create(void *data, int ev_type, void *ev){return 1;}
1272 static int _e_manager_cb_window_configure_request(void *data, int ev_type, void *ev){return 1;}
1273 static int _e_manager_cb_window_configure(void *data, int ev_type, void *ev){return 1;}
1274 static int _e_manager_cb_window_gravity(void *data, int ev_type, void *ev){return 1;}
1275 static int _e_manager_cb_window_stack(void *data, int ev_type, void *ev){return 1;}
1276 static int _e_manager_cb_window_stack_request(void *data, int ev_type, void *ev){return 1;}
1277 static int _e_manager_cb_window_property(void *data, int ev_type, void *ev){return 1;}
1278 static int _e_manager_cb_window_colormap(void *data, int ev_type, void *ev){return 1;}
1279 static int _e_manager_cb_window_shape(void *data, int ev_type, void *ev){return 1;}
1280 #endif