update for beta release
[framework/uifw/e17.git] / src / modules / pager / e_mod_main.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 /* gadcon requirements */
5 static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
6 static void _gc_shutdown(E_Gadcon_Client *gcc);
7 static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient __UNUSED__);
8 static const char *_gc_label(E_Gadcon_Client_Class *client_class __UNUSED__);
9 static Evas_Object *_gc_icon(E_Gadcon_Client_Class *client_class __UNUSED__, Evas *evas);
10 static const char *_gc_id_new(E_Gadcon_Client_Class *client_class __UNUSED__);
11
12 /* and actually define the gadcon class that this module provides (just 1) */
13 static const E_Gadcon_Client_Class _gadcon_class =
14 {
15    GADCON_CLIENT_CLASS_VERSION,
16      "pager",
17      {
18         _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
19         e_gadcon_site_is_not_toolbar
20      },
21    E_GADCON_CLIENT_STYLE_INSET
22 };
23
24 /* actual module specifics */
25 typedef struct _Instance Instance;
26 typedef struct _Pager Pager;
27 typedef struct _Pager_Desk Pager_Desk;
28 typedef struct _Pager_Win Pager_Win;
29 typedef struct _Pager_Popup Pager_Popup;
30
31 struct _Instance
32 {
33    E_Gadcon_Client *gcc;
34    Evas_Object *o_pager; /* table */
35    Pager *pager;
36 };
37
38 struct _Pager
39 {
40    Instance *inst;
41    E_Drop_Handler *drop_handler;
42    Pager_Popup *popup;
43    Evas_Object *o_table;
44    E_Zone *zone;
45    int xnum, ynum;
46    Eina_List *desks;
47    unsigned char dragging : 1;
48    unsigned char just_dragged : 1;
49    Evas_Coord dnd_x, dnd_y;
50    Pager_Desk *active_drop_pd;
51 };
52
53 struct _Pager_Desk
54 {
55    Pager *pager;
56    E_Desk *desk;
57    Eina_List *wins;
58    Evas_Object *o_desk;
59    Evas_Object *o_layout;
60    int xpos, ypos, urgent;
61    int current : 1;
62    struct 
63      {
64         Pager *from_pager;
65         unsigned char in_pager : 1;
66         unsigned char start : 1;
67         int x, y, dx, dy, button;
68      } drag;
69 };
70
71 struct _Pager_Win
72 {
73    E_Border *border;
74    Pager_Desk *desk;
75    Evas_Object *o_window;
76    Evas_Object *o_icon;
77    unsigned char skip_winlist : 1;
78    struct 
79      {
80         Pager *from_pager;
81         unsigned char start : 1;
82         unsigned char in_pager : 1;
83         unsigned char no_place : 1;
84         unsigned char desktop  : 1;
85         int x, y, dx, dy, button;
86      } drag;
87 };
88
89 struct _Pager_Popup
90 {
91    E_Popup *popup;
92    Pager *pager;
93    Evas_Object *o_bg;
94    Ecore_Timer *timer;
95    unsigned char urgent : 1;
96 };
97
98 static void _pager_cb_obj_moveresize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__);
99 static void _button_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
100 static void _menu_cb_post(void *data __UNUSED__, E_Menu *m __UNUSED__);
101 static void _pager_inst_cb_menu_configure(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__);
102 static void _pager_inst_cb_menu_virtual_desktops_dialog(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__);
103 static void _pager_instance_drop_zone_recalc(Instance *inst);
104 static Eina_Bool _pager_cb_event_border_resize(void *data __UNUSED__, int type __UNUSED__, void *event);
105 static Eina_Bool _pager_cb_event_border_move(void *data __UNUSED__, int type __UNUSED__, void *event);
106 static Eina_Bool _pager_cb_event_border_add(void *data __UNUSED__, int type __UNUSED__, void *event);
107 static Eina_Bool _pager_cb_event_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event);
108 static Eina_Bool _pager_cb_event_border_iconify(void *data __UNUSED__, int type __UNUSED__, void *event);
109 static Eina_Bool _pager_cb_event_border_uniconify(void *data __UNUSED__, int type __UNUSED__, void *event);
110 static Eina_Bool _pager_cb_event_border_stick(void *data __UNUSED__, int type __UNUSED__, void *event);
111 static Eina_Bool _pager_cb_event_border_unstick(void *data __UNUSED__, int type __UNUSED__, void *event);
112 static Eina_Bool _pager_cb_event_border_desk_set(void *data __UNUSED__, int type __UNUSED__, void *event);
113 static Eina_Bool _pager_cb_event_border_stack(void *data __UNUSED__, int type __UNUSED__, void *event);
114 static Eina_Bool _pager_cb_event_border_icon_change(void *data __UNUSED__, int type __UNUSED__, void *event);
115 static Eina_Bool _pager_cb_event_border_urgent_change(void *data __UNUSED__, int type __UNUSED__, void *event);
116 static Eina_Bool _pager_cb_event_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event);
117 static Eina_Bool _pager_cb_event_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event);
118 static Eina_Bool _pager_cb_event_border_property(void *data __UNUSED__, int type __UNUSED__, void *event);
119 static Eina_Bool _pager_cb_event_zone_desk_count_set(void *data __UNUSED__, int type __UNUSED__, void *event);
120 static Eina_Bool _pager_cb_event_desk_show(void *data __UNUSED__, int type __UNUSED__, void *event);
121 static Eina_Bool _pager_cb_event_desk_name_change(void *data __UNUSED__, int type __UNUSED__, void *event);
122 static Eina_Bool _pager_cb_event_container_resize(void *data __UNUSED__, int type __UNUSED__, void *event);
123 static void _pager_window_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
124 static void _pager_window_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
125 static void _pager_window_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
126 static void *_pager_window_cb_drag_convert(E_Drag *drag, const char *type);
127 static void _pager_window_cb_drag_finished(E_Drag *drag, int dropped);
128 static void _pager_drop_cb_enter(void *data, const char *type __UNUSED__, void *event_info);
129 static void _pager_drop_cb_move(void *data, const char *type __UNUSED__, void *event_info);
130 static void _pager_drop_cb_leave(void *data, const char *type __UNUSED__, void *event_info __UNUSED__);
131 static void _pager_drop_cb_drop(void *data, const char *type, void *event_info);
132 static void _pager_inst_cb_scroll(void *data);
133 static void _pager_update_drop_position(Pager *p, Evas_Coord x, Evas_Coord y);
134 static void _pager_desk_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
135 static void _pager_desk_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
136 static void _pager_desk_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
137 static void _pager_desk_cb_drag_finished(E_Drag *drag, int dropped);
138 static void _pager_desk_cb_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
139 static Eina_Bool _pager_popup_cb_timeout(void *data);
140 static Pager *_pager_new(Evas *evas, E_Zone *zone);
141 static void _pager_free(Pager *p);
142 static void _pager_fill(Pager *p);
143 static void _pager_empty(Pager *p);
144 static Pager_Desk *_pager_desk_new(Pager *p, E_Desk *desk, int xpos, int ypos);
145 static void _pager_desk_free(Pager_Desk *pd);
146 static Pager_Desk *_pager_desk_at_coord(Pager *p, Evas_Coord x, Evas_Coord y);
147 static void _pager_desk_select(Pager_Desk *pd);
148 static Pager_Desk *_pager_desk_find(Pager *p, E_Desk *desk);
149 static void _pager_desk_switch(Pager_Desk *pd1, Pager_Desk *pd2);
150 static Pager_Win *_pager_window_new(Pager_Desk *pd, E_Border *border);
151 static void _pager_window_free(Pager_Win *pw);
152 static void _pager_window_move(Pager_Win *pw);
153 static Pager_Win *_pager_window_find(Pager *p, E_Border *border);
154 static Pager_Win *_pager_desk_window_find(Pager_Desk *pd, E_Border *border);
155 static Pager_Popup *_pager_popup_new(E_Zone *zone, int keyaction);
156 static void _pager_popup_free(Pager_Popup *pp);
157 static Pager_Popup *_pager_popup_find(E_Zone *zone);
158 static E_Config_Dialog *_pager_config_dialog(E_Container *con, const char *params);
159
160 /* functions for pager popup on key actions */
161 static int _pager_popup_show();
162 static void _pager_popup_hide(int switch_desk);
163 static Eina_Bool _pager_popup_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event);
164 static Eina_Bool _pager_popup_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event);
165 static Eina_Bool _pager_popup_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event);
166 static Eina_Bool _pager_popup_cb_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event);
167 static void _pager_popup_desk_switch(int x, int y);
168 static void _pager_popup_modifiers_set(int mod);
169 static Eina_Bool _pager_popup_cb_key_down(void *data __UNUSED__, int type __UNUSED__, void *event);
170 static Eina_Bool _pager_popup_cb_key_up(void *data __UNUSED__, int type __UNUSED__, void *event);
171 static void _pager_popup_cb_action_show(E_Object *obj __UNUSED__, const char *params __UNUSED__, Ecore_Event_Key *ev __UNUSED__);
172 static void _pager_popup_cb_action_switch(E_Object *obj __UNUSED__, const char *params, Ecore_Event_Key *ev);
173
174 /* variables for pager popup on key actions */
175 static E_Action *act_popup_show = NULL;
176 static E_Action *act_popup_switch = NULL;
177 static Ecore_X_Window input_window = 0;
178 static Eina_List *handlers = NULL;
179 static Pager_Popup *act_popup = NULL; /* active popup */
180 static int hold_count = 0;
181 static int hold_mod = 0;
182 static E_Desk *current_desk = NULL;
183 static E_Config_DD *conf_edd = NULL;
184 static Eina_List *pagers = NULL;
185
186 Config *pager_config = NULL;
187
188 static E_Gadcon_Client *
189 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
190 {
191    Pager *p;
192    Evas_Object *o;
193    E_Gadcon_Client *gcc;
194    Instance *inst;
195    Evas_Coord x, y, w, h;
196    const char *drop[] = 
197      { 
198         "enlightenment/pager_win", "enlightenment/border", 
199         "enlightenment/vdesktop"
200      };
201
202    inst = E_NEW(Instance, 1);
203
204    p = _pager_new(gc->evas, gc->zone);
205    p->inst = inst;
206    inst->pager = p;
207    o = p->o_table;
208    gcc = e_gadcon_client_new(gc, name, id, style, o);
209    gcc->data = inst;
210
211    inst->gcc = gcc;
212    inst->o_pager = o;
213
214    evas_object_geometry_get(o, &x, &y, &w, &h);
215    p->drop_handler =
216    e_drop_handler_add(E_OBJECT(inst->gcc), p,
217                       _pager_drop_cb_enter, _pager_drop_cb_move,
218                       _pager_drop_cb_leave, _pager_drop_cb_drop,
219                       drop, 3, x, y, w, h);
220    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
221                                   _pager_cb_obj_moveresize, inst);
222    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
223                                   _pager_cb_obj_moveresize, inst);
224    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
225                                   _button_cb_mouse_down, inst);
226    pager_config->instances = eina_list_append(pager_config->instances, inst);
227    return gcc;
228 }
229
230 static void
231 _gc_shutdown(E_Gadcon_Client *gcc)
232 {
233    Instance *inst;
234
235    inst = gcc->data;
236    pager_config->instances = eina_list_remove(pager_config->instances, inst);
237    e_drop_handler_del(inst->pager->drop_handler);
238    _pager_free(inst->pager);
239    E_FREE(inst);
240 }
241
242 static void
243 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient __UNUSED__)
244 {
245    Instance *inst;
246
247    inst = gcc->data;
248    e_gadcon_client_aspect_set(gcc,
249                               inst->pager->xnum * inst->pager->zone->w,
250                               inst->pager->ynum * inst->pager->zone->h);
251    e_gadcon_client_min_size_set(gcc, 16, 16);
252 }
253
254 static const char *
255 _gc_label(E_Gadcon_Client_Class *client_class __UNUSED__)
256 {
257    return _("Pager");
258 }
259
260 static Evas_Object *
261 _gc_icon(E_Gadcon_Client_Class *client_class __UNUSED__, Evas *evas)
262 {
263    Evas_Object *o;
264    char buf[PATH_MAX];
265
266    o = edje_object_add(evas);
267    snprintf(buf, sizeof(buf), "%s/e-module-pager.edj",
268             e_module_dir_get(pager_config->module));
269    edje_object_file_set(o, buf, "icon");
270    return o;
271 }
272
273 static const char *
274 _gc_id_new(E_Gadcon_Client_Class *client_class __UNUSED__)
275 {
276    return _gadcon_class.name;
277 }
278
279 static Pager *
280 _pager_new(Evas *evas, E_Zone *zone)
281 {
282    Pager *p;
283
284    p = E_NEW(Pager, 1);
285    p->inst = NULL;
286    p->popup = NULL;
287    p->o_table = e_table_add(evas);
288    e_table_homogenous_set(p->o_table, 1);
289    p->zone = zone;
290    _pager_fill(p);
291    pagers = eina_list_append(pagers, p);
292    return p;
293 }
294
295 static void
296 _pager_free(Pager *p)
297 {
298    _pager_empty(p);
299    evas_object_del(p->o_table);
300    pagers = eina_list_remove(pagers, p);
301    E_FREE(p);
302 }
303
304 static void
305 _pager_fill(Pager *p)
306 {
307    int x, y;
308
309    e_zone_desk_count_get(p->zone, &(p->xnum), &(p->ynum));
310    for (x = 0; x < p->xnum; x++)
311      {
312         for (y = 0; y < p->ynum; y++)
313           {
314              Pager_Desk *pd;
315              E_Desk *desk;
316
317              desk = e_desk_at_xy_get(p->zone, x, y);
318              pd = _pager_desk_new(p, desk, x, y);
319              if (pd)
320                {
321                   p->desks = eina_list_append(p->desks, pd);
322                   if (desk == e_desk_current_get(desk->zone))
323                     _pager_desk_select(pd);
324                }
325           }
326      }
327 }
328
329 static void
330 _pager_empty(Pager *p)
331 {
332    while (p->desks)
333      {
334         _pager_desk_free(p->desks->data);
335         p->desks = eina_list_remove_list(p->desks, p->desks);
336      }
337 }
338
339 static Pager_Desk *
340 _pager_desk_new(Pager *p, E_Desk *desk, int xpos, int ypos)
341 {
342    Pager_Desk *pd;
343    Evas_Object *o, *evo;
344    E_Border_List *bl;
345    E_Border *bd;
346
347    pd = E_NEW(Pager_Desk, 1);
348    if (!pd) return NULL;
349
350    pd->xpos = xpos;
351    pd->ypos = ypos;
352    pd->urgent = 0;
353    pd->desk = desk;
354    e_object_ref(E_OBJECT(desk));
355    pd->pager = p;
356
357    o = edje_object_add(evas_object_evas_get(p->o_table));
358    pd->o_desk = o;
359    e_theme_edje_object_set(o, "base/theme/modules/pager",
360                            "e/modules/pager/desk");
361    if (pager_config->show_desk_names)
362      edje_object_part_text_set(o, "e.text.label", desk->name);
363    else
364      edje_object_part_text_set(o, "e.text.label", "");
365
366    e_table_pack(p->o_table, o, xpos, ypos, 1, 1);
367    e_table_pack_options_set(o, 1, 1, 1, 1, 0.5, 0.5, 0, 0, -1, -1);
368
369    evo = (Evas_Object *)edje_object_part_object_get(o, "e.eventarea");
370    if (!evo) evo = o;
371
372    evas_object_event_callback_add(evo, EVAS_CALLBACK_MOUSE_DOWN,
373                                   _pager_desk_cb_mouse_down, pd);
374    evas_object_event_callback_add(evo, EVAS_CALLBACK_MOUSE_UP,
375                                   _pager_desk_cb_mouse_up, pd);
376    evas_object_event_callback_add(evo, EVAS_CALLBACK_MOUSE_MOVE,
377                                   _pager_desk_cb_mouse_move, pd);
378    evas_object_event_callback_add(evo, EVAS_CALLBACK_MOUSE_WHEEL,
379                                   _pager_desk_cb_mouse_wheel, pd);
380    evas_object_show(o);
381
382    o = e_layout_add(evas_object_evas_get(p->o_table));
383    pd->o_layout = o;
384
385    e_layout_virtual_size_set(o, desk->zone->w, desk->zone->h);
386    edje_object_part_swallow(pd->o_desk, "e.swallow.content", pd->o_layout);
387    evas_object_show(o);
388
389    bl = e_container_border_list_first(desk->zone->container);
390    while ((bd = e_container_border_list_next(bl)))
391      {
392         Pager_Win *pw;
393
394         if ((bd->new_client) || ((bd->desk != desk) && (!bd->sticky))) 
395           continue;
396         pw = _pager_window_new(pd, bd);
397         if (pw) pd->wins = eina_list_append(pd->wins, pw);
398      }
399    e_container_border_list_free(bl);
400    return pd;
401 }
402
403 static void
404 _pager_desk_free(Pager_Desk *pd)
405 {
406    Pager_Win *w;
407
408    evas_object_del(pd->o_desk);
409    evas_object_del(pd->o_layout);
410    EINA_LIST_FREE(pd->wins, w)
411      _pager_window_free(w);
412    e_object_unref(E_OBJECT(pd->desk));
413    E_FREE(pd);
414 }
415
416 static Pager_Desk *
417 _pager_desk_at_coord(Pager *p, Evas_Coord x, Evas_Coord y)
418 {
419    Eina_List *l;
420    Pager_Desk *pd;
421
422    EINA_LIST_FOREACH(p->desks, l, pd)
423      {
424         Evas_Coord dx, dy, dw, dh;
425
426         evas_object_geometry_get(pd->o_desk, &dx, &dy, &dw, &dh);
427         if (E_INSIDE(x, y, dx, dy, dw, dh)) return pd;
428      }
429    return NULL;
430 }
431
432 static void
433 _pager_desk_select(Pager_Desk *pd)
434 {
435    Eina_List *l;
436    Pager_Desk *pd2;
437
438    if (pd->current) return;
439
440    EINA_LIST_FOREACH(pd->pager->desks, l, pd2)
441      {
442         if (pd == pd2)
443           {
444              pd2->current = 1;
445              evas_object_raise(pd2->o_desk);
446              edje_object_signal_emit(pd2->o_desk, "e,state,selected", "e");
447           }
448         else
449           {
450              if (pd2->current)
451                {
452                   pd2->current = 0;
453                   edje_object_signal_emit(pd2->o_desk, "e,state,unselected", "e");
454                }
455           }
456      }
457 }
458
459 static Pager_Desk *
460 _pager_desk_find(Pager *p, E_Desk *desk)
461 {
462    Eina_List *l;
463    Pager_Desk *pd;
464
465    EINA_LIST_FOREACH(p->desks, l, pd)
466      if (pd->desk == desk) return pd;
467
468    return NULL;
469 }
470
471 static void
472 _pager_desk_switch(Pager_Desk *pd1, Pager_Desk *pd2)
473 {
474    int c;
475    E_Zone *zone1, *zone2;
476    E_Desk *desk1, *desk2;
477    Pager_Win *pw;
478    Eina_List *l;
479
480    if ((!pd1) || (!pd2) || (!pd1->desk) || (!pd2->desk)) return;
481    if (pd1 == pd2) return;
482
483    desk1 = pd1->desk;
484    desk2 = pd2->desk;
485    zone1 = pd1->desk->zone;
486    zone2 = pd2->desk->zone;
487
488    /* Move opened windows from on desk to the other */
489    EINA_LIST_FOREACH(pd1->wins, l, pw)
490      {
491         if ((!pw) || (!pw->border) || (pw->border->iconic)) continue;
492         e_border_desk_set(pw->border, desk2);
493      }
494    EINA_LIST_FOREACH(pd2->wins, l, pw)
495      {
496         if ((!pw) || (!pw->border) || (pw->border->iconic)) continue;
497         e_border_desk_set(pw->border, desk1);
498      }
499
500    /* Modify desktop names in the config */
501    for (l = e_config->desktop_names, c = 0; l && c < 2; l = l->next)
502      {
503         E_Config_Desktop_Name *tmp_dn;
504
505         tmp_dn = l->data;
506         if (!tmp_dn) continue;
507         if ((tmp_dn->desk_x == desk1->x) &&
508             (tmp_dn->desk_y == desk1->y) &&
509             (tmp_dn->zone == (int) desk1->zone->num))
510           {
511              tmp_dn->desk_x = desk2->x;
512              tmp_dn->desk_y = desk2->y;
513              tmp_dn->zone   = desk2->zone->num;
514              c++;
515           }
516         else if ((tmp_dn->desk_x == desk2->x) &&
517                  (tmp_dn->desk_y == desk2->y) &&
518                  (tmp_dn->zone == (int) desk2->zone->num))
519           {
520              tmp_dn->desk_x = desk1->x;
521              tmp_dn->desk_y = desk1->y;
522              tmp_dn->zone   = desk1->zone->num;
523              c++;
524           }
525      }
526    if (c > 0) e_config_save();
527    e_desk_name_update();
528
529    /* Modify desktop backgrounds in the config */
530    for (l = e_config->desktop_backgrounds, c = 0; l && c < 2; l = l->next)
531      {
532         E_Config_Desktop_Background *tmp_db;
533
534         tmp_db = l->data;
535         if (!tmp_db) continue;
536         if ((tmp_db->desk_x == desk1->x) &&
537             (tmp_db->desk_y == desk1->y) &&
538             (tmp_db->zone == (int) desk1->zone->num))
539           {
540              tmp_db->desk_x = desk2->x;
541              tmp_db->desk_y = desk2->y;
542              tmp_db->zone   = desk2->zone->num;
543              c++;
544           }
545         else if ((tmp_db->desk_x == desk2->x) &&
546                  (tmp_db->desk_y == desk2->y) &&
547                  (tmp_db->zone == (int) desk2->zone->num))
548           {
549              tmp_db->desk_x = desk1->x;
550              tmp_db->desk_y = desk1->y;
551              tmp_db->zone   = desk1->zone->num;
552              c++;
553           }
554      }
555    if (c > 0) e_config_save();
556
557    /* If the current desktop has been switched, force to update of the screen */
558    if (desk2 == e_desk_current_get(zone2))
559      {
560         desk2->visible = 0;
561         e_desk_show(desk2);
562      }
563    if (desk1 == e_desk_current_get(zone1))
564      {
565         desk1->visible = 0;
566         e_desk_show(desk1);
567      }
568 }
569
570 static Pager_Win  *
571 _pager_window_new(Pager_Desk *pd, E_Border *border)
572 {
573    Pager_Win *pw;
574    Evas_Object *o;
575    int visible;
576
577    if (!border) return NULL;
578    pw = E_NEW(Pager_Win, 1);
579    if (!pw) return NULL;
580
581    pw->border = border;
582    e_object_ref(E_OBJECT(border));
583
584    visible = ((!border->iconic) && (!border->client.netwm.state.skip_pager));
585    pw->skip_winlist = border->client.netwm.state.skip_pager;
586    pw->desk = pd;
587
588    o = edje_object_add(evas_object_evas_get(pd->pager->o_table));
589    pw->o_window = o;
590    e_theme_edje_object_set(o, "base/theme/modules/pager",
591                            "e/modules/pager/window");
592    if (visible) evas_object_show(o);
593
594    e_layout_pack(pd->o_layout, pw->o_window);
595    e_layout_child_raise(pw->o_window);
596
597    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, 
598                                   _pager_window_cb_mouse_down, pw);
599    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, 
600                                   _pager_window_cb_mouse_up, pw);
601    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, 
602                                   _pager_window_cb_mouse_move, pw);
603
604    o = e_border_icon_add(border, evas_object_evas_get(pd->pager->o_table));
605    if (o)
606      {
607         pw->o_icon = o;
608         evas_object_show(o);
609         edje_object_part_swallow(pw->o_window, "e.swallow.icon", o);
610      }
611
612    if (border->client.icccm.urgent && !border->focused)
613      {
614         if (!(border->iconic))
615           edje_object_signal_emit(pd->o_desk, "e,state,urgent", "e");
616         edje_object_signal_emit(pw->o_window, "e,state,urgent", "e");
617      }
618
619    evas_object_show(o);
620
621    _pager_window_move(pw);
622    return pw;
623 }
624
625 static void
626 _pager_window_free(Pager_Win *pw)
627 {
628    if ((pw->drag.from_pager) && (pw->desk->pager->dragging))
629      pw->desk->pager->dragging = 0;
630    if (pw->o_window) evas_object_del(pw->o_window);
631    if (pw->o_icon) evas_object_del(pw->o_icon);
632    e_object_unref(E_OBJECT(pw->border));
633    E_FREE(pw);
634 }
635
636 static void
637 _pager_window_move(Pager_Win *pw)
638 {
639    e_layout_child_move(pw->o_window, 
640                        pw->border->x - pw->border->zone->x, 
641                        pw->border->y - pw->border->zone->y);
642    e_layout_child_resize(pw->o_window, pw->border->w, pw->border->h);
643 }
644
645 static Pager_Win *
646 _pager_window_find(Pager *p, E_Border *border)
647 {
648    Eina_List  *l;
649    Pager_Desk *pd;
650
651    EINA_LIST_FOREACH(p->desks, l, pd)
652      {
653         Pager_Win *pw;
654
655         pw = _pager_desk_window_find(pd, border);
656         if (pw) return pw;
657      }
658    return NULL;
659 }
660
661 static Pager_Win *
662 _pager_desk_window_find(Pager_Desk *pd, E_Border *border)
663 {
664    Eina_List *l;
665    Pager_Win *pw;
666
667    EINA_LIST_FOREACH(pd->wins, l, pw)
668      if (pw->border == border) return pw;
669
670    return NULL;
671 }
672
673 static Pager_Popup *
674 _pager_popup_new(E_Zone *zone, int keyaction)
675 {
676    Pager_Popup *pp;
677    Evas_Coord w, h, zx, zy, zw, zh;
678    int x, y, height, width;
679    E_Desk *desk;
680
681    pp = E_NEW(Pager_Popup, 1);
682    if (!pp) return NULL;
683
684    /* Show popup */
685    pp->popup = e_popup_new(zone, 0, 0, 1, 1);
686    if (!pp->popup)
687      {
688         E_FREE(pp);
689         return NULL;
690      }
691    e_popup_layer_set(pp->popup, 255);
692
693    pp->pager = _pager_new(pp->popup->evas, zone);
694    pp->pager->popup = pp;
695    pp->urgent = 0;
696
697    e_zone_desk_count_get(zone, &x, &y);
698
699    if (keyaction)
700      height = pager_config->popup_act_height * y;
701    else
702      height = pager_config->popup_height * y;
703
704    width = height * (zone->w * x) / (zone->h * y);
705
706    evas_object_move(pp->pager->o_table, 0, 0);
707    evas_object_resize(pp->pager->o_table, width, height);
708
709    pp->o_bg = edje_object_add(pp->popup->evas);
710    e_theme_edje_object_set(pp->o_bg, "base/theme/modules/pager",
711                            "e/modules/pager/popup");
712    desk = e_desk_current_get(zone);
713    if (desk)
714      edje_object_part_text_set(pp->o_bg, "e.text.label", desk->name);
715    evas_object_show(pp->o_bg);
716
717    edje_extern_object_min_size_set(pp->pager->o_table, width, height);
718    edje_object_part_swallow(pp->o_bg, "e.swallow.content", pp->pager->o_table);
719    edje_object_size_min_calc(pp->o_bg, &w, &h);
720
721    evas_object_move(pp->o_bg, 0, 0);
722    evas_object_resize(pp->o_bg, w, h);
723    e_popup_edje_bg_object_set(pp->popup, pp->o_bg);
724    //e_popup_ignore_events_set(pp->popup, 1);
725    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
726    zx -= zone->x;
727    zy -= zone->y;
728    e_popup_move_resize(pp->popup,
729                        zx + ((zw - w) / 2), zy + ((zh - h) / 2), w, h);
730    e_bindings_mouse_grab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
731    e_bindings_wheel_grab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
732
733    e_popup_show(pp->popup);
734
735    pp->timer = NULL;
736
737    return pp;
738 }
739
740 static void
741 _pager_popup_free(Pager_Popup *pp)
742 {
743    if (pp->timer) ecore_timer_del(pp->timer);
744    evas_object_del(pp->o_bg);
745    _pager_free(pp->pager);
746    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
747    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
748    e_object_del(E_OBJECT(pp->popup));
749    E_FREE(pp);
750 }
751
752 static Pager_Popup *
753 _pager_popup_find(E_Zone *zone)
754 {
755    Eina_List *l;
756    Pager *p;
757
758    EINA_LIST_FOREACH(pagers, l, p)
759      if ((p->popup) && (p->zone == zone))
760        return p->popup;
761
762    return NULL;
763 }
764
765 static void
766 _pager_cb_obj_moveresize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
767 {
768    Instance *inst;
769
770    inst = data;
771    _pager_instance_drop_zone_recalc(inst);
772 }
773
774 static void
775 _button_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
776 {
777    Instance *inst;
778    Evas_Event_Mouse_Down *ev;
779
780    inst = data;
781    ev = event_info;
782    if ((ev->button == 3) && (!pager_config->menu))
783      {
784         E_Menu *m;
785         E_Menu_Item *mi;
786         int cx, cy;
787
788         m = e_menu_new();       
789         mi = e_menu_item_new(m);
790         e_menu_item_label_set(mi, _("Settings"));
791         e_util_menu_item_theme_icon_set(mi, "configure");
792         e_menu_item_callback_set(mi, _pager_inst_cb_menu_configure, NULL);
793
794         m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
795         e_menu_post_deactivate_callback_set(m, _menu_cb_post, inst);
796         pager_config->menu = m;
797
798         if (e_configure_registry_exists("screen/virtual_desktops"))
799           {
800              mi = e_menu_item_new_relative(m, NULL);
801              e_menu_item_label_set(mi, _("Virtual Desktops Settings"));
802              e_util_menu_item_theme_icon_set(mi, "preferences-desktop");
803              e_menu_item_callback_set(mi, _pager_inst_cb_menu_virtual_desktops_dialog, inst);
804           }
805
806         e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, 
807                                           NULL, NULL);
808         e_menu_activate_mouse(m,
809                               e_util_zone_current_get(e_manager_current_get()),
810                               cx + ev->output.x, cy + ev->output.y, 1, 1,
811                               E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
812      }
813 }
814
815 static void
816 _menu_cb_post(void *data __UNUSED__, E_Menu *m __UNUSED__)
817 {
818    if (!pager_config->menu) return;
819    e_object_del(E_OBJECT(pager_config->menu));
820    pager_config->menu = NULL;
821 }
822
823 static void
824 _pager_inst_cb_menu_configure(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
825 {
826    if (!pager_config) return;
827    if (pager_config->config_dialog) return;
828    /* FIXME: pass zone config item */
829    _config_pager_module(NULL);
830 }
831
832 static E_Config_Dialog *
833 _pager_config_dialog(E_Container *con __UNUSED__, const char *params __UNUSED__)
834 {
835    if (!pager_config) return NULL;
836    if (pager_config->config_dialog) return NULL;
837    /* FIXME: pass zone config item */
838    _config_pager_module(NULL);
839    return pager_config->config_dialog;
840 }
841
842 static void
843 _pager_inst_cb_menu_virtual_desktops_dialog(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
844 {
845    Instance *inst;
846
847    inst = data;
848    e_configure_registry_call("screen/virtual_desktops", 
849                              inst->gcc->gadcon->zone->container, NULL);
850 }
851
852 static void
853 _pager_instance_drop_zone_recalc(Instance *inst)
854 {
855    Evas_Coord x, y, w, h;
856
857    e_gadcon_client_viewport_geometry_get(inst->gcc, &x, &y, &w, &h);
858    e_drop_handler_geometry_set(inst->pager->drop_handler, x, y, w, h);
859 }
860
861 void
862 _pager_cb_config_updated(void)
863 {
864    if (!pager_config) return;
865 }
866
867 static Eina_Bool
868 _pager_cb_event_border_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
869 {
870    E_Event_Border_Resize *ev = event;
871    Eina_List *l, *l2;
872    Pager *p;
873
874    EINA_LIST_FOREACH(pagers, l, p)
875      {
876         Pager_Desk *pd;
877
878         if (p->zone != ev->border->zone) continue;
879         EINA_LIST_FOREACH(p->desks, l2, pd)
880           {
881              Pager_Win *pw;
882
883              pw = _pager_desk_window_find(pd, ev->border);
884              if (pw) _pager_window_move(pw);
885           }
886      }
887    return ECORE_CALLBACK_PASS_ON;
888 }
889
890 static Eina_Bool
891 _pager_cb_event_border_move(void *data __UNUSED__, int type __UNUSED__, void *event)
892 {
893    E_Event_Border_Move *ev = event;
894    Eina_List *l;
895    Pager_Win *pw;
896    Pager_Desk *pd;
897    Pager *p;
898
899    EINA_LIST_FOREACH(pagers, l, p)
900      {
901         Eina_List *l2;
902
903         if (p->zone != ev->border->zone) continue;
904         EINA_LIST_FOREACH(p->desks, l2, pd)
905           {
906              pw = _pager_desk_window_find(pd, ev->border);
907              if (pw) _pager_window_move(pw);
908           }
909      }
910
911    if ((act_popup) && (act_popup->pager->zone == ev->border->zone))
912      {
913         EINA_LIST_FOREACH(act_popup->pager->desks, l, pd)
914           {
915              pw = _pager_desk_window_find(pd, ev->border);
916              if (pw) _pager_window_move(pw);
917           }
918      }
919
920    return ECORE_CALLBACK_PASS_ON;
921 }
922
923 static Eina_Bool
924 _pager_cb_event_border_add(void *data __UNUSED__, int type __UNUSED__, void *event)
925 {
926    E_Event_Border_Add *ev = event;
927    Eina_List *l;
928    Pager *p;
929
930    EINA_LIST_FOREACH(pagers, l, p)
931      {
932         Pager_Desk *pd;
933         Pager_Win *pw;
934
935         if ((p->zone != ev->border->zone) ||
936             (_pager_window_find(p, ev->border)))
937           continue;
938         pd = _pager_desk_find(p, ev->border->desk);
939         if (!pd) continue;
940         pw = _pager_window_new(pd, ev->border);
941         if (pw) pd->wins = eina_list_append(pd->wins, pw);
942      }
943
944    return ECORE_CALLBACK_PASS_ON;
945 }
946
947 static Eina_Bool
948 _pager_cb_event_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event)
949 {
950    E_Event_Border_Remove *ev = event;
951    Eina_List *l;
952    Pager *p;
953
954    EINA_LIST_FOREACH(pagers, l, p)
955      {
956         Eina_List *l2;
957         Pager_Desk *pd;
958
959         if (p->zone != ev->border->zone) continue;
960
961         EINA_LIST_FOREACH(p->desks, l2, pd)
962           {
963              Pager_Win *pw;
964
965              pw = _pager_desk_window_find(pd, ev->border);
966              if (!pw) continue;
967              pd->wins = eina_list_remove(pd->wins, pw);
968              _pager_window_free(pw);
969           }
970      }
971    return ECORE_CALLBACK_PASS_ON;
972 }
973
974 static Eina_Bool
975 _pager_cb_event_border_iconify(void *data __UNUSED__, int type __UNUSED__, void *event)
976 {
977    E_Event_Border_Iconify *ev = event;
978    Eina_List *l;
979    Pager *p;
980
981    EINA_LIST_FOREACH(pagers, l, p)
982      {
983         Eina_List *l2;
984         Pager_Desk *pd;
985
986         if (p->zone != ev->border->zone) continue;
987
988         EINA_LIST_FOREACH(p->desks, l2, pd)
989           {
990              Pager_Win *pw;
991
992              pw = _pager_desk_window_find(pd, ev->border);
993              if (!pw) continue;
994              if ((pw->drag.from_pager) && (pw->desk->pager->dragging))
995                pw->desk->pager->dragging = 0;
996              evas_object_hide(pw->o_window);
997           }
998      }
999
1000    return ECORE_CALLBACK_PASS_ON;
1001 }
1002
1003 static Eina_Bool
1004 _pager_cb_event_border_uniconify(void *data __UNUSED__, int type __UNUSED__, void *event)
1005 {
1006    E_Event_Border_Uniconify *ev = event;
1007    Eina_List *l;
1008    Pager *p;
1009
1010    EINA_LIST_FOREACH(pagers, l, p)
1011      {
1012         Eina_List *l2;
1013         Pager_Desk *pd;
1014
1015         if (p->zone != ev->border->zone) continue;
1016
1017         EINA_LIST_FOREACH(p->desks, l2, pd)
1018           {
1019              Pager_Win *pw;
1020
1021              pw = _pager_desk_window_find(pd, ev->border);
1022              if ((pw) && (!pw->skip_winlist)) evas_object_show(pw->o_window);
1023           }
1024      }
1025
1026    return ECORE_CALLBACK_PASS_ON;
1027 }
1028
1029 static Eina_Bool
1030 _pager_cb_event_border_stick(void *data __UNUSED__, int type __UNUSED__, void *event)
1031 {
1032    E_Event_Border_Stick *ev = event;
1033    Eina_List *l;
1034    Pager *p;
1035
1036    EINA_LIST_FOREACH(pagers, l, p)
1037      {
1038         Eina_List *l2;
1039         Pager_Desk *pd;
1040         Pager_Win *pw;
1041
1042         if (p->zone != ev->border->zone) continue;
1043         pw = _pager_window_find(p, ev->border);
1044         if (!pw) continue;
1045
1046         EINA_LIST_FOREACH(p->desks, l2, pd)
1047           if (ev->border->desk != pd->desk)
1048             {
1049                pw = _pager_window_new(pd, ev->border);
1050                if (pw) pd->wins = eina_list_append(pd->wins, pw);
1051             }
1052      }
1053
1054    return ECORE_CALLBACK_PASS_ON;
1055 }
1056
1057 static Eina_Bool
1058 _pager_cb_event_border_unstick(void *data __UNUSED__, int type __UNUSED__, void *event)
1059 {
1060    E_Event_Border_Unstick *ev = event;
1061    Eina_List *l;
1062    Pager *p;
1063
1064    EINA_LIST_FOREACH(pagers, l, p)
1065      {
1066         Pager_Desk *pd;
1067         Eina_List *l2;
1068
1069         if (p->zone != ev->border->zone) continue;
1070
1071         EINA_LIST_FOREACH(p->desks, l2, pd)
1072           if (ev->border->desk != pd->desk)
1073             {
1074                Pager_Win *pw;
1075
1076                pw = _pager_desk_window_find(pd, ev->border);
1077                if (pw)
1078                  {
1079                     pd->wins = eina_list_remove(pd->wins, pw);
1080                     _pager_window_free(pw);
1081                  }
1082             }
1083      }
1084    return ECORE_CALLBACK_PASS_ON;
1085 }
1086
1087 static void
1088 _pager_window_desk_change(Pager *pager, E_Border *bd)
1089 {
1090    Eina_List *l;
1091    Pager_Win  *pw;
1092    Pager_Desk *pd;
1093
1094    /* if this pager is not for the zone of the border */
1095    if (pager->zone != bd->zone)
1096      {
1097         /* look at all desks in the pager */
1098         EINA_LIST_FOREACH(pager->desks, l, pd)
1099           {
1100              /* find this border in this desk */
1101              pw = _pager_desk_window_find(pd, bd);
1102              if (!pw) continue;
1103              /* if it is found - remove it. it does not belong in this
1104               * pager as it probably moves zones */
1105              pd->wins = eina_list_remove(pd->wins, pw);
1106              _pager_window_free(pw);
1107           }
1108         return;
1109      }
1110    /* and this pager zone is for this border */
1111    /* see if the window is in this pager at all */
1112    pw = _pager_window_find(pager, bd);
1113    if (pw)
1114      {
1115         /* is it sticky */
1116         if (bd->sticky)
1117           {
1118              /* if its sticky and in this pager - its already everywhere, so abort
1119               * doing anything else */
1120              return;
1121           }
1122         /* move it to the right desk */
1123         /* find the pager desk of the target desk */
1124         pd = _pager_desk_find(pager, bd->desk);
1125         if (pd)
1126           {
1127              Pager_Win *pw2 = NULL;
1128              E_Border *bd;
1129
1130              /* remove it from whatever desk it was on */
1131              pw->desk->wins = eina_list_remove(pw->desk->wins, pw);
1132              e_layout_unpack(pw->o_window);
1133
1134              /* add it to the one its MEANT to be on */
1135              pw->desk = pd;
1136              pd->wins = eina_list_append(pd->wins, pw);
1137              e_layout_pack(pd->o_layout, pw->o_window);
1138
1139              bd = e_util_desk_border_above(pw->border);
1140              if (bd)
1141                pw2 = _pager_desk_window_find(pd, bd);
1142              if (pw2)
1143                e_layout_child_lower_below(pw->o_window, pw2->o_window);
1144              else
1145                e_layout_child_raise(pw->o_window);
1146
1147              _pager_window_move(pw);
1148           }
1149      }
1150    /* the border isn't in this pager at all - it must have moved zones */
1151    else
1152      {
1153         if (!bd->sticky)
1154           {
1155              /* find the pager desk it needs to go to */
1156              pd = _pager_desk_find(pager, bd->desk);
1157              if (pd)
1158                {
1159                   /* create it and add it */
1160                   pw = _pager_window_new(pd, bd);
1161                   if (pw)
1162                     {
1163                        Pager_Win *pw2 = NULL;
1164                        E_Border *bd;
1165
1166                        pd->wins = eina_list_append(pd->wins, pw);
1167                        bd = e_util_desk_border_above(pw->border);
1168                        if (bd)
1169                          pw2 = _pager_desk_window_find(pd, bd);
1170                        if (pw2)
1171                          e_layout_child_lower_below(pw->o_window, pw2->o_window);
1172                        else
1173                          e_layout_child_raise(pw->o_window);
1174                        _pager_window_move(pw);
1175                     }
1176                }
1177           }
1178         else
1179           {
1180              /* go through all desks */
1181              EINA_LIST_FOREACH(pager->desks, l, pd)
1182                {
1183                   /* create it and add it */
1184                   pw = _pager_window_new(pd, bd);
1185                   if (pw)
1186                     {
1187                        Pager_Win *pw2 = NULL;
1188                        E_Border *bd;
1189
1190                        pd->wins = eina_list_append(pd->wins, pw);
1191                        bd = e_util_desk_border_above(pw->border);
1192                        if (bd)
1193                          pw2 = _pager_desk_window_find(pd, bd);
1194                        if (pw2)
1195                          e_layout_child_lower_below(pw->o_window, pw2->o_window);
1196                        else
1197                          e_layout_child_raise(pw->o_window);
1198                        _pager_window_move(pw);
1199                     }
1200                }
1201           }
1202      }
1203 }
1204
1205 static Eina_Bool
1206 _pager_cb_event_border_desk_set(void *data __UNUSED__, int type __UNUSED__, void *event)
1207 {
1208    E_Event_Border_Desk_Set *ev = event;
1209    Eina_List *l;
1210    Pager *p;
1211
1212    EINA_LIST_FOREACH(pagers, l, p)
1213      _pager_window_desk_change(p, ev->border);
1214
1215    return ECORE_CALLBACK_PASS_ON;
1216 }
1217
1218 static Eina_Bool
1219 _pager_cb_event_border_stack(void *data __UNUSED__, int type __UNUSED__, void *event)
1220 {
1221    E_Event_Border_Stack *ev = event;
1222    Eina_List *l;
1223    Pager *p;
1224
1225    EINA_LIST_FOREACH(pagers, l, p)
1226      {
1227         Eina_List *l2;
1228         Pager_Desk *pd;
1229
1230         if (p->zone != ev->border->zone) continue;
1231         EINA_LIST_FOREACH(p->desks, l2, pd)
1232           {
1233              Pager_Win *pw, *pw2 = NULL;
1234
1235              pw = _pager_desk_window_find(pd, ev->border);
1236              if (pw)
1237                {
1238                   if (ev->stack)
1239                     {
1240                        pw2 = _pager_desk_window_find(pd, ev->stack);
1241                        if (!pw2)
1242                          {
1243                             /* This border is on another desk... */
1244                             E_Border *bd = NULL;
1245
1246                             if (ev->type == E_STACKING_ABOVE)
1247                               bd = e_util_desk_border_below(ev->border);
1248                             else if (ev->type == E_STACKING_BELOW)
1249                               bd = e_util_desk_border_above(ev->border);
1250                             if (bd) pw2 = _pager_desk_window_find(pd, bd);
1251                          }
1252                     }
1253                   if (ev->type == E_STACKING_ABOVE)
1254                     {
1255                        if (pw2)
1256                          e_layout_child_raise_above(pw->o_window, pw2->o_window);
1257                        else
1258                          /* If we aren't above any window, we are at the bottom */
1259                          e_layout_child_lower(pw->o_window);
1260                     }
1261                   else if (ev->type == E_STACKING_BELOW)
1262                     {
1263                        if (pw2)
1264                          e_layout_child_lower_below(pw->o_window, pw2->o_window);
1265                        else
1266                          /* If we aren't below any window, we are at the top */
1267                          e_layout_child_raise(pw->o_window);
1268                     }
1269                }
1270           }
1271      }
1272
1273    return ECORE_CALLBACK_PASS_ON;
1274 }
1275
1276 static Eina_Bool
1277 _pager_cb_event_border_icon_change(void *data __UNUSED__, int type __UNUSED__, void *event)
1278 {
1279    E_Event_Border_Icon_Change *ev = event;
1280    Eina_List *l;
1281    Pager *p;
1282
1283    EINA_LIST_FOREACH(pagers, l, p)
1284      {
1285         Eina_List *l2;
1286         Pager_Desk *pd;
1287
1288         if (p->zone != ev->border->zone) continue;
1289         EINA_LIST_FOREACH(p->desks, l2, pd)
1290           {
1291              Pager_Win *pw;
1292
1293              pw = _pager_desk_window_find(pd, ev->border);
1294              if (pw)
1295                {
1296                   Evas_Object *o;
1297
1298                   if (pw->o_icon)
1299                     {
1300                        evas_object_del(pw->o_icon);
1301                        pw->o_icon = NULL;
1302                     }
1303                   o = e_border_icon_add(ev->border, 
1304                                         evas_object_evas_get(p->o_table));
1305                   if (o)
1306                     {
1307                        pw->o_icon = o;
1308                        evas_object_show(o);
1309                        edje_object_part_swallow(pw->o_window, 
1310                                                 "e.swallow.icon", o);
1311                     }
1312                }
1313           }
1314      }
1315
1316    return ECORE_CALLBACK_PASS_ON;
1317 }
1318
1319 static Eina_Bool
1320 _pager_cb_event_border_urgent_change(void *data __UNUSED__, int type __UNUSED__, void *event)
1321 {
1322    E_Event_Border_Urgent_Change *ev;
1323    Eina_List *l, *l2;
1324    Pager_Popup *pp;
1325    E_Zone *zone;
1326    int urgent;
1327    Pager *p;
1328    Pager_Desk *pd;
1329    Pager_Win *pw;
1330
1331    ev = event;
1332    zone = ev->border->zone;
1333    urgent = ev->border->client.icccm.urgent;
1334
1335    if (pager_config->popup_urgent && (pager_config->popup_urgent_focus ||
1336       (!pager_config->popup_urgent_focus && !ev->border->focused)))
1337      {
1338         pp = _pager_popup_find(zone);
1339
1340         if ((!pp) && (urgent) && !(ev->border->iconic))
1341           {
1342              pp = _pager_popup_new(zone, 0);
1343
1344              if ((pp) && (!pager_config->popup_urgent_stick))
1345                pp->timer = ecore_timer_add(pager_config->popup_urgent_speed,
1346                                            _pager_popup_cb_timeout, pp);
1347              if (pp) pp->urgent = 1;
1348           }
1349      }
1350
1351    EINA_LIST_FOREACH(pagers, l, p)
1352      {
1353         if (p->zone != zone) continue;
1354
1355         EINA_LIST_FOREACH(p->desks, l2, pd)
1356           {
1357              pw = _pager_desk_window_find(pd, ev->border);
1358              if (pw)
1359                {
1360                   if (urgent && !ev->border->focused)
1361                     {
1362                        if (!(ev->border->iconic))
1363                          {
1364                             if ((pd->pager) && (pd->pager->inst) && 
1365                                 (!pager_config->popup_urgent))
1366                               e_gadcon_urgent_show(pd->pager->inst->gcc->gadcon);
1367                             edje_object_signal_emit(pd->o_desk,
1368                                                     "e,state,urgent", "e");
1369                          }
1370                        edje_object_signal_emit(pw->o_window,
1371                                                "e,state,urgent", "e");
1372                     }
1373                   else
1374                     {
1375                        if (!(ev->border->iconic))
1376                          edje_object_signal_emit(pd->o_desk,
1377                                                  "e,state,not_urgent", "e");
1378                        edje_object_signal_emit(pw->o_window,
1379                                                "e,state,not_urgent", "e");
1380                     }
1381                }
1382           }
1383      }
1384
1385    return ECORE_CALLBACK_PASS_ON;
1386 }
1387
1388 static Eina_Bool
1389 _pager_cb_event_border_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
1390 {
1391    E_Event_Border_Focus_In *ev;
1392    Instance *inst;
1393    Eina_List *l, *l2;
1394    Pager_Popup *pp;
1395    Pager_Desk *pd;
1396    Pager_Win *pw;
1397    E_Zone *zone;
1398
1399    ev = event;
1400    zone = ev->border->zone;
1401
1402    EINA_LIST_FOREACH(pager_config->instances, l, inst)
1403      {
1404         if (inst->pager->zone != zone) continue;
1405
1406         EINA_LIST_FOREACH(inst->pager->desks, l2, pd)
1407           {
1408              pw = _pager_desk_window_find(pd, ev->border);
1409              if (pw)
1410                {
1411                   edje_object_signal_emit(pw->o_window,
1412                                           "e,state,focused", "e");
1413                   break;
1414                }
1415           }
1416      }
1417
1418    pp = _pager_popup_find(zone);
1419    if (!pp) return ECORE_CALLBACK_PASS_ON;
1420
1421    EINA_LIST_FOREACH(pp->pager->desks, l, pd)
1422      {
1423         pw = _pager_desk_window_find(pd, ev->border);
1424         if (pw)
1425           {
1426              edje_object_signal_emit(pw->o_window,
1427                                      "e,state,focused", "e");
1428              break;
1429           }
1430      }
1431
1432    return ECORE_CALLBACK_PASS_ON;
1433 }
1434
1435 static Eina_Bool
1436 _pager_cb_event_border_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
1437 {
1438    E_Event_Border_Focus_Out *ev;
1439    Eina_List *l;
1440    Pager_Popup *pp;
1441    Pager_Desk *pd;
1442    Pager_Win *pw;
1443    Instance *inst;
1444    E_Zone *zone;
1445
1446    ev = event;
1447    zone = ev->border->zone;
1448
1449    EINA_LIST_FOREACH(pager_config->instances, l, inst)
1450      {
1451         Eina_List *l2;
1452
1453         if (inst->pager->zone != zone) continue;
1454
1455         EINA_LIST_FOREACH(inst->pager->desks, l2, pd)
1456           {
1457              pw = _pager_desk_window_find(pd, ev->border);
1458              if (pw)
1459                {
1460                   edje_object_signal_emit(pw->o_window,
1461                                           "e,state,unfocused", "e");
1462                   break;
1463                }
1464           }
1465      }
1466
1467    pp = _pager_popup_find(zone);
1468    if (!pp) return ECORE_CALLBACK_PASS_ON;
1469
1470    EINA_LIST_FOREACH(pp->pager->desks, l, pd)
1471      {
1472         pw = _pager_desk_window_find(pd, ev->border);
1473         if (pw)
1474           {
1475              edje_object_signal_emit(pw->o_window,
1476                                      "e,state,unfocused", "e");
1477              break;
1478           }
1479      }
1480
1481    return ECORE_CALLBACK_PASS_ON;
1482 }
1483
1484 static Eina_Bool
1485 _pager_cb_event_border_property(void *data __UNUSED__, int type __UNUSED__, void *event)
1486 {
1487    E_Event_Border_Property *ev = event;
1488    Eina_List *l, *l2;
1489    int found = 0;
1490    Pager *p;
1491    Pager_Win *pw;
1492    Pager_Desk *pd;
1493
1494    EINA_LIST_FOREACH(pagers, l, p)
1495      {
1496         if (p->zone != ev->border->zone) continue;
1497
1498         EINA_LIST_FOREACH(p->desks, l2, pd)
1499           {
1500              pw = _pager_desk_window_find(pd, ev->border);
1501              if (pw)
1502                {
1503                   found = 1;
1504                   if (ev->border->client.netwm.state.skip_pager)
1505                     {
1506                        pd->wins = eina_list_remove(pd->wins, pw);
1507                        _pager_window_free(pw);
1508                     }
1509                }
1510           }
1511      }
1512    if (found) return ECORE_CALLBACK_PASS_ON;
1513
1514    /* If we did not find this window in the pager, then add it because
1515     * the skip_pager state may have changed to 1 */
1516    EINA_LIST_FOREACH(pagers, l, p)
1517      {
1518         if ((p->zone != ev->border->zone) ||
1519             (_pager_window_find(p, ev->border)))
1520           continue;
1521         if (!ev->border->sticky)
1522           {
1523              pd = _pager_desk_find(p, ev->border->desk);
1524              if (pd)
1525                {
1526                   Pager_Win *pw;
1527
1528                   pw = _pager_window_new(pd, ev->border);
1529                   if (pw)
1530                     {
1531                        Pager_Win *pw2 = NULL;
1532                        E_Border *bd;
1533
1534                        pd->wins = eina_list_append(pd->wins, pw);
1535                        bd = e_util_desk_border_above(pw->border);
1536                        if (bd)
1537                          pw2 = _pager_desk_window_find(pd, bd);
1538                        if (pw2)
1539                          e_layout_child_lower_below(pw->o_window, pw2->o_window);
1540                        else
1541                          e_layout_child_raise(pw->o_window);
1542                        _pager_window_move(pw);
1543                     }
1544                }
1545           }
1546         else
1547           {
1548              EINA_LIST_FOREACH(p->desks, l2, pd)
1549                {
1550                   pw = _pager_window_new(pd, ev->border);
1551                   if (pw)
1552                     {
1553                        Pager_Win *pw2 = NULL;
1554                        E_Border *bd;
1555
1556                        pd->wins = eina_list_append(pd->wins, pw);
1557                        bd = e_util_desk_border_above(pw->border);
1558                        if (bd)
1559                          pw2 = _pager_desk_window_find(pd, bd);
1560                        if (pw2)
1561                          e_layout_child_lower_below(pw->o_window, pw2->o_window);
1562                        else
1563                          e_layout_child_raise(pw->o_window);
1564                        _pager_window_move(pw);
1565                     }
1566                }
1567           }
1568      }
1569
1570    return ECORE_CALLBACK_PASS_ON;
1571 }
1572
1573 static Eina_Bool
1574 _pager_cb_event_zone_desk_count_set(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
1575 {
1576    Eina_List *l;
1577    Pager *p;
1578
1579    EINA_LIST_FOREACH(pagers, l, p)
1580      {
1581         _pager_empty(p);
1582         _pager_fill(p);
1583         if (p->inst) _gc_orient(p->inst->gcc, p->inst->gcc->gadcon->orient);
1584      }
1585
1586    return ECORE_CALLBACK_PASS_ON;
1587 }
1588
1589 static Eina_Bool
1590 _pager_cb_event_desk_show(void *data __UNUSED__, int type __UNUSED__, void *event)
1591 {
1592    E_Event_Desk_Show *ev = event;
1593    Eina_List *l;
1594    Pager *p;
1595    Pager_Popup *pp;
1596    Pager_Desk *pd;
1597
1598    EINA_LIST_FOREACH(pagers, l, p)
1599      {
1600         if (p->zone != ev->desk->zone) continue;
1601         pd = _pager_desk_find(p, ev->desk);
1602         if (pd) _pager_desk_select(pd);
1603
1604         if (p->popup)
1605           edje_object_part_text_set(p->popup->o_bg, "text", ev->desk->name);
1606      }
1607
1608    if ((pager_config->popup) && (!act_popup))
1609      {
1610         if ((pp = _pager_popup_find(ev->desk->zone)))
1611           ecore_timer_del(pp->timer);
1612         else
1613           pp = _pager_popup_new(ev->desk->zone, 0);
1614
1615         if (pp)
1616           {
1617              pp->timer = ecore_timer_add(pager_config->popup_speed,
1618                                          _pager_popup_cb_timeout, pp);
1619
1620              pd = _pager_desk_find(pp->pager, ev->desk);
1621              if (pd)
1622                {
1623                   _pager_desk_select(pd);
1624                   edje_object_part_text_set(pp->o_bg, "e.text.label",
1625                                             ev->desk->name);
1626                }
1627              ecore_timer_del(pp->timer);
1628              pp->timer = ecore_timer_add(pager_config->popup_speed,
1629                                          _pager_popup_cb_timeout, pp);
1630           }
1631      }
1632
1633    return ECORE_CALLBACK_PASS_ON;
1634 }
1635
1636 static Eina_Bool
1637 _pager_cb_event_desk_name_change(void *data __UNUSED__, int type __UNUSED__, void *event)
1638 {
1639    E_Event_Desk_Name_Change *ev = event;
1640    Eina_List *l;
1641    Pager *p;
1642
1643    EINA_LIST_FOREACH(pagers, l, p)
1644      {
1645         Pager_Desk *pd;
1646
1647         if (p->zone != ev->desk->zone) continue;
1648         pd = _pager_desk_find(p, ev->desk);
1649         if (pager_config->show_desk_names)
1650           {
1651              if (pd)
1652                edje_object_part_text_set(pd->o_desk, "e.text.label", 
1653                                          ev->desk->name);
1654           }
1655         else
1656           {
1657              if (pd)
1658                edje_object_part_text_set(pd->o_desk, "e.text.label", "");
1659           }
1660      }
1661
1662    return ECORE_CALLBACK_PASS_ON;
1663 }
1664
1665 static Eina_Bool
1666 _pager_cb_event_container_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
1667 {
1668    E_Event_Container_Resize *ev = event;
1669    Eina_List *l;
1670    Pager *p;
1671
1672    EINA_LIST_FOREACH(pagers, l, p)
1673      {
1674         Eina_List *l2;
1675         Pager_Desk *pd;
1676
1677         if (p->zone->container != ev->container) continue;
1678
1679         EINA_LIST_FOREACH(p->desks, l2, pd)
1680           e_layout_virtual_size_set(pd->o_layout, pd->desk->zone->w,
1681                                     pd->desk->zone->h);
1682
1683         if (p->inst) _gc_orient(p->inst->gcc, p->inst->gcc->gadcon->orient);
1684         /* TODO if (p->popup) */
1685      }
1686
1687    return ECORE_CALLBACK_PASS_ON;
1688 }
1689
1690 static void
1691 _pager_window_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1692 {
1693    Evas_Event_Mouse_Down *ev;
1694    Pager_Win *pw;
1695
1696    ev = event_info;
1697    pw = data;
1698
1699    if (!pw) return;
1700    if (pw->desk->pager->popup && !act_popup) return;
1701    if (!pw->desk->pager->popup && ev->button == 3) return;
1702    if (ev->button == (int) pager_config->btn_desk) return;
1703    if ((ev->button == (int) pager_config->btn_drag) ||
1704        (ev->button == (int) pager_config->btn_noplace))
1705      {
1706         Evas_Coord ox, oy;
1707
1708         evas_object_geometry_get(pw->o_window, &ox, &oy, NULL, NULL);
1709         pw->drag.in_pager = 1;
1710         pw->drag.x = ev->canvas.x;
1711         pw->drag.y = ev->canvas.y;
1712         pw->drag.dx = ox - ev->canvas.x;
1713         pw->drag.dy = oy - ev->canvas.y;
1714         pw->drag.start = 1;
1715         pw->drag.button = ev->button;
1716 #if 0
1717         /* FIXME: disable move in pager for now, as dropping in between
1718            desks causes lost window */
1719         pw->drag.no_place = 0;
1720         if (ev->button == pager_config->btn_noplace) pw->drag.no_place = 1;
1721 #else
1722         pw->drag.no_place = 1;
1723 #endif
1724      }
1725 }
1726
1727 static void
1728 _pager_window_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1729 {
1730    Evas_Event_Mouse_Up *ev;
1731    Pager_Win *pw;
1732    Pager *p;
1733
1734    ev = event_info;
1735    pw = data;
1736    if (!pw) return;
1737
1738    p = pw->desk->pager;
1739
1740    if (pw->desk->pager->popup && !act_popup) return;
1741    if (ev->button == (int) pager_config->btn_desk) return;
1742    if ((ev->button == (int) pager_config->btn_drag) ||
1743        (ev->button == (int) pager_config->btn_noplace))
1744      {
1745         if (!pw->drag.from_pager)
1746           {
1747              if (!pw->drag.start) p->just_dragged = 1;
1748              pw->drag.in_pager = 0;
1749              pw->drag.start = 0;
1750              p->dragging = 0;
1751           }
1752      }
1753 }
1754
1755 static void
1756 _pager_window_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1757 {
1758    Evas_Event_Mouse_Move *ev;
1759    Pager_Win *pw;
1760    E_Drag *drag;
1761    Evas_Object *o, *oo;
1762    Evas_Coord x, y, w, h;
1763    const char *drag_types[] = 
1764      { "enlightenment/pager_win", "enlightenment/border" };
1765    Evas_Coord dx, dy;
1766    unsigned int resist = 0;
1767    Evas_Coord mx, my, vx, vy;
1768    Pager_Desk *pd;
1769
1770    ev = event_info;
1771    pw = data;
1772
1773    if (!pw) return;
1774    if (pw->border->lock_user_location) return;
1775    if ((pw->desk->pager->popup) && (!act_popup)) return;
1776    /* prevent drag for a few pixels */
1777    if (pw->drag.start)
1778      {
1779         dx = pw->drag.x - ev->cur.output.x;
1780         dy = pw->drag.y - ev->cur.output.y;
1781         if ((pw->desk) && (pw->desk->pager))
1782           resist = pager_config->drag_resist;
1783
1784         if (((unsigned int) (dx * dx) + (unsigned int) (dy * dy)) <= 
1785             (resist * resist)) return;
1786
1787         pw->desk->pager->dragging = 1;
1788         pw->drag.start = 0;
1789      }
1790
1791    /* dragging this win around inside the pager */
1792    if (pw->drag.in_pager)
1793      {
1794         /* m for mouse */
1795         mx = ev->cur.canvas.x;
1796         my = ev->cur.canvas.y;
1797
1798         /* find desk at pointer */
1799         pd = _pager_desk_at_coord(pw->desk->pager, mx, my);
1800         if ((pd) && (!pw->drag.no_place))
1801           {
1802              int zx, zy;
1803
1804              e_zone_useful_geometry_get(pd->desk->zone, &zx, &zy, NULL, NULL);
1805              e_layout_coord_canvas_to_virtual(pd->o_layout,
1806                                               mx + pw->drag.dx,
1807                                               my + pw->drag.dy, &vx, &vy);
1808              if (pd != pw->desk)
1809                e_border_desk_set(pw->border, pd->desk);
1810              e_border_move(pw->border, vx + zx, vy + zy);
1811           }
1812         else
1813           {
1814              evas_object_geometry_get(pw->o_window, &x, &y, &w, &h);
1815              evas_object_hide(pw->o_window);
1816
1817              drag = e_drag_new(pw->desk->pager->zone->container,
1818                                x, y, drag_types, 2, pw, -1,
1819                                _pager_window_cb_drag_convert,
1820                                _pager_window_cb_drag_finished);
1821
1822              o = edje_object_add(drag->evas);
1823              e_theme_edje_object_set(o, "base/theme/modules/pager",
1824                                      "e/modules/pager/window");
1825              evas_object_show(o);
1826
1827              oo = e_border_icon_add(pw->border, drag->evas);
1828              if (oo)
1829                {
1830                   evas_object_show(oo);
1831                   edje_object_part_swallow(o, "e.swallow.icon", oo);
1832                }
1833
1834              e_drag_object_set(drag, o);
1835              e_drag_resize(drag, w, h);
1836              e_drag_start(drag, x - pw->drag.dx, y - pw->drag.dy);
1837
1838              /* this prevents the desk from switching on drags */
1839              pw->drag.from_pager = pw->desk->pager;
1840              pw->drag.from_pager->dragging = 1;
1841              pw->drag.in_pager = 0;
1842           }
1843      }
1844 }
1845
1846 static void *
1847 _pager_window_cb_drag_convert(E_Drag *drag, const char *type)
1848 {
1849    Pager_Win *pw;
1850
1851    pw = drag->data;
1852    if (!strcmp(type, "enlightenment/pager_win")) return pw;
1853    if (!strcmp(type, "enlightenment/border")) return pw->border;
1854    return NULL;
1855 }
1856
1857 static void
1858 _pager_window_cb_drag_finished(E_Drag *drag, int dropped)
1859 {
1860    Pager_Win *pw;
1861    E_Container *cont;
1862    E_Zone *zone;
1863    E_Desk *desk;
1864    int x, y, dx, dy;
1865
1866    pw = drag->data;
1867    if (!pw) return;
1868    evas_object_show(pw->o_window);
1869    if (!dropped)
1870      {
1871         int zx, zy, zw, zh;
1872
1873         /* wasn't dropped (on pager). move it to position of mouse on screen */
1874         cont = e_container_current_get(e_manager_current_get());
1875         zone = e_zone_current_get(cont);
1876         desk = e_desk_current_get(zone);
1877
1878         e_border_zone_set(pw->border, zone);
1879         e_border_desk_set(pw->border, desk);
1880
1881         ecore_x_pointer_last_xy_get(&x, &y);
1882
1883         dx = (pw->border->w / 2);
1884         dy = (pw->border->h / 2);
1885
1886         e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
1887
1888         /* offset so that center of window is on mouse, but keep within desk bounds */
1889         if (dx < x)
1890           {
1891              x -= dx;
1892              if ((pw->border->w < zw) &&
1893                  (x + pw->border->w > zx + zw))
1894                x -= x + pw->border->w - (zx + zw);
1895           }
1896         else x = 0;
1897
1898         if (dy < y)
1899           {
1900              y -= dy;
1901              if ((pw->border->h < zh) &&
1902                  (y + pw->border->h > zy + zh))
1903                y -= y + pw->border->h - (zy + zh);
1904           }
1905         else y = 0;
1906         e_border_move(pw->border, x, y);
1907
1908         if (!(pw->border->lock_user_stacking)) e_border_raise(pw->border);
1909      }
1910    if (pw->drag.from_pager) pw->drag.from_pager->dragging = 0;
1911    pw->drag.from_pager = NULL;
1912
1913   if (act_popup)
1914      {
1915         e_grabinput_get(input_window, 0, input_window);
1916         if (!hold_count) _pager_popup_hide(1);
1917      }
1918 }
1919
1920 static void
1921 _pager_inst_cb_scroll(void *data)
1922 {
1923    Pager *p;
1924
1925    p = data;
1926    _pager_update_drop_position(p, p->dnd_x, p->dnd_y);
1927 }
1928
1929 static void
1930 _pager_update_drop_position(Pager *p, Evas_Coord x, Evas_Coord y)
1931 {
1932    Pager_Desk *pd, *pd2;
1933    Eina_List *l;
1934
1935    p->dnd_x = x;
1936    p->dnd_y = y;
1937    pd = _pager_desk_at_coord(p, x, y);
1938    if (pd == p->active_drop_pd) return;
1939    for (l = p->desks; l; l = l->next)
1940      {
1941         pd2 = l->data;
1942         if (pd == pd2)
1943           edje_object_signal_emit(pd2->o_desk, "e,action,drag,in", "e");
1944         else if (pd2 == p->active_drop_pd)
1945           edje_object_signal_emit(pd2->o_desk, "e,action,drag,out", "e");
1946      }
1947    p->active_drop_pd = pd;
1948 }
1949
1950 static void
1951 _pager_drop_cb_enter(void *data, const char *type __UNUSED__, void *event_info)
1952 {
1953    E_Event_Dnd_Enter *ev;
1954    Pager *p;
1955
1956    ev = event_info;
1957    p = data;
1958
1959    /* FIXME this fixes a segv, but the case is not easy
1960     * reproduceable. this makes no sense either since
1961     * the same 'pager' is passed to e_drop_handler_add
1962     * and it works without this almost all the time.
1963     * so this must be an issue with e_dnd code... i guess */
1964    if (act_popup) p = act_popup->pager;
1965
1966    _pager_update_drop_position(p, ev->x, ev->y);
1967
1968    if (p->inst)
1969      {
1970         e_gadcon_client_autoscroll_cb_set(p->inst->gcc, _pager_inst_cb_scroll, p);
1971         e_gadcon_client_autoscroll_update(p->inst->gcc, ev->x, ev->y);
1972      }
1973 }
1974
1975 static void
1976 _pager_drop_cb_move(void *data, const char *type __UNUSED__, void *event_info)
1977 {
1978    E_Event_Dnd_Move *ev;
1979    Pager *p;
1980
1981    ev = event_info;
1982    p = data;
1983
1984    if (act_popup) p = act_popup->pager;
1985
1986    _pager_update_drop_position(p, ev->x, ev->y);
1987
1988    if (p->inst)
1989      e_gadcon_client_autoscroll_update(p->inst->gcc, ev->x, ev->y);
1990 }
1991
1992 static void
1993 _pager_drop_cb_leave(void *data, const char *type __UNUSED__, void *event_info __UNUSED__)
1994 {
1995    Pager *p;
1996    Eina_List *l;
1997
1998    p = data;
1999
2000    if (act_popup) p = act_popup->pager;
2001
2002    for (l = p->desks; l && p->active_drop_pd; l = l->next)
2003      {
2004         Pager_Desk *pd;
2005
2006         pd = l->data;
2007         if (pd == p->active_drop_pd)
2008           {
2009              edje_object_signal_emit(pd->o_desk, "e,action,drag,out", "e");
2010              p->active_drop_pd = NULL;
2011           }
2012      }
2013
2014    if (p->inst) e_gadcon_client_autoscroll_cb_set(p->inst->gcc, NULL, NULL);
2015 }
2016
2017 static void
2018 _pager_drop_cb_drop(void *data, const char *type, void *event_info)
2019 {
2020    E_Event_Dnd_Drop *ev;
2021    Pager_Desk *pd;
2022    Pager_Desk *pd2 = NULL;
2023    E_Border *bd = NULL;
2024    Eina_List *l;
2025    int dx = 0, dy = 0;
2026    Pager_Win *pw = NULL;
2027    Evas_Coord wx, wy, wx2, wy2;
2028    Evas_Coord nx, ny;
2029    Pager *p;
2030
2031    ev = event_info;
2032    p = data;
2033
2034    if (act_popup) p = act_popup->pager;
2035
2036    pd = _pager_desk_at_coord(p, ev->x, ev->y);
2037    if (pd)
2038      {
2039         if (!strcmp(type, "enlightenment/pager_win"))
2040           {
2041              pw = (Pager_Win *)(ev->data);
2042              if (pw)
2043                {
2044                   bd = pw->border;
2045                   dx = pw->drag.dx;
2046                   dy = pw->drag.dy;
2047                }
2048           }
2049         else if (!strcmp(type, "enlightenment/border"))
2050           {
2051              bd = ev->data;
2052              e_layout_coord_virtual_to_canvas(pd->o_layout, bd->x, bd->y, 
2053                                               &wx, &wy);
2054              e_layout_coord_virtual_to_canvas(pd->o_layout, bd->x + bd->w, 
2055                                               bd->y + bd->h, &wx2, &wy2);
2056              dx = (wx - wx2) / 2;
2057              dy = (wy - wy2) / 2;
2058           }
2059         else if (!strcmp(type, "enlightenment/vdesktop"))
2060           {
2061              pd2 = ev->data;
2062              if (!pd2) return;
2063              _pager_desk_switch(pd, pd2);
2064           }
2065         else
2066           return;
2067
2068         if (bd)
2069           {
2070              if (bd->iconic) e_border_uniconify(bd);
2071              e_border_desk_set(bd, pd->desk);
2072              if ((!pw) || ((pw) && (!pw->drag.no_place)))
2073                {
2074                   int zx, zy;
2075
2076                   e_layout_coord_canvas_to_virtual(pd->o_layout,
2077                                                    ev->x + dx,
2078                                                    ev->y + dy,
2079                                                    &nx, &ny);
2080                   e_zone_useful_geometry_get(pd->desk->zone,
2081                                              &zx, &zy, NULL, NULL);
2082
2083                   e_border_move(bd, nx + zx, ny + zy);
2084                }
2085           }
2086      }
2087
2088    for (l = p->desks; l && p->active_drop_pd; l = l->next)
2089      {
2090         pd = l->data;
2091         if (pd == p->active_drop_pd)
2092           {
2093              edje_object_signal_emit(pd->o_desk, "e,action,drag,out", "e");
2094              p->active_drop_pd = NULL;
2095           }
2096      }
2097
2098    if (p->inst) e_gadcon_client_autoscroll_cb_set(p->inst->gcc, NULL, NULL);
2099 }
2100
2101 static void
2102 _pager_desk_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2103 {
2104    Evas_Event_Mouse_Down *ev;
2105    Pager_Desk *pd;
2106    Evas_Coord ox, oy;
2107
2108    ev = event_info;
2109    pd = data;
2110    if (!pd) return;
2111    if ((!pd->pager->popup) && (ev->button == 3)) return;
2112    if (ev->button == (int) pager_config->btn_desk)
2113      {
2114         evas_object_geometry_get(pd->o_desk, &ox, &oy, NULL, NULL);
2115         pd->drag.start = 1;
2116         pd->drag.in_pager = 1;
2117         pd->drag.dx = ox - ev->canvas.x;
2118         pd->drag.dy = oy - ev->canvas.y;
2119         pd->drag.x = ev->canvas.x;
2120         pd->drag.y = ev->canvas.y;
2121         pd->drag.button = ev->button;
2122      }
2123 }
2124
2125 static void
2126 _pager_desk_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2127 {
2128    Evas_Event_Mouse_Up *ev;
2129    Pager_Desk *pd;
2130    Pager *p;
2131
2132    ev = event_info;
2133    pd = data;
2134
2135    if (!pd) return;
2136    p = pd->pager;
2137
2138    /* FIXME: pd->pager->dragging is 0 when finishing a drag from desk to desk */
2139    if ((ev->button == 1) && (!pd->pager->dragging) &&
2140        (!pd->pager->just_dragged))
2141      {
2142         current_desk = pd->desk;
2143         e_desk_show(pd->desk);
2144         pd->drag.start = 0;
2145         pd->drag.in_pager = 0;
2146      }
2147    pd->pager->just_dragged = 0;
2148
2149    if ((p->popup) && (p->popup->urgent)) _pager_popup_free(p->popup);
2150 }
2151
2152 static void
2153 _pager_desk_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2154 {
2155    Evas_Event_Mouse_Move *ev;
2156    Pager_Desk *pd;
2157    Evas_Coord dx, dy;
2158    unsigned int resist = 0;
2159    E_Drag *drag;
2160    Evas_Object *o, *oo, *o_icon;
2161    Evas_Coord x, y, w, h;
2162    const char *drag_types[] = { "enlightenment/vdesktop" };
2163    Pager_Win *pw;
2164    Eina_List *l;
2165
2166    ev = event_info;
2167
2168    pd = data;
2169    if (!pd) return;
2170    /* prevent drag for a few pixels */
2171    if (pd->drag.start)
2172      {
2173         dx = pd->drag.x - ev->cur.output.x;
2174         dy = pd->drag.y - ev->cur.output.y;
2175         if ((pd->pager) && (pd->pager->inst))
2176           resist = pager_config->drag_resist;
2177
2178         if (((unsigned int) (dx * dx) + (unsigned int) (dy * dy)) <= 
2179             (resist * resist)) return;
2180
2181         if (pd->pager) pd->pager->dragging = 1;
2182         pd->drag.start = 0;
2183      }
2184
2185    if (pd->drag.in_pager && pd->pager)
2186      {
2187         evas_object_geometry_get(pd->o_desk, &x, &y, &w, &h);
2188         drag = e_drag_new(pd->pager->zone->container,
2189                           x, y, drag_types, 1, pd, -1,
2190                           NULL, _pager_desk_cb_drag_finished);
2191
2192         /* set a background to the drag icon */
2193         o = evas_object_rectangle_add(drag->evas);
2194         evas_object_color_set(o, 255, 255, 255, 255);
2195         evas_object_resize(o, w, h);
2196         evas_object_show(o);
2197
2198         /* redraw the desktop theme above */
2199         o = edje_object_add(drag->evas);
2200         e_theme_edje_object_set(o, "base/theme/modules/pager",
2201                                 "e/modules/pager/desk");
2202         evas_object_show(o);
2203         e_drag_object_set(drag, o);
2204
2205         /* and redraw is content */
2206         oo = e_layout_add(drag->evas);
2207         e_layout_virtual_size_set(oo, pd->pager->zone->w, pd->pager->zone->h);
2208         edje_object_part_swallow(o, "e.swallow.content", oo);
2209         evas_object_show(oo);
2210
2211         EINA_LIST_FOREACH(pd->wins, l, pw)
2212           {
2213              int zx, zy;
2214
2215              if ((!pw) || (pw->border->iconic)
2216                  || (pw->border->client.netwm.state.skip_pager))
2217                continue;
2218
2219              o = edje_object_add(drag->evas);
2220              e_theme_edje_object_set(o, "base/theme/modules/pager",
2221                                      "e/modules/pager/window");
2222              e_layout_pack(oo, o);
2223              e_layout_child_raise(o);
2224              e_zone_useful_geometry_get(pw->desk->desk->zone,
2225                                         &zx, &zy, NULL, NULL);
2226              e_layout_child_move(o, pw->border->x - zx, pw->border->y - zy);
2227              e_layout_child_resize(o, pw->border->w, pw->border->h);
2228              evas_object_show(o);
2229
2230              if ((o_icon = e_border_icon_add(pw->border, drag->evas)))
2231                {
2232                   evas_object_show(o_icon);
2233                   edje_object_part_swallow(o, "e.swallow.icon", o_icon);
2234                }
2235           }
2236         e_drag_resize(drag, w, h);
2237         e_drag_start(drag, x - pd->drag.dx, y - pd->drag.dy);
2238
2239         pd->drag.from_pager = pd->pager;
2240         pd->drag.from_pager->dragging = 1;
2241         pd->drag.in_pager = 0;
2242      }
2243 }
2244
2245 static void
2246 _pager_desk_cb_drag_finished(E_Drag *drag, int dropped)
2247 {
2248    Pager_Desk *pd;
2249    Pager_Desk *pd2 = NULL;
2250    Eina_List *l;
2251    E_Desk *desk;
2252    E_Zone *zone;
2253    Pager *p;
2254
2255    pd = drag->data;
2256    if (!pd) return;
2257    if (!dropped)
2258      {
2259         /* wasn't dropped on pager, switch with current desktop */
2260         if (!pd->desk) return;
2261         zone = e_util_zone_current_get(e_manager_current_get());
2262         desk = e_desk_current_get(zone);
2263         for (l = pagers; l && !pd2; l = l->next)
2264           {
2265              p = l->data;
2266              pd2 = _pager_desk_find(p, desk);
2267           }
2268         _pager_desk_switch(pd, pd2);
2269      }
2270    if (pd->drag.from_pager)
2271      {
2272         pd->drag.from_pager->dragging = 0;
2273         pd->drag.from_pager->just_dragged = 0;
2274      }
2275    pd->drag.from_pager = NULL;
2276
2277    if (act_popup)
2278      {
2279         e_grabinput_get(input_window, 0, input_window);
2280         if (!hold_count) _pager_popup_hide(1);
2281      }
2282 }
2283
2284 static void
2285 _pager_desk_cb_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2286 {
2287    Evas_Event_Mouse_Wheel *ev;
2288    Pager_Desk *pd;
2289
2290    ev = event_info;
2291    pd = data;
2292
2293    if (pd->pager->popup) return;
2294
2295    if (pager_config->flip_desk)
2296      e_zone_desk_linear_flip_by(pd->desk->zone, ev->z);
2297 }
2298
2299 static Eina_Bool
2300 _pager_popup_cb_timeout(void *data)
2301 {
2302    Pager_Popup *pp;
2303
2304    pp = data;
2305    pp->timer = NULL;
2306    _pager_popup_free(pp);
2307
2308    if (input_window)
2309      {
2310         ecore_x_window_free(input_window);
2311         e_grabinput_release(input_window, input_window);
2312         input_window = 0;
2313      }
2314
2315    return ECORE_CALLBACK_CANCEL;
2316 }
2317
2318 /************************************************************************/
2319 /* popup-on-keyaction functions */
2320 static int
2321 _pager_popup_show()
2322 {
2323    E_Zone *zone;
2324    int x, y, w, h;
2325    Pager_Popup *pp;
2326    const char *drop[] = 
2327      { 
2328         "enlightenment/pager_win", "enlightenment/border", 
2329         "enlightenment/vdesktop"
2330      };
2331
2332    if ((act_popup) || (input_window)) return 0;
2333
2334    zone = e_util_zone_current_get(e_manager_current_get());
2335
2336    pp = _pager_popup_find(zone);
2337    if (pp) _pager_popup_free(pp);
2338
2339    input_window = ecore_x_window_input_new(zone->container->win, 0, 0, 1, 1);
2340    ecore_x_window_show(input_window);
2341    if (!e_grabinput_get(input_window, 0, input_window))
2342      {
2343         ecore_x_window_free(input_window);
2344         input_window = 0;
2345         return 0;
2346      }
2347
2348    handlers = eina_list_append
2349      (handlers, ecore_event_handler_add
2350          (ECORE_EVENT_KEY_DOWN, _pager_popup_cb_key_down, NULL));
2351    handlers = eina_list_append
2352      (handlers, ecore_event_handler_add
2353          (ECORE_EVENT_KEY_UP, _pager_popup_cb_key_up, NULL));
2354    handlers = eina_list_append
2355      (handlers, ecore_event_handler_add
2356          (ECORE_EVENT_MOUSE_BUTTON_DOWN, _pager_popup_cb_mouse_down, NULL));
2357    handlers = eina_list_append
2358      (handlers, ecore_event_handler_add
2359          (ECORE_EVENT_MOUSE_BUTTON_UP, _pager_popup_cb_mouse_up, NULL));
2360    handlers = eina_list_append
2361      (handlers, ecore_event_handler_add
2362          (ECORE_EVENT_MOUSE_WHEEL, _pager_popup_cb_mouse_wheel, NULL));
2363    handlers = eina_list_append
2364      (handlers, ecore_event_handler_add
2365          (ECORE_EVENT_MOUSE_MOVE, _pager_popup_cb_mouse_move, NULL));
2366
2367    act_popup = _pager_popup_new(zone, 1);
2368
2369    e_popup_ignore_events_set(act_popup->popup, 1);
2370
2371    evas_object_geometry_get(act_popup->pager->o_table, &x, &y, &w, &h);
2372
2373    e_drop_handler_add(E_OBJECT(act_popup->popup), act_popup->pager,
2374                       _pager_drop_cb_enter, _pager_drop_cb_move,
2375                       _pager_drop_cb_leave, _pager_drop_cb_drop,
2376                       drop, 3, x, y, w, h);
2377
2378    e_bindings_key_grab(E_BINDING_CONTEXT_POPUP, act_popup->popup->evas_win);
2379
2380    evas_event_freeze(act_popup->popup->evas);
2381    evas_event_feed_mouse_in(act_popup->popup->evas, 
2382                             ecore_x_current_time_get(), NULL);
2383    evas_event_feed_mouse_move(act_popup->popup->evas, -1000000, -1000000, 
2384                               ecore_x_current_time_get(), NULL);
2385    evas_event_thaw(act_popup->popup->evas);
2386
2387    current_desk = e_desk_current_get(zone);
2388
2389    return 1;
2390 }
2391
2392 static void
2393 _pager_popup_hide(int switch_desk)
2394 {
2395    e_bindings_key_ungrab(E_BINDING_CONTEXT_POPUP, act_popup->popup->evas_win);
2396    hold_count = 0;
2397    hold_mod = 0;
2398    while (handlers)
2399      {
2400         ecore_event_handler_del(handlers->data);
2401         handlers = eina_list_remove_list(handlers, handlers);
2402      }
2403
2404    act_popup->timer = ecore_timer_add(0.1, _pager_popup_cb_timeout, act_popup);
2405
2406    if ((switch_desk) && (current_desk)) e_desk_show(current_desk);
2407
2408    act_popup = NULL;
2409 }
2410
2411 static void
2412 _pager_popup_modifiers_set(int mod)
2413 {
2414    if (!act_popup) return;
2415    hold_mod = mod;
2416    hold_count = 0;
2417    if (hold_mod & ECORE_EVENT_MODIFIER_SHIFT) hold_count++;
2418    if (hold_mod & ECORE_EVENT_MODIFIER_CTRL) hold_count++;
2419    if (hold_mod & ECORE_EVENT_MODIFIER_ALT) hold_count++;
2420    if (hold_mod & ECORE_EVENT_MODIFIER_WIN) hold_count++;
2421 }
2422
2423 static void
2424 _pager_popup_desk_switch(int x, int y)
2425 {
2426    int max_x,max_y, desk_x, desk_y;
2427    Pager_Desk *pd;
2428    Pager_Popup *pp = act_popup;
2429
2430    e_zone_desk_count_get(pp->pager->zone, &max_x, &max_y);
2431
2432    desk_x = current_desk->x + x;
2433    desk_y = current_desk->y + y;
2434
2435    if (desk_x < 0)
2436      desk_x = max_x - 1;
2437    else if (desk_x >= max_x)
2438      desk_x = 0;
2439
2440    if (desk_y < 0)
2441      desk_y = max_y - 1;
2442    else if (desk_y >= max_y)
2443      desk_y = 0;
2444
2445    current_desk = e_desk_at_xy_get(pp->pager->zone, desk_x, desk_y);
2446
2447    pd = _pager_desk_find(pp->pager, current_desk);
2448    if (pd) _pager_desk_select(pd);
2449
2450    edje_object_part_text_set(pp->o_bg, "e.text.label", current_desk->name);
2451 }
2452
2453 static void
2454 _pager_popup_cb_action_show(E_Object *obj __UNUSED__, const char *params __UNUSED__, Ecore_Event_Key *ev __UNUSED__)
2455 {
2456    if (_pager_popup_show())
2457      _pager_popup_modifiers_set(ev->modifiers);
2458 }
2459
2460 static void
2461 _pager_popup_cb_action_switch(E_Object *obj __UNUSED__, const char *params, Ecore_Event_Key *ev)
2462 {
2463    int max_x,max_y, desk_x;
2464    int x = 0, y = 0;
2465
2466    if (!act_popup)
2467      {
2468         if (_pager_popup_show())
2469           _pager_popup_modifiers_set(ev->modifiers);
2470         else
2471           return;
2472      }
2473
2474    e_zone_desk_count_get(act_popup->pager->zone, &max_x, &max_y);
2475    desk_x = current_desk->x /* + x <=this is always 0 */;
2476
2477    if (!strcmp(params, "left"))
2478      x = -1;
2479    else if (!strcmp(params, "right"))
2480      x = 1;
2481    else if (!strcmp(params, "up"))
2482      y = -1;
2483    else if (!strcmp(params, "down"))
2484      y = 1;
2485    else if (!strcmp(params, "next"))
2486      {
2487         x = 1;
2488         if (desk_x == max_x - 1)
2489           y = 1;
2490      }
2491    else if (!strcmp(params, "prev"))
2492      {
2493         x = -1;
2494         if (desk_x == 0)
2495           y = -1;
2496      }
2497    
2498    _pager_popup_desk_switch(x, y);
2499 }
2500
2501 static Eina_Bool
2502 _pager_popup_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event)
2503 {
2504    Ecore_Event_Mouse_Button *ev;
2505    Pager_Popup *pp = act_popup;
2506
2507    ev = event;
2508    if (ev->window != input_window) return ECORE_CALLBACK_PASS_ON;
2509
2510    evas_event_feed_mouse_down(pp->popup->evas, ev->buttons,
2511                               0, ev->timestamp, NULL);
2512    return ECORE_CALLBACK_PASS_ON;
2513 }
2514
2515 static Eina_Bool
2516 _pager_popup_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event)
2517 {
2518    Ecore_Event_Mouse_Button *ev;
2519    Pager_Popup *pp = act_popup;
2520
2521    ev = event;
2522    if (ev->window != input_window) return ECORE_CALLBACK_PASS_ON;
2523
2524    evas_event_feed_mouse_up(pp->popup->evas, ev->buttons,
2525                             0, ev->timestamp, NULL);
2526    return ECORE_CALLBACK_PASS_ON;
2527 }
2528
2529 static Eina_Bool
2530 _pager_popup_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event)
2531 {
2532    Ecore_Event_Mouse_Move *ev;
2533    Pager_Popup *pp = act_popup;
2534
2535    ev = event;
2536    if (ev->window != input_window) return 1;
2537
2538    evas_event_feed_mouse_move(pp->popup->evas,
2539                               ev->x - pp->popup->x + pp->pager->zone->x,
2540                               ev->y - pp->popup->y + pp->pager->zone->y,
2541                               ev->timestamp, NULL);
2542    return ECORE_CALLBACK_PASS_ON;
2543 }
2544
2545 static Eina_Bool
2546 _pager_popup_cb_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event)
2547 {
2548    Ecore_Event_Mouse_Wheel *ev = event;
2549    Pager_Popup *pp = act_popup;
2550    int max_x;
2551    
2552    e_zone_desk_count_get(pp->pager->zone, &max_x, NULL);
2553
2554    if (current_desk->x + ev->z >= max_x)
2555      _pager_popup_desk_switch(1, 1);
2556    else if (current_desk->x + ev->z < 0)
2557      _pager_popup_desk_switch(-1, -1);
2558    else
2559      _pager_popup_desk_switch(ev->z, 0);
2560
2561    return ECORE_CALLBACK_PASS_ON;
2562 }
2563
2564 static Eina_Bool
2565 _pager_popup_cb_key_down(void *data __UNUSED__, int type __UNUSED__, void *event)
2566 {
2567    Ecore_Event_Key *ev;
2568
2569    ev = event;
2570    if (ev->window != input_window) return ECORE_CALLBACK_PASS_ON;
2571    if (!strcmp(ev->key, "Up"))
2572      _pager_popup_desk_switch(0, -1);
2573    else if (!strcmp(ev->key, "Down"))
2574      _pager_popup_desk_switch(0, 1);
2575    else if (!strcmp(ev->key, "Left"))
2576      _pager_popup_desk_switch(-1, 0);
2577    else if (!strcmp(ev->key, "Right"))
2578      _pager_popup_desk_switch(1, 0);
2579    else if (!strcmp(ev->key, "Escape"))
2580      _pager_popup_hide(0);
2581    else
2582      {
2583         E_Config_Binding_Key *bind;
2584         Eina_List *l;
2585
2586         EINA_LIST_FOREACH(e_config->key_bindings, l, bind)
2587           {
2588              E_Binding_Modifier mod = 0;
2589
2590              if ((bind->action) && (strcmp(bind->action,"pager_switch"))) 
2591                continue;
2592
2593              if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) 
2594                mod |= E_BINDING_MODIFIER_SHIFT;
2595              if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) 
2596                mod |= E_BINDING_MODIFIER_CTRL;
2597              if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT) 
2598                mod |= E_BINDING_MODIFIER_ALT;
2599              if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN) 
2600                mod |= E_BINDING_MODIFIER_WIN;
2601
2602              if (bind->key && (!strcmp(bind->key, ev->keyname)) && 
2603                  ((bind->modifiers == (int) mod)))
2604                {
2605                   E_Action *act;
2606
2607                   act = e_action_find(bind->action);
2608
2609                   if (act)
2610                     {
2611                        if (act->func.go_key)
2612                          act->func.go_key(NULL, bind->params, ev);
2613                     }
2614                }
2615           }
2616      }
2617    return ECORE_CALLBACK_PASS_ON;
2618 }
2619
2620 static Eina_Bool
2621 _pager_popup_cb_key_up(void *data __UNUSED__, int type __UNUSED__, void *event)
2622 {
2623    Ecore_Event_Key *ev;
2624
2625    ev = event;
2626    if (!(act_popup)) return ECORE_CALLBACK_PASS_ON;
2627
2628    if (hold_mod)
2629      {
2630         if ((hold_mod & ECORE_EVENT_MODIFIER_SHIFT) && 
2631             (!strcmp(ev->key, "Shift_L"))) hold_count--;
2632         else if ((hold_mod & ECORE_EVENT_MODIFIER_SHIFT) && 
2633                  (!strcmp(ev->key, "Shift_R"))) hold_count--;
2634         else if ((hold_mod & ECORE_EVENT_MODIFIER_CTRL) && 
2635                  (!strcmp(ev->key, "Control_L"))) hold_count--;
2636         else if ((hold_mod & ECORE_EVENT_MODIFIER_CTRL) && 
2637                  (!strcmp(ev->key, "Control_R"))) hold_count--;
2638         else if ((hold_mod & ECORE_EVENT_MODIFIER_ALT) && 
2639                  (!strcmp(ev->key, "Alt_L"))) hold_count--;
2640         else if ((hold_mod & ECORE_EVENT_MODIFIER_ALT) && 
2641                  (!strcmp(ev->key, "Alt_R"))) hold_count--;
2642         else if ((hold_mod & ECORE_EVENT_MODIFIER_ALT) && 
2643                  (!strcmp(ev->key, "Meta_L"))) hold_count--;
2644         else if ((hold_mod & ECORE_EVENT_MODIFIER_ALT) && 
2645                  (!strcmp(ev->key, "Meta_R"))) hold_count--;
2646         else if ((hold_mod & ECORE_EVENT_MODIFIER_ALT) && 
2647                  (!strcmp(ev->key, "Super_L"))) hold_count--;
2648         else if ((hold_mod & ECORE_EVENT_MODIFIER_ALT) && 
2649                  (!strcmp(ev->key, "Super_R"))) hold_count--;
2650         else if ((hold_mod & ECORE_EVENT_MODIFIER_WIN) && 
2651                  (!strcmp(ev->key, "Super_L"))) hold_count--;
2652         else if ((hold_mod & ECORE_EVENT_MODIFIER_WIN) && 
2653                  (!strcmp(ev->key, "Super_R"))) hold_count--;
2654         else if ((hold_mod & ECORE_EVENT_MODIFIER_WIN) && 
2655                  (!strcmp(ev->key, "Mode_switch"))) hold_count--;
2656         else if ((hold_mod & ECORE_EVENT_MODIFIER_WIN) && 
2657                  (!strcmp(ev->key, "Meta_L"))) hold_count--;
2658         else if ((hold_mod & ECORE_EVENT_MODIFIER_WIN) && 
2659                  (!strcmp(ev->key, "Meta_R"))) hold_count--;
2660         if ((hold_count <= 0) && (!act_popup->pager->dragging))
2661           {
2662              _pager_popup_hide(1);
2663              return ECORE_CALLBACK_PASS_ON;
2664           }
2665      }
2666
2667    return ECORE_CALLBACK_PASS_ON;
2668 }
2669
2670 /***************************************************************************/
2671 /* module setup */
2672 EAPI E_Module_Api e_modapi =
2673 {
2674    E_MODULE_API_VERSION, "Pager"
2675 };
2676
2677 EAPI void *
2678 e_modapi_init(E_Module *m)
2679 {
2680    conf_edd = E_CONFIG_DD_NEW("Pager_Config", Config);
2681 #undef T
2682 #undef D
2683 #define T Config
2684 #define D conf_edd
2685    E_CONFIG_VAL(D, T, popup, UINT);
2686    E_CONFIG_VAL(D, T, popup_speed, DOUBLE);
2687    E_CONFIG_VAL(D, T, popup_urgent, UINT);
2688    E_CONFIG_VAL(D, T, popup_urgent_stick, UINT);
2689    E_CONFIG_VAL(D, T, popup_urgent_speed, DOUBLE);
2690    E_CONFIG_VAL(D, T, show_desk_names, UINT);
2691    E_CONFIG_VAL(D, T, popup_height, INT);
2692    E_CONFIG_VAL(D, T, popup_act_height, INT);
2693    E_CONFIG_VAL(D, T, drag_resist, UINT);
2694    E_CONFIG_VAL(D, T, btn_drag, UCHAR);
2695    E_CONFIG_VAL(D, T, btn_noplace, UCHAR);
2696    E_CONFIG_VAL(D, T, btn_desk, UCHAR);
2697    E_CONFIG_VAL(D, T, flip_desk, UCHAR);
2698
2699    pager_config = e_config_domain_load("module.pager", conf_edd);
2700
2701    if (!pager_config)
2702      {
2703         pager_config = E_NEW(Config, 1);
2704         pager_config->popup = 1;
2705         pager_config->popup_speed = 1.0;
2706         pager_config->popup_urgent = 0;
2707         pager_config->popup_urgent_stick = 0;
2708         pager_config->popup_urgent_speed = 1.5;
2709         pager_config->show_desk_names = 1;
2710         pager_config->popup_height = 60;
2711         pager_config->popup_act_height = 60;
2712         pager_config->drag_resist = 3;
2713         pager_config->btn_drag = 1;
2714         pager_config->btn_noplace = 2;
2715         pager_config->btn_desk = 0;
2716         pager_config->flip_desk = 0;
2717      }
2718    E_CONFIG_LIMIT(pager_config->popup, 0, 1);
2719    E_CONFIG_LIMIT(pager_config->popup_speed, 0.1, 10.0);
2720    E_CONFIG_LIMIT(pager_config->popup_urgent, 0, 1);
2721    E_CONFIG_LIMIT(pager_config->popup_urgent_stick, 0, 1);
2722    E_CONFIG_LIMIT(pager_config->popup_urgent_speed, 0.1, 10.0);
2723    E_CONFIG_LIMIT(pager_config->show_desk_names, 0, 1);
2724    E_CONFIG_LIMIT(pager_config->popup_height, 20, 200);
2725    E_CONFIG_LIMIT(pager_config->popup_act_height, 20, 200);
2726    E_CONFIG_LIMIT(pager_config->drag_resist, 0, 50);
2727    E_CONFIG_LIMIT(pager_config->flip_desk, 0, 1);
2728    E_CONFIG_LIMIT(pager_config->btn_drag, 0, 32);
2729    E_CONFIG_LIMIT(pager_config->btn_noplace, 0, 32);
2730    E_CONFIG_LIMIT(pager_config->btn_desk, 0, 32);
2731
2732    pager_config->handlers = eina_list_append
2733      (pager_config->handlers, ecore_event_handler_add
2734          (E_EVENT_BORDER_RESIZE, _pager_cb_event_border_resize, NULL));
2735    pager_config->handlers = eina_list_append
2736      (pager_config->handlers, ecore_event_handler_add
2737          (E_EVENT_BORDER_MOVE, _pager_cb_event_border_move, NULL));
2738    pager_config->handlers = eina_list_append
2739      (pager_config->handlers, ecore_event_handler_add
2740          (E_EVENT_BORDER_ADD, _pager_cb_event_border_add, NULL));
2741    pager_config->handlers = eina_list_append
2742      (pager_config->handlers, ecore_event_handler_add
2743          (E_EVENT_BORDER_REMOVE, _pager_cb_event_border_remove, NULL));
2744    pager_config->handlers = eina_list_append
2745      (pager_config->handlers, ecore_event_handler_add
2746          (E_EVENT_BORDER_ICONIFY, _pager_cb_event_border_iconify, NULL));
2747    pager_config->handlers = eina_list_append
2748      (pager_config->handlers, ecore_event_handler_add
2749          (E_EVENT_BORDER_UNICONIFY, _pager_cb_event_border_uniconify, NULL));
2750    pager_config->handlers = eina_list_append
2751      (pager_config->handlers, ecore_event_handler_add
2752          (E_EVENT_BORDER_STICK, _pager_cb_event_border_stick, NULL));
2753    pager_config->handlers = eina_list_append
2754      (pager_config->handlers, ecore_event_handler_add
2755          (E_EVENT_BORDER_UNSTICK, _pager_cb_event_border_unstick, NULL));
2756    pager_config->handlers = eina_list_append
2757      (pager_config->handlers, ecore_event_handler_add
2758          (E_EVENT_BORDER_DESK_SET, _pager_cb_event_border_desk_set, NULL));
2759    pager_config->handlers = eina_list_append
2760      (pager_config->handlers, ecore_event_handler_add
2761          (E_EVENT_BORDER_STACK, _pager_cb_event_border_stack, NULL));
2762    pager_config->handlers = eina_list_append
2763      (pager_config->handlers, ecore_event_handler_add
2764          (E_EVENT_BORDER_ICON_CHANGE, _pager_cb_event_border_icon_change, NULL));
2765    pager_config->handlers = eina_list_append
2766      (pager_config->handlers, ecore_event_handler_add
2767          (E_EVENT_BORDER_URGENT_CHANGE, _pager_cb_event_border_urgent_change, NULL));
2768    pager_config->handlers = eina_list_append
2769      (pager_config->handlers, ecore_event_handler_add
2770          (E_EVENT_BORDER_FOCUS_IN,
2771              _pager_cb_event_border_focus_in, NULL));
2772    pager_config->handlers = eina_list_append
2773      (pager_config->handlers, ecore_event_handler_add
2774          (E_EVENT_BORDER_FOCUS_OUT,
2775              _pager_cb_event_border_focus_out, NULL));
2776    pager_config->handlers = eina_list_append
2777      (pager_config->handlers, ecore_event_handler_add
2778          (E_EVENT_BORDER_PROPERTY, _pager_cb_event_border_property, NULL));
2779    pager_config->handlers = eina_list_append
2780      (pager_config->handlers, ecore_event_handler_add
2781          (E_EVENT_ZONE_DESK_COUNT_SET, _pager_cb_event_zone_desk_count_set, NULL));
2782    pager_config->handlers = eina_list_append
2783      (pager_config->handlers, ecore_event_handler_add
2784          (E_EVENT_DESK_SHOW, _pager_cb_event_desk_show, NULL));
2785    pager_config->handlers = eina_list_append
2786      (pager_config->handlers, ecore_event_handler_add
2787          (E_EVENT_DESK_NAME_CHANGE, _pager_cb_event_desk_name_change, NULL));
2788    pager_config->handlers = eina_list_append
2789      (pager_config->handlers, ecore_event_handler_add
2790          (E_EVENT_CONTAINER_RESIZE, _pager_cb_event_container_resize, NULL));
2791
2792    pager_config->module = m;
2793
2794    e_gadcon_provider_register(&_gadcon_class);
2795
2796    e_configure_registry_item_add("extensions/pager", 40, N_("Pager"), NULL,
2797                                  "preferences-pager", _pager_config_dialog);
2798
2799    act_popup_show = e_action_add("pager_show");
2800    if (act_popup_show)
2801      {
2802         act_popup_show->func.go_key = _pager_popup_cb_action_show;
2803         e_action_predef_name_set(N_("Pager"), N_("Show Pager Popup"), 
2804                                  "pager_show", "<none>", NULL, 0);
2805      }
2806    act_popup_switch = e_action_add("pager_switch");
2807    if (act_popup_switch)
2808      {
2809         act_popup_switch->func.go_key = _pager_popup_cb_action_switch;
2810         e_action_predef_name_set(N_("Pager"), N_("Popup Desk Right"), 
2811                                  "pager_switch", "right", NULL, 0);
2812         e_action_predef_name_set(N_("Pager"), N_("Popup Desk Left"),  
2813                                  "pager_switch", "left",  NULL, 0);
2814         e_action_predef_name_set(N_("Pager"), N_("Popup Desk Up"),    
2815                                  "pager_switch", "up",    NULL, 0);
2816         e_action_predef_name_set(N_("Pager"), N_("Popup Desk Down"),  
2817                                  "pager_switch", "down",  NULL, 0);
2818         e_action_predef_name_set(N_("Pager"), N_("Popup Desk Next"),    
2819                                  "pager_switch", "next",    NULL, 0);
2820         e_action_predef_name_set(N_("Pager"), N_("Popup Desk Previous"),  
2821                                  "pager_switch", "prev",  NULL, 0);
2822      }
2823
2824    return m;
2825 }
2826
2827 EAPI int
2828 e_modapi_shutdown(E_Module *m __UNUSED__)
2829 {
2830    e_gadcon_provider_unregister(&_gadcon_class);
2831
2832    if (pager_config->config_dialog)
2833      e_object_del(E_OBJECT(pager_config->config_dialog));
2834    while (pager_config->handlers)
2835      {
2836         ecore_event_handler_del(pager_config->handlers->data);
2837         pager_config->handlers = 
2838           eina_list_remove_list(pager_config->handlers, pager_config->handlers);
2839      }
2840
2841    if (pager_config->menu)
2842      {
2843         e_menu_post_deactivate_callback_set(pager_config->menu, NULL, NULL);
2844         e_object_del(E_OBJECT(pager_config->menu));
2845         pager_config->menu = NULL;
2846      }
2847
2848    e_configure_registry_item_del("extensions/pager");
2849
2850    e_action_del("pager_show");
2851    e_action_del("pager_switch");
2852
2853    e_action_predef_name_del(N_("Pager"), N_("Popup Desk Right"));
2854    e_action_predef_name_del(N_("Pager"), N_("Popup Desk Left"));
2855    e_action_predef_name_del(N_("Pager"), N_("Popup Desk Up"));
2856    e_action_predef_name_del(N_("Pager"), N_("Popup Desk Down"));
2857    e_action_predef_name_del(N_("Pager"), N_("Popup Desk Next"));
2858    e_action_predef_name_del(N_("Pager"), N_("Popup Desk Previous"));
2859
2860    E_FREE(pager_config);
2861    E_CONFIG_DD_FREE(conf_edd);
2862    return 1;
2863 }
2864
2865 EAPI int
2866 e_modapi_save(E_Module *m __UNUSED__)
2867 {
2868    e_config_domain_save("module.pager", conf_edd, pager_config);
2869    return 1;
2870 }