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