1 #include "e_illume_private.h"
2 #include "e_mod_quickpanel.h"
4 /* local function prototypes */
5 static Eina_Bool _e_mod_quickpanel_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event);
6 static Eina_Bool _e_mod_quickpanel_cb_mouse_up(void *data, int type __UNUSED__, void *event);
7 static Eina_Bool _e_mod_quickpanel_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event);
8 static Eina_Bool _e_mod_quickpanel_cb_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event);
9 static Eina_Bool _e_mod_quickpanel_cb_border_resize(void *data __UNUSED__, int type __UNUSED__, void *event);
10 static Eina_Bool _e_mod_quickpanel_cb_border_uniconify(void *data __UNUSED__, int type __UNUSED__, void *event);
11 static void _e_mod_quickpanel_cb_post_fetch(void *data __UNUSED__, void *data2);
12 static void _e_mod_quickpanel_cb_free(E_Illume_Quickpanel *qp);
13 static Eina_Bool _e_mod_quickpanel_cb_delay_hide(void *data);
14 static void _e_mod_quickpanel_slide(E_Illume_Quickpanel *qp, int visible, double len);
15 static void _e_mod_quickpanel_hide(E_Illume_Quickpanel *qp);
16 static Eina_Bool _e_mod_quickpanel_cb_animate(void *data);
17 static void _e_mod_quickpanel_position_update(E_Illume_Quickpanel *qp);
18 static void _e_mod_quickpanel_animate_down(E_Illume_Quickpanel *qp);
19 static void _e_mod_quickpanel_animate_up(E_Illume_Quickpanel *qp);
20 static void _e_mod_quickpanel_clickwin_show(E_Illume_Quickpanel *qp);
21 static void _e_mod_quickpanel_clickwin_hide(E_Illume_Quickpanel *qp);
24 static Eina_List *_qp_hdls = NULL;
25 static E_Border_Hook *_qp_hook = NULL;
28 e_mod_quickpanel_init(void)
30 /* add handlers for messages we are interested in */
32 eina_list_append(_qp_hdls,
33 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
34 _e_mod_quickpanel_cb_client_message,
37 eina_list_append(_qp_hdls,
38 ecore_event_handler_add(E_EVENT_BORDER_ADD,
39 _e_mod_quickpanel_cb_border_add,
42 eina_list_append(_qp_hdls,
43 ecore_event_handler_add(E_EVENT_BORDER_REMOVE,
44 _e_mod_quickpanel_cb_border_remove,
47 eina_list_append(_qp_hdls,
48 ecore_event_handler_add(E_EVENT_BORDER_RESIZE,
49 _e_mod_quickpanel_cb_border_resize,
52 eina_list_append(_qp_hdls,
53 ecore_event_handler_add(E_EVENT_BORDER_UNICONIFY,
54 _e_mod_quickpanel_cb_border_uniconify,
57 /* add hook for new borders so we can test for qp borders */
58 _qp_hook = e_border_hook_add(E_BORDER_HOOK_EVAL_PRE_POST_FETCH,
59 _e_mod_quickpanel_cb_post_fetch, NULL);
65 e_mod_quickpanel_shutdown(void)
67 Ecore_Event_Handler *hdl;
69 /* delete the event handlers */
70 EINA_LIST_FREE(_qp_hdls, hdl)
71 ecore_event_handler_del(hdl);
73 /* delete the border hook */
74 if (_qp_hook) e_border_hook_del(_qp_hook);
81 e_mod_quickpanel_new(E_Zone *zone)
83 E_Illume_Quickpanel *qp;
85 /* try to allocate a new quickpanel object */
86 qp = E_OBJECT_ALLOC(E_Illume_Quickpanel, E_ILLUME_QP_TYPE,
87 _e_mod_quickpanel_cb_free);
90 /* set quickpanel zone */
93 qp->mouse_hdl = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
94 _e_mod_quickpanel_cb_mouse_up, qp);
100 e_mod_quickpanel_show(E_Illume_Quickpanel *qp)
102 E_Illume_Config_Zone *cz;
107 /* delete the animator if it exists */
108 if (qp->animator) ecore_animator_del(qp->animator);
111 /* delete any existing timer */
112 if (qp->timer) ecore_timer_del(qp->timer);
115 /* if it's already visible, or has no borders to show, then get out */
116 if ((qp->visible) || (!qp->borders)) return;
118 duration = _e_illume_cfg->animation.quickpanel.duration;
120 /* grab the height of the indicator */
121 cz = e_illume_zone_config_get(qp->zone->num);
122 qp->vert.isize = cz->indicator.size;
124 /* check animation duration */
132 if (qp->vert.dir == 1) ny = 0;
134 /* if we are not animating, just show the borders */
135 EINA_LIST_FOREACH(qp->borders, l, bd)
137 if (!bd->visible) e_illume_border_show(bd);
138 if (qp->vert.dir == 0)
140 e_border_fx_offset(bd, 0, ny);
146 e_border_fx_offset(bd, 0, ny);
150 _e_mod_quickpanel_clickwin_show(qp);
153 _e_mod_quickpanel_slide(qp, 1, (double)duration / 1000.0);
157 e_mod_quickpanel_hide(E_Illume_Quickpanel *qp)
159 if (!qp->visible) return;
161 qp->timer = ecore_timer_add(0.2, _e_mod_quickpanel_cb_delay_hide, qp);
164 /* local functions */
166 _e_mod_quickpanel_cb_client_message(void *data __UNUSED__, int type __UNUSED__, void *event)
168 Ecore_X_Event_Client_Message *ev;
171 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
175 if ((zone = e_util_zone_window_find(ev->win)))
177 E_Illume_Quickpanel *qp;
179 if ((qp = e_illume_quickpanel_by_zone_get(zone)))
181 if (ev->data.l[0] == (int)ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF)
182 _e_mod_quickpanel_hide(qp);
184 e_mod_quickpanel_show(qp);
188 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE)
192 if ((zone = e_util_zone_window_find(ev->win)))
194 E_Illume_Quickpanel *qp;
196 if ((qp = e_illume_quickpanel_by_zone_get(zone)))
199 _e_mod_quickpanel_hide(qp);
201 e_mod_quickpanel_show(qp);
205 else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE)
208 E_Illume_Quickpanel *qp;
210 if (!(bd = e_border_find_by_client_window(ev->win)))
211 return ECORE_CALLBACK_PASS_ON;
212 if (!(qp = e_illume_quickpanel_by_zone_get(bd->zone)))
213 return ECORE_CALLBACK_PASS_ON;
214 _e_mod_quickpanel_position_update(qp);
217 return ECORE_CALLBACK_PASS_ON;
221 _e_mod_quickpanel_cb_mouse_up(void *data, int type __UNUSED__, void *event)
223 Ecore_Event_Mouse_Button *ev;
224 E_Illume_Quickpanel *qp;
227 if (!(qp = data)) return ECORE_CALLBACK_PASS_ON;
228 if (ev->event_window != qp->clickwin) return ECORE_CALLBACK_PASS_ON;
229 if (qp->visible) e_mod_quickpanel_hide(qp);
230 return ECORE_CALLBACK_PASS_ON;
234 _e_mod_quickpanel_cb_border_add(void *data __UNUSED__, int type __UNUSED__, void *event)
236 E_Event_Border_Add *ev;
237 E_Illume_Quickpanel *qp;
242 if (!ev->border->client.illume.quickpanel.quickpanel)
243 return ECORE_CALLBACK_PASS_ON;
245 if (!(zone = ev->border->zone)) return ECORE_CALLBACK_PASS_ON;
247 /* if this border should be on a different zone, get requested zone */
248 if ((int)zone->num != ev->border->client.illume.quickpanel.zone)
254 if (!(con = e_container_current_get(e_manager_current_get())))
255 return ECORE_CALLBACK_PASS_ON;
256 zn = ev->border->client.illume.quickpanel.zone;
257 zone = e_util_container_zone_number_get(con->num, zn);
258 if (!zone) zone = e_util_container_zone_number_get(con->num, 0);
259 if (!zone) return ECORE_CALLBACK_PASS_ON;
262 if (!(qp = e_illume_quickpanel_by_zone_get(zone)))
263 return ECORE_CALLBACK_PASS_ON;
265 /* set position and zone */
266 e_illume_border_indicator_pos_get(zone, NULL, &iy);
267 if ((ev->border->x != zone->x) || (ev->border->y != iy))
268 e_border_move(ev->border, zone->x, iy);
269 if (ev->border->zone != zone)
270 e_border_zone_set(ev->border, zone);
272 /* hide this border */
273 e_illume_border_hide(ev->border);
275 qp->vert.size += ev->border->h;
277 /* add this border to QP border collection */
278 qp->borders = eina_list_append(qp->borders, ev->border);
280 return ECORE_CALLBACK_PASS_ON;
284 _e_mod_quickpanel_cb_border_remove(void *data __UNUSED__, int type __UNUSED__, void *event)
286 E_Event_Border_Remove *ev;
287 E_Illume_Quickpanel *qp;
293 if (!ev->border->client.illume.quickpanel.quickpanel)
294 return ECORE_CALLBACK_PASS_ON;
296 if (!(zone = ev->border->zone)) return ECORE_CALLBACK_PASS_ON;
298 /* if this border should be on a different zone, get requested zone */
299 if ((int)zone->num != ev->border->client.illume.quickpanel.zone)
305 if (!(con = e_container_current_get(e_manager_current_get())))
306 return ECORE_CALLBACK_PASS_ON;
307 zn = ev->border->client.illume.quickpanel.zone;
308 zone = e_util_container_zone_number_get(con->num, zn);
309 if (!zone) zone = e_util_container_zone_number_get(con->num, 0);
310 if (!zone) return ECORE_CALLBACK_PASS_ON;
313 if (!(qp = e_illume_quickpanel_by_zone_get(zone)))
314 return ECORE_CALLBACK_PASS_ON;
316 /* add this border to QP border collection */
318 qp->borders = eina_list_remove(qp->borders, ev->border);
321 EINA_LIST_FOREACH(qp->borders, l, bd)
322 qp->vert.size += bd->h;
324 return ECORE_CALLBACK_PASS_ON;
328 _e_mod_quickpanel_cb_border_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
330 E_Event_Border_Resize *ev;
331 E_Illume_Quickpanel *qp;
336 if (!ev->border->client.illume.quickpanel.quickpanel)
337 return ECORE_CALLBACK_PASS_ON;
338 if (!(qp = e_illume_quickpanel_by_zone_get(ev->border->zone)))
339 return ECORE_CALLBACK_PASS_ON;
342 EINA_LIST_FOREACH(qp->borders, l, bd)
343 qp->vert.size += bd->h;
345 return ECORE_CALLBACK_PASS_ON;
349 _e_mod_quickpanel_cb_border_uniconify(void *data __UNUSED__, int type __UNUSED__, void *event)
351 E_Event_Border_Uniconify *ev;
352 E_Illume_Quickpanel *qp;
355 if (!ev->border->client.illume.quickpanel.quickpanel)
356 return ECORE_CALLBACK_PASS_ON;
357 if (!(qp = e_illume_quickpanel_by_zone_get(ev->border->zone)))
358 return ECORE_CALLBACK_PASS_ON;
359 e_mod_quickpanel_show(qp);
360 return ECORE_CALLBACK_PASS_ON;
364 _e_mod_quickpanel_cb_post_fetch(void *data __UNUSED__, void *data2)
368 if (!(bd = data2)) return;
369 if (!bd->client.illume.quickpanel.quickpanel) return;
374 _e_mod_quickpanel_cb_free(E_Illume_Quickpanel *qp)
378 /* delete the animator if it exists */
379 if (qp->animator) ecore_animator_del(qp->animator);
382 /* delete the timer if it exists */
383 if (qp->timer) ecore_timer_del(qp->timer);
386 /* delete the clickwin */
387 if (qp->clickwin) ecore_x_window_free(qp->clickwin);
390 /* delete the mouse handler */
391 if (qp->mouse_hdl) ecore_event_handler_del(qp->mouse_hdl);
392 qp->mouse_hdl = NULL;
394 /* set the borders of this quickpanel to not stolen */
395 EINA_LIST_FREE(qp->borders, bd)
398 /* free the structure */
403 _e_mod_quickpanel_cb_delay_hide(void *data)
405 E_Illume_Quickpanel *qp;
407 if (!(qp = data)) return ECORE_CALLBACK_CANCEL;
408 _e_mod_quickpanel_hide(qp);
409 return ECORE_CALLBACK_CANCEL;
413 _e_mod_quickpanel_slide(E_Illume_Quickpanel *qp, int visible, double len)
416 qp->start = ecore_loop_time_get();
418 qp->vert.adjust_start = qp->vert.adjust;
419 qp->vert.adjust_end = 0;
420 if (qp->vert.dir == 0)
422 if (visible) qp->vert.adjust_end = qp->vert.size;
426 if (visible) qp->vert.adjust_end = -qp->vert.size;
430 qp->animator = ecore_animator_add(_e_mod_quickpanel_cb_animate, qp);
434 _e_mod_quickpanel_hide(E_Illume_Quickpanel *qp)
440 /* delete the animator if it exists */
441 if (qp->animator) ecore_animator_del(qp->animator);
444 /* delete the timer if it exists */
445 if (qp->timer) ecore_timer_del(qp->timer);
448 /* if it's not visible, we can't hide it */
449 if (!qp->visible) return;
451 duration = _e_illume_cfg->animation.quickpanel.duration;
458 /* if we are not animating, hide the qp borders */
459 EINA_LIST_REVERSE_FOREACH(qp->borders, l, bd)
461 e_border_fx_offset(bd, 0, 0);
462 if (bd->visible) e_illume_border_hide(bd);
465 _e_mod_quickpanel_clickwin_hide(qp);
468 _e_mod_quickpanel_slide(qp, 0, (double)duration / 1000.0);
472 _e_mod_quickpanel_cb_animate(void *data)
474 E_Illume_Quickpanel *qp;
477 if (!(qp = data)) return ECORE_CALLBACK_CANCEL;
478 t = (ecore_loop_time_get() - qp->start);
479 if (t > qp->len) t = qp->len;
490 qp->vert.adjust = ((qp->vert.adjust_end * v) +
491 (qp->vert.adjust_start * (1.0 - v)));
493 if (qp->vert.dir == 0) _e_mod_quickpanel_animate_down(qp);
494 else _e_mod_quickpanel_animate_up(qp);
502 _e_mod_quickpanel_clickwin_hide(qp);
507 _e_mod_quickpanel_clickwin_show(qp);
509 return ECORE_CALLBACK_CANCEL;
512 return ECORE_CALLBACK_RENEW;
516 _e_mod_quickpanel_position_update(E_Illume_Quickpanel *qp)
523 _e_mod_quickpanel_hide(qp);
524 if (!qp->zone) return;
525 e_illume_border_indicator_pos_get(qp->zone, NULL, &iy);
526 EINA_LIST_FOREACH(qp->borders, l, bd)
527 e_border_move(bd, qp->zone->x, iy);
530 if ((iy + qp->vert.isize + qp->vert.size) > qp->zone->h) qp->vert.dir = 1;
534 _e_mod_quickpanel_animate_down(E_Illume_Quickpanel *qp)
541 pbh = (qp->vert.isize - qp->vert.size);
542 EINA_LIST_FOREACH(qp->borders, l, bd)
544 /* don't adjust borders that are being deleted */
545 if (e_object_is_del(E_OBJECT(bd))) continue;
546 if (bd->fx.y != (qp->vert.adjust + pbh))
547 e_border_fx_offset(bd, 0, (qp->vert.adjust + pbh));
554 if (!bd->visible) e_illume_border_show(bd);
561 if (bd->visible) e_illume_border_hide(bd);
568 _e_mod_quickpanel_animate_up(E_Illume_Quickpanel *qp)
576 EINA_LIST_FOREACH(qp->borders, l, bd)
578 /* don't adjust borders that are being deleted */
579 if (e_object_is_del(E_OBJECT(bd))) continue;
581 if (bd->fx.y != (qp->vert.adjust + pbh))
582 e_border_fx_offset(bd, 0, (qp->vert.adjust + pbh));
588 if (!bd->visible) e_illume_border_show(bd);
595 if (bd->visible) e_illume_border_hide(bd);
602 _e_mod_quickpanel_clickwin_show(E_Illume_Quickpanel *qp)
606 if ((!qp) || (!qp->borders) || (!qp->zone)) return;
607 if (!(ind = eina_list_nth(qp->borders, 0))) return;
609 if (qp->clickwin) ecore_x_window_free(qp->clickwin);
611 qp->clickwin = ecore_x_window_input_new(qp->zone->container->win,
612 qp->zone->x, qp->zone->y,
613 qp->zone->w, qp->zone->h);
615 ecore_x_window_configure(qp->clickwin,
616 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
617 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
618 qp->zone->x, qp->zone->y,
619 qp->zone->w, qp->zone->h, 0,
620 ind->win, ECORE_X_WINDOW_STACK_BELOW);
622 ecore_x_window_show(qp->clickwin);
626 _e_mod_quickpanel_clickwin_hide(E_Illume_Quickpanel *qp)
629 if (qp->clickwin) ecore_x_window_free(qp->clickwin);