1 #include "e.h"
2 #include "e_mod_main.h"
3 
4 /* local subsystem functions */
5 typedef struct _E_Winlist_Win E_Winlist_Win;
6 
7 struct _E_Winlist_Win
8 {
9    Evas_Object  *bg_object;
10    Evas_Object  *icon_object;
11    E_Client     *client;
12    unsigned char was_iconified E_BITFIELD;
13    unsigned char was_shaded E_BITFIELD;
14 };
15 
16 static void      _e_winlist_size_adjust(void);
17 static Eina_Bool _e_winlist_client_add(E_Client *ec, E_Zone *zone, E_Desk *desk);
18 static void      _e_winlist_client_del(E_Client *ec);
19 static void      _e_winlist_activate_nth(int n);
20 static void      _e_winlist_activate(void);
21 static void      _e_winlist_deactivate(void);
22 static void      _e_winlist_show_active(void);
23 static Eina_Bool _e_winlist_cb_event_border_add(void *data, int type, void *event);
24 static Eina_Bool _e_winlist_cb_event_border_remove(void *data, int type, void *event);
25 static Eina_Bool _e_winlist_cb_key_down(void *data, int type, void *event);
26 static Eina_Bool _e_winlist_cb_key_up(void *data, int type, void *event);
27 static Eina_Bool _e_winlist_cb_mouse_down(void *data, int type, void *event);
28 static Eina_Bool _e_winlist_cb_mouse_up(void *data, int type, void *event);
29 static Eina_Bool _e_winlist_cb_mouse_wheel(void *data, int type, void *event);
30 static Eina_Bool _e_winlist_cb_mouse_move(void *data, int type, void *event);
31 static Eina_Bool _e_winlist_scroll_timer(void *data);
32 static Eina_Bool _e_winlist_animator(void *data);
33 #if 0
34 static void      _e_winlist_cb_item_mouse_in(void *data, Evas *evas,
35                                              Evas_Object *obj, void *event_info);
36 #endif
37 
38 /* local subsystem globals */
39 static Evas_Object *_winlist = NULL;
40 static E_Zone *_winlist_zone = NULL;
41 static Evas_Object *_bg_object = NULL;
42 static Evas_Object *_list_object = NULL;
43 static Evas_Object *_icon_object = NULL;
44 static Eina_List *_wins = NULL;
45 static Eina_List *_win_selected = NULL;
46 static E_Desk *_last_desk = NULL;
47 static int _last_pointer_x = 0;
48 static int _last_pointer_y = 0;
49 static E_Client *_last_client = NULL;
50 static int _hold_count = 0;
51 static int _hold_mod = 0;
52 static E_Winlist_Activate_Type _activate_type = 0;
53 static Eina_List *_handlers = NULL;
54 static Ecore_Window _input_window = 0;
55 static int _scroll_to = 0;
56 static double _scroll_align_to = 0.0;
57 static double _scroll_align = 0.0;
58 static Ecore_Timer *_scroll_timer = NULL;
59 static Ecore_Animator *_animator = NULL;
60 
61 static Eina_Bool
_wmclass_picked(const Eina_List * lst,const char * wmclass)62 _wmclass_picked(const Eina_List *lst, const char *wmclass)
63 {
64    const Eina_List *l;
65    const char *s;
66 
67    if (!wmclass) return EINA_FALSE;
68 
69    EINA_LIST_FOREACH(lst, l, s)
70      if (s == wmclass)
71        return EINA_TRUE;
72 
73    return EINA_FALSE;
74 }
75 
76 static void
_cb_lost(void * data EINA_UNUSED)77 _cb_lost(void *data EINA_UNUSED)
78 {
79    e_winlist_hide();
80 }
81 
82 /* externally accessible functions */
83 int
e_winlist_init(void)84 e_winlist_init(void)
85 {
86    return 1;
87 }
88 
89 int
e_winlist_shutdown(void)90 e_winlist_shutdown(void)
91 {
92    e_winlist_hide();
93    return 1;
94 }
95 
96 int
e_winlist_show(E_Zone * zone,E_Winlist_Filter filter)97 e_winlist_show(E_Zone *zone, E_Winlist_Filter filter)
98 {
99    int x, y, w, h;
100    Evas_Object *o;
101    Eina_List *l, *ll;
102    E_Desk *desk;
103    E_Client *ec;
104    E_Winlist_Win *ww;
105    Eina_List *wmclasses = NULL;
106 
107    E_OBJECT_CHECK_RETURN(zone, 0);
108    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, 0);
109 
110    if (_winlist) return 1;
111 
112 #ifndef HAVE_WAYLAND_ONLY
113    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
114      {
115         Ecore_X_Window mouse_grab = 0;
116         _input_window = ecore_x_window_input_new(e_comp->root, 0, 0, 1, 1);
117         ecore_x_window_show(_input_window);
118         if (_activate_type == E_WINLIST_ACTIVATE_TYPE_MOUSE)
119           mouse_grab = _input_window;
120         if (!e_grabinput_get(mouse_grab, 0, _input_window))
121           {
122              ecore_x_window_free(_input_window);
123              _input_window = 0;
124              return 0;
125           }
126         e_grabinput_lost_cb_set(_cb_lost, NULL);
127      }
128 #endif
129    if (e_comp->comp_type != E_PIXMAP_TYPE_X)
130      {
131         Eina_Bool mouse_grab = EINA_FALSE;
132         if (_activate_type == E_WINLIST_ACTIVATE_TYPE_MOUSE)
133           mouse_grab = EINA_TRUE;
134         if (!e_comp_grab_input(mouse_grab, EINA_TRUE))
135           return 0;
136         _input_window = e_comp->ee_win;
137      }
138 
139    w = (double)zone->w * e_config->winlist_pos_size_w;
140    if (w > e_config->winlist_pos_max_w) w = e_config->winlist_pos_max_w;
141    else if (w < e_config->winlist_pos_min_w)
142      w = e_config->winlist_pos_min_w;
143    if (w > zone->w) w = zone->w;
144    x = zone->x + (double)(zone->w - w) * e_config->winlist_pos_align_x;
145 
146    h = (double)zone->h * e_config->winlist_pos_size_h;
147    if (h > e_config->winlist_pos_max_h) h = e_config->winlist_pos_max_h;
148    else if (h < e_config->winlist_pos_min_h)
149      h = e_config->winlist_pos_min_h;
150    if (h > zone->h) h = zone->h;
151    y = zone->y + (double)(zone->h - h) * e_config->winlist_pos_align_y;
152 
153    _winlist_zone = zone;
154    e_client_move_cancel();
155    e_client_resize_cancel();
156    e_client_focus_track_freeze();
157 
158 #ifndef HAVE_WAYLAND_ONLY
159    evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
160    evas_event_feed_mouse_move(e_comp->evas, -1000000, -1000000, 0, NULL);
161 #endif
162 
163    evas_event_freeze(e_comp->evas);
164    o = edje_object_add(e_comp->evas);
165    evas_object_pass_events_set(o, EINA_TRUE);
166    _winlist = e_comp_object_util_add(o, E_COMP_OBJECT_TYPE_POPUP);
167    evas_object_layer_set(_winlist, E_LAYER_CLIENT_POPUP);
168    evas_object_move(_winlist, x, y);
169    _bg_object = o;
170    e_theme_edje_object_set(o, "base/theme/winlist",
171                            "e/widgets/winlist/main");
172 
173    o = elm_box_add(e_comp->elm);
174    _list_object = o;
175    elm_box_homogeneous_set(o, 1);
176    e_comp_object_util_del_list_append(_winlist, o);
177    edje_object_part_swallow(_bg_object, "e.swallow.list", o);
178    edje_object_part_text_set(_bg_object, "e.text.title", _("Select a window"));
179    evas_object_show(o);
180 
181    _last_client = e_client_focused_get();
182 
183    desk = e_desk_current_get(_winlist_zone);
184    EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
185      {
186         Eina_Bool pick;
187 
188         // skip if we already have it in winlist
189         EINA_LIST_FOREACH(_wins, ll, ww)
190           {
191              if (e_client_stack_bottom_get(ww->client) ==
192                  e_client_stack_bottom_get(ec)) break;
193           }
194         if (ll) continue;
195         switch (filter)
196           {
197            case E_WINLIST_FILTER_CLASS_WINDOWS:
198              if (!_last_client)
199                pick = EINA_FALSE;
200              else
201                pick = _last_client->icccm.class == ec->icccm.class;
202              break;
203            case E_WINLIST_FILTER_CLASSES:
204              pick = (!_wmclass_picked(wmclasses, ec->icccm.class));
205              if (pick)
206                wmclasses = eina_list_append(wmclasses, ec->icccm.class);
207              break;
208 
209            default:
210              pick = EINA_TRUE;
211           }
212         if (pick) _e_winlist_client_add(ec, _winlist_zone, desk);
213      }
214    eina_list_free(wmclasses);
215 
216    if (!_wins)
217      {
218         e_winlist_hide();
219         evas_event_thaw(e_comp->evas);
220         return 1;
221      }
222 
223    if (e_config->winlist_list_show_other_desk_windows ||
224        e_config->winlist_list_show_other_screen_windows)
225      _last_desk = e_desk_current_get(_winlist_zone);
226    if (e_config->winlist_warp_while_selecting)
227      ecore_evas_pointer_xy_get(e_comp->ee,
228                             &_last_pointer_x, &_last_pointer_y);
229 
230    _e_winlist_activate_nth(0);
231 
232    evas_event_thaw(e_comp->evas);
233    _e_winlist_size_adjust();
234 
235    E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_ADD, _e_winlist_cb_event_border_add, NULL);
236    E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_REMOVE, _e_winlist_cb_event_border_remove, NULL);
237    E_LIST_HANDLER_APPEND(_handlers, ECORE_EVENT_KEY_DOWN, _e_winlist_cb_key_down, NULL);
238    E_LIST_HANDLER_APPEND(_handlers, ECORE_EVENT_KEY_UP, _e_winlist_cb_key_up, NULL);
239    E_LIST_HANDLER_APPEND(_handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_winlist_cb_mouse_down, NULL);
240    E_LIST_HANDLER_APPEND(_handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _e_winlist_cb_mouse_up, NULL);
241    E_LIST_HANDLER_APPEND(_handlers, ECORE_EVENT_MOUSE_WHEEL, _e_winlist_cb_mouse_wheel, NULL);
242    E_LIST_HANDLER_APPEND(_handlers, ECORE_EVENT_MOUSE_MOVE, _e_winlist_cb_mouse_move, NULL);
243 
244    evas_object_show(_winlist);
245    return 1;
246 }
247 
248 void
e_winlist_hide(void)249 e_winlist_hide(void)
250 {
251    E_Client *ec = NULL;
252    E_Winlist_Win *ww;
253 
254    if (!_winlist) return;
255    if (_win_selected)
256      {
257         ww = _win_selected->data;
258         ec = ww->client;
259      }
260    evas_object_hide(_winlist);
261    EINA_LIST_FREE(_wins, ww)
262      {
263         if ((!ec) || (ww->client != ec))
264           e_object_unref(E_OBJECT(ww->client));
265         free(ww);
266      }
267    _win_selected = NULL;
268    _icon_object = NULL;
269 
270    evas_object_del(_winlist);
271    e_client_focus_track_thaw();
272    _winlist = NULL;
273    _winlist_zone = NULL;
274    _hold_count = 0;
275    _hold_mod = 0;
276    _activate_type = 0;
277 
278    E_FREE_LIST(_handlers, ecore_event_handler_del);
279 
280    E_FREE_FUNC(_scroll_timer, ecore_timer_del);
281    E_FREE_FUNC(_animator, ecore_animator_del);
282 
283 #ifndef HAVE_WAYLAND_ONLY
284    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
285      {
286         if (_input_window)
287           {
288              e_grabinput_release(_input_window, _input_window);
289              ecore_x_window_free(_input_window);
290           }
291      }
292 #endif
293    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
294      e_comp_ungrab_input(1, 1);
295    _input_window = 0;
296    if (ec)
297      {
298         Eina_Bool set = !ec->lock_focus_out;
299 
300         if (ec->shaded)
301           {
302              if (!ec->lock_user_shade)
303                e_client_unshade(ec, ec->shade_dir);
304           }
305         if (e_config->winlist_list_move_after_select)
306           {
307              e_client_zone_set(ec, e_zone_current_get());
308              e_client_desk_set(ec, e_desk_current_get(ec->zone));
309           }
310         else if (ec->desk)
311           {
312              if (!ec->sticky) e_desk_show(ec->desk);
313           }
314         if (!ec->lock_user_stacking)
315           {
316              evas_object_raise(ec->frame);
317              e_client_raise_latest_set(ec);
318           }
319         if (ec->iconic)
320           e_client_uniconify(ec);
321         if (ec->shaded)
322           e_client_unshade(ec, ec->shade_dir);
323         if ((e_config->focus_policy != E_FOCUS_CLICK) ||
324             (e_config->winlist_warp_at_end) ||
325             (e_config->winlist_warp_while_selecting))
326           {
327              set |= !e_client_pointer_warp_to_center_now(ec);
328           }
329         if (set)
330           {
331              evas_object_focus_set(ec->frame, 1);
332              e_client_focus_latest_set(ec);
333           }
334         e_object_unref(E_OBJECT(ec));
335      }
336 }
337 
338 void
e_winlist_next(void)339 e_winlist_next(void)
340 {
341    if (!_winlist) return;
342    if (eina_list_count(_wins) == 1)
343      {
344         if (!_win_selected)
345           {
346              _win_selected = _wins;
347              _e_winlist_show_active();
348              _e_winlist_activate();
349           }
350         return;
351      }
352    _e_winlist_deactivate();
353    if (!_win_selected)
354      _win_selected = _wins;
355    else
356      _win_selected = _win_selected->next;
357    if (!_win_selected) _win_selected = _wins;
358    _e_winlist_show_active();
359    _e_winlist_activate();
360 }
361 
362 void
e_winlist_prev(void)363 e_winlist_prev(void)
364 {
365    if (!_winlist) return;
366    if (eina_list_count(_wins) == 1)
367      {
368         if (!_win_selected)
369           {
370              _win_selected = _wins;
371              _e_winlist_show_active();
372              _e_winlist_activate();
373           }
374         return;
375      }
376    _e_winlist_deactivate();
377    if (!_win_selected)
378      _win_selected = _wins;
379    else
380      _win_selected = _win_selected->prev;
381    if (!_win_selected) _win_selected = eina_list_last(_wins);
382    _e_winlist_show_active();
383    _e_winlist_activate();
384 }
385 
386 static int
point_line_dist(int x,int y,int lx1,int ly1,int lx2,int ly2)387 point_line_dist(int x, int y, int lx1, int ly1, int lx2, int ly2)
388 {
389    int xx, yy, dx, dy;
390    int a = x - lx1;
391    int b = y - ly1;
392    int c = lx2 - lx1;
393    int d = ly2 - ly1;
394 
395    int dot = (a * c) + (b * d);
396    int len_sq = (c * c) + (d * d);
397    double dist, param = -1.0;
398 
399    // if line is 0 length
400    if (len_sq) param = (double)dot / len_sq;
401 
402    if (param < 0)
403      {
404         xx = lx1;
405         yy = ly1;
406      }
407    else if (param > 1)
408      {
409         xx = lx2;
410         yy = ly2;
411      }
412    else
413      {
414         xx = lx1 + lround(param * c);
415         yy = ly1 + lround(param * d);
416    }
417 
418    dx = x - xx;
419    dy = y - yy;
420    dist = sqrt((dx * dx) + (dy * dy));
421    return lround(dist);
422 }
423 
424 void
e_winlist_direction_select(E_Zone * zone,int dir)425 e_winlist_direction_select(E_Zone *zone, int dir)
426 {
427    E_Client *ec;
428    Eina_List *l;
429    E_Desk *desk;
430    E_Client *ec_orig, *ec_next = NULL;
431    int distance = INT_MAX;
432    int cx, cy;
433    E_Winlist_Win *ww;
434 
435    ec_next = NULL;
436 
437    E_OBJECT_CHECK(zone);
438    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
439 
440    ec_orig = e_client_focused_get();
441    if (!ec_orig) return;
442 
443    cx = ec_orig->x + (ec_orig->w / 2);
444    cy = ec_orig->y + (ec_orig->h / 2);
445 
446    desk = e_desk_current_get(zone);
447    EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
448      {
449         int a = 0, d = 0;
450 
451         if (ec == ec_orig) continue;
452         if ((!ec->icccm.accepts_focus) &&
453             (!ec->icccm.take_focus)) continue;
454         if (ec->netwm.state.skip_taskbar) continue;
455         if (ec->user_skip_winlist) continue;
456         if (ec->iconic)
457           {
458              if (!e_config->winlist_list_show_iconified) continue;
459              if ((ec->zone != zone) &&
460                  (!e_config->winlist_list_show_other_screen_iconified))
461                continue;
462              if ((ec->desk != desk) &&
463                  (!e_config->winlist_list_show_other_desk_iconified)) continue;
464           }
465         else
466           {
467              if (ec->sticky)
468                {
469                   if ((ec->zone != zone) &&
470                       (!e_config->winlist_list_show_other_screen_windows))
471                     continue;
472                }
473              else
474                {
475                   if (ec->desk != desk)
476                     {
477                        if ((ec->zone) && (ec->zone != zone))
478                          {
479                             if (!e_config->winlist_list_show_other_screen_windows)
480                               continue;
481                          }
482                        else if (!e_config->winlist_list_show_other_desk_windows)
483                          continue;
484                     }
485                }
486           }
487 
488         switch (dir)
489           {
490            case 0: /* up */
491              d = point_line_dist(cx, cy,
492                                  ec->x,         ec->y + ec->h,
493                                  ec->x + ec->w, ec->y + ec->h);
494              if (d >= distance) continue;
495              d = point_line_dist(cx, cy,
496                                  ec->x,         ec->y + (ec->h / 2),
497                                  ec->x + ec->w, ec->y + (ec->h / 2));
498              if (d >= distance) continue;
499              if (cy <= (ec->y + (ec->h / 2))) continue;
500              a = abs(cx - (ec->x + (ec->w / 2)));
501              d += (a * a) / d;
502              if (d >= distance) continue;
503              break;
504            case 1: /* down */
505              d = point_line_dist(cx, cy,
506                                  ec->x,         ec->y,
507                                  ec->x + ec->w, ec->y);
508              if (d >= distance) continue;
509              d = point_line_dist(cx, cy,
510                                  ec->x,         ec->y + (ec->h / 2),
511                                  ec->x + ec->w, ec->y + (ec->h / 2));
512              if (d >= distance) continue;
513              if (cy >= (ec->y + (ec->h / 2))) continue;
514              a = abs(cx - (ec->x + (ec->w / 2)));
515              d += (a * a) / d;
516              if (d >= distance) continue;
517              break;
518            case 2: /* left */
519              d = point_line_dist(cx, cy,
520                                  ec->x + ec->w, ec->y,
521                                  ec->x + ec->w, ec->y + ec->h);
522              if (d >= distance) continue;
523              d = point_line_dist(cx, cy,
524                                  ec->x + (ec->w / 2), ec->y,
525                                  ec->x + (ec->w / 2), ec->y + ec->h);
526              if (d >= distance) continue;
527              if (cx <= (ec->x + (ec->w / 2))) continue;
528              a = abs(cy - (ec->y + (ec->h / 2)));
529              d += (a * a) / d;
530              if (d >= distance) continue;
531              break;
532            case 3: /* right */
533              d = point_line_dist(cx, cy,
534                                  ec->x, ec->y,
535                                  ec->x, ec->y + ec->h);
536              if (d >= distance) continue;
537              d = point_line_dist(cx, cy,
538                                  ec->x + (ec->w / 2), ec->y,
539                                  ec->x + (ec->w / 2), ec->y + ec->h);
540              if (d >= distance) continue;
541              if (cx >= (ec->x + (ec->w / 2))) continue;
542              a = abs(cy - (ec->y + (ec->h / 2)));
543              d += (a * a) / d;
544              if (d >= distance) continue;
545              break;
546           }
547         ec_next = ec;
548         distance = d;
549      }
550 
551    if (!ec_next) return;
552    _e_winlist_deactivate();
553    EINA_LIST_FOREACH(_wins, l, ww)
554      {
555         if (ww->client != ec_next) continue;
556         _win_selected = l;
557         break;
558      }
559    _e_winlist_show_active();
560    _e_winlist_activate();
561 }
562 
563 void
e_winlist_modifiers_set(int mod,E_Winlist_Activate_Type type)564 e_winlist_modifiers_set(int mod, E_Winlist_Activate_Type type)
565 {
566    _hold_mod = mod;
567    _hold_count = 0;
568    _activate_type = type;
569    if (type == E_WINLIST_ACTIVATE_TYPE_MOUSE) _hold_count++;
570    if (_hold_mod & ECORE_EVENT_MODIFIER_SHIFT) _hold_count++;
571    if (_hold_mod & ECORE_EVENT_MODIFIER_CTRL) _hold_count++;
572    if (_hold_mod & ECORE_EVENT_MODIFIER_ALT) _hold_count++;
573    if (_hold_mod & ECORE_EVENT_MODIFIER_WIN) _hold_count++;
574 }
575 
576 /* local subsystem functions */
577 static void
_e_winlist_size_adjust(void)578 _e_winlist_size_adjust(void)
579 {
580    Evas_Coord mw, mh;
581    E_Zone *zone;
582    int x, y, w, h;
583 
584    elm_box_recalculate(_list_object);
585    edje_object_part_swallow(_bg_object, "e.swallow.list", _list_object);
586    edje_object_size_min_calc(_bg_object, &mw, &mh);
587    evas_object_size_hint_min_set(_list_object, -1, -1);
588    edje_object_part_swallow(_bg_object, "e.swallow.list", _list_object);
589 
590    zone = _winlist_zone;
591    w = (double)zone->w * e_config->winlist_pos_size_w;
592    if (w < mw) w = mw;
593    if (w > e_config->winlist_pos_max_w) w = e_config->winlist_pos_max_w;
594    else if (w < e_config->winlist_pos_min_w)
595      w = e_config->winlist_pos_min_w;
596    if (w > zone->w) w = zone->w;
597    x = zone->x + (double)(zone->w - w) * e_config->winlist_pos_align_x;
598 
599    h = mh;
600    if (h > e_config->winlist_pos_max_h) h = e_config->winlist_pos_max_h;
601    else if (h < e_config->winlist_pos_min_h)
602      h = e_config->winlist_pos_min_h;
603    if (h > zone->h) h = zone->h;
604    y = zone->y + (double)(zone->h - h) * e_config->winlist_pos_align_y;
605 
606    evas_object_geometry_set(_winlist, x, y, w, h);
607 }
608 
609 static Eina_Bool
_e_winlist_client_add(E_Client * ec,E_Zone * zone,E_Desk * desk)610 _e_winlist_client_add(E_Client *ec, E_Zone *zone, E_Desk *desk)
611 {
612    E_Winlist_Win *ww;
613    Evas_Coord mw, mh;
614    Evas_Object *o;
615 
616    if ((!ec->icccm.accepts_focus) &&
617        (!ec->icccm.take_focus)) return EINA_FALSE;
618    if (ec->netwm.state.skip_taskbar) return EINA_FALSE;
619    if (ec->user_skip_winlist) return EINA_FALSE;
620    if (ec->iconic)
621      {
622         if (!e_config->winlist_list_show_iconified) return EINA_FALSE;
623         if ((ec->zone != zone) &&
624             (!e_config->winlist_list_show_other_screen_iconified)) return EINA_FALSE;
625         if ((ec->desk != desk) &&
626             (!e_config->winlist_list_show_other_desk_iconified)) return EINA_FALSE;
627      }
628    else
629      {
630         if (ec->sticky)
631           {
632              if ((ec->zone != zone) &&
633                  (!e_config->winlist_list_show_other_screen_windows)) return EINA_FALSE;
634           }
635         else
636           {
637              if (ec->desk != desk)
638                {
639                   if ((ec->zone) && (ec->zone != zone))
640                     {
641                        if (!e_config->winlist_list_show_other_screen_windows)
642                          return EINA_FALSE;
643                        if (ec->zone && ec->desk && (ec->desk != e_desk_current_get(ec->zone)))
644                          {
645                             if (!e_config->winlist_list_show_other_desk_windows)
646                               return EINA_FALSE;
647                          }
648                     }
649                   else if (!e_config->winlist_list_show_other_desk_windows)
650                     return EINA_FALSE;
651                }
652           }
653      }
654 
655    ww = E_NEW(E_Winlist_Win, 1);
656    if (!ww) return EINA_FALSE;
657    ww->client = ec;
658    _wins = eina_list_append(_wins, ww);
659    o = edje_object_add(e_comp->evas);
660    E_FILL(o);
661    e_comp_object_util_del_list_append(_winlist, o);
662    ww->bg_object = o;
663    e_theme_edje_object_set(o, "base/theme/winlist",
664                            "e/widgets/winlist/item");
665    edje_object_part_text_set(o, "e.text.label",
666                              e_client_util_name_get
667                              (e_client_stack_active_adjust(ww->client)));
668    evas_object_show(o);
669    if (edje_object_part_exists(ww->bg_object, "e.swallow.icon"))
670      {
671         o = e_client_icon_add(ec, e_comp->evas);
672         ww->icon_object = o;
673         e_comp_object_util_del_list_append(_winlist, o);
674         edje_object_part_swallow(ww->bg_object, "e.swallow.icon", o);
675         evas_object_show(o);
676      }
677    if (ec->shaded)
678      edje_object_signal_emit(ww->bg_object, "e,state,shaded", "e");
679    else if (ec->iconic)
680      edje_object_signal_emit(ww->bg_object, "e,state,iconified", "e");
681    else if (ec->desk != desk)
682      {
683         if (!((ec->sticky) && (ec->zone == zone)))
684           edje_object_signal_emit(ww->bg_object, "e,state,invisible", "e");
685      }
686 
687    edje_object_size_min_calc(ww->bg_object, &mw, &mh);
688    E_WEIGHT(ww->bg_object, 1, 0);
689    E_FILL(ww->bg_object);
690    evas_object_size_hint_min_set(ww->bg_object, mw, mh);
691    evas_object_size_hint_max_set(ww->bg_object, 9999, mh);
692    elm_box_pack_end(_list_object, ww->bg_object);
693    e_object_ref(E_OBJECT(ww->client));
694    return EINA_TRUE;
695 }
696 
697 static void
_e_winlist_client_del(E_Client * ec)698 _e_winlist_client_del(E_Client *ec)
699 {
700    E_Winlist_Win *ww;
701    Eina_List *l;
702 
703    if (ec == _last_client) _last_client = NULL;
704    EINA_LIST_FOREACH(_wins, l, ww)
705      {
706         if (ww->client == ec)
707           {
708              e_object_unref(E_OBJECT(ww->client));
709              if (l == _win_selected)
710                {
711                   _win_selected = l->next;
712                   if (!_win_selected) _win_selected = l->prev;
713                   _e_winlist_show_active();
714                   _e_winlist_activate();
715                }
716              e_comp_object_util_del_list_remove(_winlist, ww->bg_object);
717              evas_object_del(ww->bg_object);
718              if (ww->icon_object)
719                {
720                   e_comp_object_util_del_list_remove(_winlist, ww->icon_object);
721                   evas_object_del(ww->icon_object);
722                }
723              E_FREE(ww);
724              _wins = eina_list_remove_list(_wins, l);
725              return;
726           }
727      }
728 }
729 
730 static void
_e_winlist_client_replace(E_Client * ec,E_Client * ec_new)731 _e_winlist_client_replace(E_Client *ec, E_Client *ec_new)
732 {
733    E_Winlist_Win *ww;
734    Eina_List *l;
735 
736    EINA_LIST_FOREACH(_wins, l, ww)
737      {
738         if (ww->client == ec)
739           {
740              Evas_Coord mw, mh;
741 
742              edje_object_part_text_set(ww->bg_object, "e.text.label",
743                                        e_client_util_name_get(ec_new));
744              edje_object_size_min_calc(ww->bg_object, &mw, &mh);
745              E_WEIGHT(ww->bg_object, 1, 0);
746              E_FILL(ww->bg_object);
747              evas_object_size_hint_min_set(ww->bg_object, mw, mh);
748              evas_object_size_hint_max_set(ww->bg_object, 9999, mh);
749              return;
750           }
751      }
752 }
753 
754 static void
_e_winlist_activate_nth(int n)755 _e_winlist_activate_nth(int n)
756 {
757    Eina_List *l;
758    int cnt;
759 
760    _e_winlist_deactivate();
761    cnt = eina_list_count(_wins);
762    if (n >= cnt) n = cnt - 1;
763    l = eina_list_nth_list(_wins, n);
764    if (!l) return;
765 
766    _win_selected = l;
767    _e_winlist_show_active();
768    _e_winlist_activate();
769 }
770 
771 static void
_e_winlist_activate(void)772 _e_winlist_activate(void)
773 {
774    E_Winlist_Win *ww;
775    Evas_Object *o;
776    int ok = 0;
777 
778    if (!_win_selected) return;
779    ww = _win_selected->data;
780    edje_object_signal_emit(ww->bg_object, "e,state,selected", "e");
781    if (ww->icon_object && e_icon_edje_get(ww->icon_object))
782      e_icon_edje_emit(ww->icon_object, "e,state,selected", "e");
783 
784    if ((ww->client->iconic) &&
785        (e_config->winlist_list_uncover_while_selecting))
786      {
787         if (!ww->client->lock_user_iconify)
788           e_client_uniconify(ww->client);
789         ww->was_iconified = 1;
790         ok = 1;
791      }
792    if ((!ww->client->sticky) &&
793        (ww->client->desk != e_desk_current_get(_winlist_zone)) &&
794        (e_config->winlist_list_jump_desk_while_selecting))
795      {
796         if (ww->client->desk) e_desk_show(ww->client->desk);
797         ok = 1;
798      }
799    if ((ww->client->shaded || ww->client->shading) &&
800        (ww->client->desk == e_desk_current_get(_winlist_zone)) &&
801        (e_config->winlist_list_uncover_while_selecting))
802      {
803         if (!ww->client->lock_user_shade)
804           e_client_unshade(ww->client, ww->client->shade_dir);
805         ww->was_shaded = 1;
806         ok = 1;
807      }
808    if ((!ww->client->iconic) &&
809        ((ww->client->desk == e_desk_current_get(_winlist_zone)) ||
810         (ww->client->sticky)))
811      ok = 1;
812    if (ok)
813      {
814         int set = 1;
815         if (e_config->winlist_warp_while_selecting)
816           {
817             if (!e_client_pointer_warp_to_center_now(ww->client))
818               {
819                  evas_object_focus_set(ww->client->frame, 1);
820                  set = 0;
821               }
822           }
823 
824         if ((!ww->client->lock_user_stacking) &&
825             (e_config->winlist_list_raise_while_selecting))
826           evas_object_raise(ww->client->frame);
827         if ((!ww->client->lock_focus_out) &&
828             (e_config->winlist_list_focus_while_selecting))
829           {
830              if (set)
831                evas_object_focus_set(ww->client->frame, 1);
832           }
833      }
834    edje_object_part_text_set(_bg_object, "e.text.label",
835                              e_client_util_name_get(ww->client));
836    if (_icon_object)
837      {
838         e_comp_object_util_del_list_remove(_winlist, _icon_object);
839         evas_object_del(_icon_object);
840         _icon_object = NULL;
841      }
842    if (edje_object_part_exists(_bg_object, "e.swallow.icon"))
843      {
844         o = e_client_icon_add(ww->client, evas_object_evas_get(_winlist));
845         _icon_object = o;
846         e_comp_object_util_del_list_append(_winlist, o);
847         edje_object_part_swallow(_bg_object, "e.swallow.icon", o);
848         evas_object_show(o);
849      }
850 
851    edje_object_signal_emit(_bg_object, "e,state,selected", "e");
852 }
853 
854 static void
_e_winlist_deactivate(void)855 _e_winlist_deactivate(void)
856 {
857    E_Winlist_Win *ww;
858 
859    if (!_win_selected) return;
860    ww = _win_selected->data;
861    if (ww->was_shaded)
862      {
863         if (!ww->client->lock_user_shade)
864           e_client_shade(ww->client, ww->client->shade_dir);
865      }
866    if (ww->was_iconified)
867      {
868         if (!ww->client->lock_user_iconify)
869           e_client_iconify(ww->client);
870      }
871    ww->was_shaded = 0;
872    ww->was_iconified = 0;
873    edje_object_part_text_set(_bg_object, "e.text.label", "");
874    edje_object_signal_emit(ww->bg_object, "e,state,unselected", "e");
875    if (ww->icon_object && e_icon_edje_get(ww->icon_object))
876      e_icon_edje_emit(ww->icon_object, "e,state,unselected", "e");
877    if (!ww->client->lock_focus_in)
878      evas_object_focus_set(ww->client->frame, 0);
879 }
880 
881 static void
_e_winlist_show_active(void)882 _e_winlist_show_active(void)
883 {
884    Eina_List *l;
885    int i, n;
886 
887    if (!_wins) return;
888 
889    for (i = 0, l = _wins; l; l = l->next, i++)
890      if (l == _win_selected) break;
891 
892    n = eina_list_count(_wins);
893    if (n <= 1) return;
894    _scroll_align_to = (double)i / (double)(n - 1);
895    if (e_config->winlist_scroll_animate)
896      {
897         _scroll_to = 1;
898         if (!_scroll_timer)
899           _scroll_timer = ecore_timer_loop_add(0.01, _e_winlist_scroll_timer, NULL);
900         if (!_animator)
901           _animator = ecore_animator_add(_e_winlist_animator, NULL);
902      }
903    else
904      {
905         _scroll_align = _scroll_align_to;
906         elm_box_align_set(_list_object, 0.5, fabs(1.0 - _scroll_align));
907      }
908 }
909 
910 static void
_e_winlist_restore_desktop(void)911 _e_winlist_restore_desktop(void)
912 {
913    if (_last_desk &&
914        (e_config->winlist_list_show_other_desk_windows ||
915         e_config->winlist_list_show_other_screen_windows))
916      e_desk_show(_last_desk);
917    if (e_config->winlist_warp_while_selecting)
918      ecore_evas_pointer_warp(e_comp->ee,
919                           _last_pointer_x, _last_pointer_y);
920    _e_winlist_deactivate();
921    _win_selected = NULL;
922    e_winlist_hide();
923    if (_last_client)
924      {
925         evas_object_focus_set(_last_client->frame, 1);
926         _last_client = NULL;
927      }
928 }
929 
930 static Eina_Bool
_e_winlist_cb_event_border_add(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)931 _e_winlist_cb_event_border_add(void *data EINA_UNUSED, int type EINA_UNUSED,
932                                void *event)
933 {
934    E_Event_Client *ev = event;
935    E_Client *ec = ev->ec;
936    Eina_List *l;
937    E_Winlist_Win *ww;
938 
939    // get base client
940    ec = e_client_stack_bottom_get(ec);
941    // skip if we already have it in winlist
942    EINA_LIST_FOREACH(_wins, l, ww)
943      {
944         if (ww->client == ec)
945           {
946              _e_winlist_client_replace(ec, e_client_stack_active_adjust(ec));
947              goto done;
948           }
949      }
950    if (_e_winlist_client_add(ec, _winlist_zone,
951                              e_desk_current_get(_winlist_zone)))
952      _e_winlist_size_adjust();
953 done:
954    return ECORE_CALLBACK_PASS_ON;
955 }
956 
957 static Eina_Bool
_e_winlist_cb_event_border_remove(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)958 _e_winlist_cb_event_border_remove(void *data EINA_UNUSED, int type EINA_UNUSED,
959                                   void *event)
960 {
961    E_Event_Client *ev = event;
962    E_Client *ec = ev->ec;
963 
964    if (!ec->stack.prev) _e_winlist_client_del(ec);
965    else _e_winlist_client_replace(ec, e_client_stack_active_adjust(ec));
966    _e_winlist_size_adjust();
967    return ECORE_CALLBACK_PASS_ON;
968 }
969 
970 static Eina_Bool
_e_winlist_cb_key_down(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)971 _e_winlist_cb_key_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
972 {
973    Ecore_Event_Key *ev = event;
974    E_Util_Action act;
975    int x = 0, y = 0;
976 
977    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
978    act = e_util_key_geometry_action_get(ev->key, &x, &y, 1, 1);
979    if (act == E_UTIL_ACTION_DONE)
980      e_winlist_hide();
981    else if (act == E_UTIL_ACTION_ABORT)
982      _e_winlist_restore_desktop();
983    else if (act == E_UTIL_ACTION_DO)
984      {
985         if      (y < 0)
986           e_winlist_direction_select(_winlist_zone, 0);
987         else if (y > 0)
988           e_winlist_direction_select(_winlist_zone, 1);
989         else if (x < 0)
990           e_winlist_direction_select(_winlist_zone, 2);
991         else if (x > 0)
992           e_winlist_direction_select(_winlist_zone, 3);
993      }
994    else if (!strcmp(ev->key, "1"))
995      _e_winlist_activate_nth(0);
996    else if (!strcmp(ev->key, "2"))
997      _e_winlist_activate_nth(1);
998    else if (!strcmp(ev->key, "3"))
999      _e_winlist_activate_nth(2);
1000    else if (!strcmp(ev->key, "4"))
1001      _e_winlist_activate_nth(3);
1002    else if (!strcmp(ev->key, "5"))
1003      _e_winlist_activate_nth(4);
1004    else if (!strcmp(ev->key, "6"))
1005      _e_winlist_activate_nth(5);
1006    else if (!strcmp(ev->key, "7"))
1007      _e_winlist_activate_nth(6);
1008    else if (!strcmp(ev->key, "8"))
1009      _e_winlist_activate_nth(7);
1010    else if (!strcmp(ev->key, "9"))
1011      _e_winlist_activate_nth(8);
1012    else if (!strcmp(ev->key, "0"))
1013      _e_winlist_activate_nth(9);
1014    else
1015      {
1016         Eina_List *l;
1017         E_Config_Binding_Key *binding;
1018         E_Binding_Modifier mod;
1019 
1020         EINA_LIST_FOREACH(e_bindings->key_bindings, l, binding)
1021           {
1022              if (binding->action != _winlist_act) continue;
1023 
1024              mod = 0;
1025 
1026              if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1027                mod |= E_BINDING_MODIFIER_SHIFT;
1028              if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
1029                mod |= E_BINDING_MODIFIER_CTRL;
1030              if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
1031                mod |= E_BINDING_MODIFIER_ALT;
1032              if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
1033                mod |= E_BINDING_MODIFIER_WIN;
1034 
1035              if (binding->key && ((!strcmp(binding->key, ev->key)) || (!strcmp(binding->key, ev->keyname))) &&
1036                  ((binding->modifiers == mod) || (binding->any_mod)))
1037                {
1038                   if (!_act_winlist) continue;
1039                   if (_act_winlist->func.go_key)
1040                     _act_winlist->func.go_key(E_OBJECT(_winlist_zone), binding->params, ev);
1041                   else if (_act_winlist->func.go)
1042                     _act_winlist->func.go(E_OBJECT(_winlist_zone), binding->params);
1043                }
1044           }
1045      }
1046    return ECORE_CALLBACK_PASS_ON;
1047 }
1048 
1049 static Eina_Bool
_e_winlist_cb_key_up(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)1050 _e_winlist_cb_key_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1051 {
1052    Ecore_Event_Key *ev;
1053    Eina_List *l;
1054    E_Config_Binding_Key *binding;
1055    E_Binding_Modifier mod;
1056 
1057    ev = event;
1058    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
1059    if (!_winlist) return ECORE_CALLBACK_PASS_ON;
1060    if (_hold_mod)
1061      {
1062 #define KEY_CHECK(MOD, NAME) \
1063         if ((_hold_mod & ECORE_EVENT_MODIFIER_##MOD) && (!strcmp(ev->key, NAME))) \
1064           _hold_count--, _hold_mod &= ~ECORE_EVENT_MODIFIER_##MOD
1065         KEY_CHECK(SHIFT, "Shift_L");
1066         else KEY_CHECK(SHIFT, "Shift_R");
1067         else KEY_CHECK(CTRL, "Control_L");
1068         else KEY_CHECK(CTRL, "Control_R");
1069         else KEY_CHECK(ALT, "Alt_L");
1070         else KEY_CHECK(ALT, "Alt_R");
1071         else KEY_CHECK(ALT, "Meta_L");
1072         else KEY_CHECK(ALT, "Meta_R");
1073         else KEY_CHECK(WIN, "Meta_L");
1074         else KEY_CHECK(WIN, "Meta_R");
1075         else KEY_CHECK(ALT, "Super_L");
1076         else KEY_CHECK(ALT, "Super_R");
1077         else KEY_CHECK(WIN, "Super_L");
1078         else KEY_CHECK(WIN, "Super_R");
1079         else KEY_CHECK(WIN, "Mode_switch");
1080 
1081         if ((_hold_count <= 0) || ((!_hold_mod) && (_activate_type == E_WINLIST_ACTIVATE_TYPE_KEY)))
1082           {
1083              e_winlist_hide();
1084              return 1;
1085           }
1086      }
1087 
1088    EINA_LIST_FOREACH(e_bindings->key_bindings, l, binding)
1089      {
1090         if (binding->action != _winlist_act) continue;
1091         mod = 0;
1092 
1093         if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
1094           mod |= E_BINDING_MODIFIER_SHIFT;
1095         if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
1096           mod |= E_BINDING_MODIFIER_CTRL;
1097         if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
1098           mod |= E_BINDING_MODIFIER_ALT;
1099         if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
1100           mod |= E_BINDING_MODIFIER_WIN;
1101 
1102         if (binding->key && (!strcmp(binding->key, ev->key)) &&
1103             ((binding->modifiers == mod) || (binding->any_mod)))
1104           {
1105              if (!_act_winlist) continue;
1106              if (_act_winlist->func.end_key)
1107                _act_winlist->func.end_key(E_OBJECT(_winlist_zone), binding->params, ev);
1108              else if (_act_winlist->func.end)
1109                _act_winlist->func.end(E_OBJECT(_winlist_zone), binding->params);
1110           }
1111      }
1112 
1113    return ECORE_CALLBACK_PASS_ON;
1114 }
1115 
1116 static Eina_Bool
_e_winlist_cb_mouse_down(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)1117 _e_winlist_cb_mouse_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1118 {
1119    Ecore_Event_Mouse_Button *ev;
1120 
1121    ev = event;
1122    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
1123    e_bindings_mouse_down_ecore_event_handle(E_BINDING_CONTEXT_WINLIST,
1124                                       E_OBJECT(_winlist_zone), ev);
1125    return ECORE_CALLBACK_PASS_ON;
1126 }
1127 
1128 static Eina_Bool
_e_winlist_cb_mouse_up(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)1129 _e_winlist_cb_mouse_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1130 {
1131    Ecore_Event_Mouse_Button *ev;
1132 
1133    ev = event;
1134    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
1135    if (e_bindings_mouse_up_ecore_event_handle(E_BINDING_CONTEXT_WINLIST, E_OBJECT(_winlist_zone), ev))
1136      return ECORE_CALLBACK_RENEW;
1137    if (_activate_type != E_WINLIST_ACTIVATE_TYPE_MOUSE) return ECORE_CALLBACK_RENEW;
1138    if (!--_hold_count) e_winlist_hide();
1139    return ECORE_CALLBACK_PASS_ON;
1140 }
1141 
1142 static Eina_Bool
_e_winlist_cb_mouse_wheel(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)1143 _e_winlist_cb_mouse_wheel(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1144 {
1145    Ecore_Event_Mouse_Wheel *ev;
1146    int i;
1147 
1148    ev = event;
1149    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
1150    e_bindings_wheel_ecore_event_handle(E_BINDING_CONTEXT_WINLIST,
1151                                  E_OBJECT(_winlist_zone), ev);
1152    if (ev->z < 0) /* up */
1153      {
1154         for (i = ev->z; i < 0; i++)
1155           e_winlist_prev();
1156      }
1157    else if (ev->z > 0) /* down */
1158      {
1159         for (i = ev->z; i > 0; i--)
1160           e_winlist_next();
1161      }
1162    return ECORE_CALLBACK_PASS_ON;
1163 }
1164 
1165 static Eina_Bool
_e_winlist_cb_mouse_move(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)1166 _e_winlist_cb_mouse_move(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1167 {
1168    Ecore_Event_Mouse_Move *ev;
1169    int x, y, w, h;
1170 
1171    ev = event;
1172    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
1173    evas_object_geometry_get(_winlist, &x, &y, &w, &h);
1174    /* only feed mouse move if it's within the winlist popup */
1175    if (E_INSIDE(ev->x, ev->y, x, y, w, h))
1176      evas_event_feed_mouse_move(evas_object_evas_get(_winlist), ev->x, ev->y, ev->timestamp, NULL);
1177 
1178    return ECORE_CALLBACK_PASS_ON;
1179 }
1180 
1181 static Eina_Bool
_e_winlist_scroll_timer(void * data EINA_UNUSED)1182 _e_winlist_scroll_timer(void *data EINA_UNUSED)
1183 {
1184    if (_scroll_to)
1185      {
1186         double spd;
1187 
1188         spd = e_config->winlist_scroll_speed;
1189         _scroll_align = (_scroll_align * (1.0 - spd)) +
1190           (_scroll_align_to * spd);
1191         return 1;
1192      }
1193    _scroll_timer = NULL;
1194    return ECORE_CALLBACK_CANCEL;
1195 }
1196 
1197 static Eina_Bool
_e_winlist_animator(void * data EINA_UNUSED)1198 _e_winlist_animator(void *data EINA_UNUSED)
1199 {
1200    if (_scroll_to)
1201      {
1202         double da;
1203 
1204         da = _scroll_align - _scroll_align_to;
1205         if (da < 0.0) da = -da;
1206         if (da < 0.01)
1207           {
1208              _scroll_align = _scroll_align_to;
1209              _scroll_to = 0;
1210           }
1211         elm_box_align_set(_list_object, 0.5, fabs(1.0 - _scroll_align));
1212      }
1213    if (!_scroll_to) _animator = NULL;
1214    return _scroll_to;
1215 }
1216 
1217 #if 0
1218 static void
1219 _e_winlist_cb_item_mouse_in(void *data, Evas *evas, Evas_Object *obj, void *event_info)
1220 {
1221    E_Winlist_Win *ww;
1222    E_Winlist_Win *lww;
1223    Eina_List *l;
1224 
1225    if (!(ww = data)) return;
1226    if (!_wins) return;
1227    EINA_LIST_FOREACH(_wins, l, lww)
1228      if (lww == ww) break;
1229    _e_winlist_deactivate();
1230    _win_selected = l;
1231    _e_winlist_show_active();
1232    _e_winlist_activate();
1233 }
1234 
1235 #endif
1236