#include "e.h" /* local subsystem globals */ static Eina_List *_e_popup_list = NULL; static E_Popup *autoclose_popup = NULL; static Ecore_Event_Handler *autoclose_handlers[4] = {NULL}; static Eina_Bool autoclose_down_obj = EINA_FALSE; static unsigned int autoclose_event = 0; /* local subsystem functions */ static void _e_popup_autoclose_cleanup(void) { if (autoclose_popup) e_grabinput_release(0, e_comp_get(autoclose_popup)->ee_win); E_FN_DEL(e_object_del, autoclose_popup); E_FN_DEL(ecore_event_handler_del, autoclose_handlers[0]); E_FN_DEL(ecore_event_handler_del, autoclose_handlers[1]); E_FN_DEL(ecore_event_handler_del, autoclose_handlers[2]); E_FN_DEL(ecore_event_handler_del, autoclose_handlers[3]); autoclose_down_obj = 0; } static void _e_popup_free(E_Popup *pop) { e_object_unref(E_OBJECT(pop->zone)); if (pop->autoclose) _e_popup_autoclose_cleanup(); E_FN_DEL(e_object_del, pop->shape); E_FREE_LIST(pop->objects, evas_object_del); pop->zone->popups = eina_list_remove(pop->zone->popups, pop); eina_stringshare_del(pop->name); _e_popup_list = eina_list_remove(_e_popup_list, pop); free(pop); } static void _e_popup_obj_autoclose_mouse_down_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { autoclose_down_obj = 1; } static Eina_Bool _e_popup_autoclose_focus_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED) { _e_popup_autoclose_cleanup(); return ECORE_CALLBACK_RENEW; } static Eina_Bool _e_popup_autoclose_key_down_cb(void *data, int type EINA_UNUSED, void *event) { Ecore_Event_Key *ev = event; Eina_Bool del = EINA_TRUE; if (autoclose_popup->key_cb) del = !autoclose_popup->key_cb(data, ev); if (del) _e_popup_autoclose_cleanup(); return ECORE_CALLBACK_RENEW; } static Eina_Bool _e_popup_autoclose_mouse_up_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { Ecore_Event_Mouse_Button *ev = event; if (autoclose_event && ((!autoclose_down_obj) || (ev->event_window != e_comp_get(autoclose_popup)->ee_win))) _e_popup_autoclose_cleanup(); else autoclose_event++; autoclose_down_obj = 0; return ECORE_CALLBACK_RENEW; } static Eina_Bool _e_popup_autoclose_mouse_down_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { Ecore_Event_Mouse_Button *ev = event; if (ev->event_window != e_comp_get(autoclose_popup)->ee_win) _e_popup_autoclose_cleanup(); autoclose_event++; return ECORE_CALLBACK_RENEW; } static void _e_popup_autoclose_setup(E_Popup *pop) { E_FN_DEL(e_object_del, autoclose_popup); autoclose_event = 0; evas_object_event_callback_add(pop->content, EVAS_CALLBACK_MOUSE_DOWN, _e_popup_obj_autoclose_mouse_down_cb, NULL); autoclose_popup = pop; if (autoclose_handlers[0]) ecore_event_handler_data_set(autoclose_handlers[0], pop->key_data); else autoclose_handlers[0] = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_popup_autoclose_mouse_down_cb, pop->key_data); if (autoclose_handlers[1]) ecore_event_handler_data_set(autoclose_handlers[1], pop->key_data); else autoclose_handlers[1] = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _e_popup_autoclose_mouse_up_cb, pop->key_data); if (autoclose_handlers[2]) ecore_event_handler_data_set(autoclose_handlers[2], pop->key_data); else autoclose_handlers[2] = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_popup_autoclose_key_down_cb, pop->key_data); if (autoclose_handlers[3]) ecore_event_handler_data_set(autoclose_handlers[3], pop->key_data); else autoclose_handlers[3] = ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, _e_popup_autoclose_focus_cb, pop->key_data); e_grabinput_get(0, 0, e_comp_get(pop)->ee_win); } /* externally accessible functions */ EINTERN int e_popup_init(void) { return 1; } EINTERN int e_popup_shutdown(void) { _e_popup_autoclose_cleanup(); return 1; } EAPI E_Popup * e_popup_new(E_Zone *zone, int x, int y, int w, int h) { E_Popup *pop; pop = E_OBJECT_ALLOC(E_Popup, E_POPUP_TYPE, _e_popup_free); if (!pop) return NULL; e_object_delay_del_set(E_OBJECT(pop), e_popup_hide); pop->zone = zone; pop->ecore_evas = zone->container->bg_ecore_evas; pop->zx = pop->zone->x; pop->zy = pop->zone->y; pop->x = x; pop->y = y; pop->w = w; pop->h = h; pop->layer = E_LAYER_POPUP; pop->comp_layer = E_COMP_CANVAS_LAYER_LAYOUT; pop->evas = e_comp_get(zone)->evas; pop->shape = e_container_shape_add(zone->container); e_object_ref(E_OBJECT(pop->zone)); pop->zone->popups = eina_list_append(pop->zone->popups, pop); _e_popup_list = eina_list_append(_e_popup_list, pop); return pop; } EAPI void e_popup_content_set(E_Popup *pop, Evas_Object *obj) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); if (pop->content) evas_object_del(pop->content); pop->content = obj; evas_object_data_set(obj, "eobj", pop); evas_object_move(obj, pop->zone->x + pop->x, pop->zone->y + pop->y); evas_object_resize(obj, pop->w, pop->h); e_popup_layer_set(pop, pop->comp_layer, pop->layer); e_popup_ignore_events_set(pop, pop->ignore_events); if (pop->visible) { e_comp_win_moveresize(pop->cw, pop->zone->x + pop->x, pop->zone->y + pop->y, pop->w, pop->h); evas_object_show(obj); } } EAPI void e_popup_show(E_Popup *pop) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); if (pop->visible) return; pop->visible = 1; e_comp_win_moveresize(pop->cw, pop->zone->x + pop->x, pop->zone->y + pop->y, pop->w, pop->h); e_comp_win_show(pop->cw); if (pop->autoclose) _e_popup_autoclose_setup(pop); } EAPI void e_popup_hide(E_Popup *pop) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); if (!pop->visible) return; pop->visible = 0; e_comp_win_hide(pop->cw); if (!pop->autoclose) return; if (e_object_is_del(E_OBJECT(pop))) return; autoclose_popup = NULL; _e_popup_autoclose_cleanup(); } EAPI void e_popup_move(E_Popup *pop, int x, int y) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); if ((pop->x == x) && (pop->y == y) && (pop->zone->x == pop->zx) && (pop->zone->y == pop->zy)) return; pop->zx = pop->zone->x; pop->zy = pop->zone->y; pop->x = x; pop->y = y; if (!pop->cw) return; e_comp_win_move(pop->cw, pop->zone->x + pop->x, pop->zone->y + pop->y); } EAPI void e_popup_resize(E_Popup *pop, int w, int h) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); if ((pop->w == w) && (pop->h == h)) return; pop->w = w; pop->h = h; if (!pop->cw) return; e_comp_win_resize(pop->cw, pop->w, pop->h); } EAPI void e_popup_move_resize(E_Popup *pop, int x, int y, int w, int h) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); if ((pop->x == x) && (pop->y == y) && (pop->w == w) && (pop->h == h) && (pop->zone->x == pop->zx) && (pop->zone->y == pop->zy)) return; pop->x = x; pop->y = y; pop->w = w; pop->h = h; if (!pop->cw) return; e_comp_win_moveresize(pop->cw, pop->zone->x + x, pop->zone->y + y, w, h); } EAPI void e_popup_ignore_events_set(E_Popup *pop, int ignore) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); ignore = !!ignore; pop->ignore_events = ignore; if (pop->cw) e_comp_win_ignore_events_set(pop->cw, ignore); } EAPI void e_popup_layer_set(E_Popup *pop, E_Comp_Canvas_Layer comp_layer, E_Layer layer) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); pop->comp_layer = comp_layer; pop->layer = layer; if (!pop->content) return; if (comp_layer == E_COMP_CANVAS_LAYER_LAYOUT) E_LAYER_LAYOUT_ADD(pop->content, layer); else E_LAYER_SET_ABOVE(pop->content, comp_layer); } EAPI void e_popup_name_set(E_Popup *pop, const char *name) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); eina_stringshare_replace(&pop->name, name); } EAPI void e_popup_object_add(E_Popup *pop, Evas_Object *obj) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); pop->objects = eina_list_append(pop->objects, obj); } EAPI void e_popup_autoclose(E_Popup *pop, E_Popup_Key_Cb cb, const void *data) { E_OBJECT_CHECK(pop); E_OBJECT_TYPE_CHECK(pop, E_POPUP_TYPE); pop->autoclose = 1; pop->key_cb = cb; pop->key_data = (void*)data; if (!pop->visible) return; _e_popup_autoclose_setup(pop); }