Enlightenment CVS committal Author : moom16 Project : e17 Module : apps/eclair
Dir : e17/apps/eclair/src Modified Files: eclair_menu.c eclair_menu.h Log Message: Some work on the menu widget: * Make the menu slide when it doesn't fit in the screen * Add the glint effect on menu items * Fix a min_size edje problem with menu item =================================================================== RCS file: /cvsroot/enlightenment/e17/apps/eclair/src/eclair_menu.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -3 -r1.2 -r1.3 --- eclair_menu.c 13 Jul 2005 22:32:31 -0000 1.2 +++ eclair_menu.c 14 Jul 2005 20:55:07 -0000 1.3 @@ -7,8 +7,22 @@ #define ECLAIR_WIDGETS_THEME PACKAGE_DATA_DIR "/widget_themes/default.edj" #endif +typedef enum _Eclair_Menu_Screen_Edge +{ + ECLAIR_MENU_NO_EDGE = 0, + ECLAIR_MENU_LEFT_EDGE = (1 << 0), + ECLAIR_MENU_RIGHT_EDGE = (1 << 1), + ECLAIR_MENU_BOTTOM_EDGE = (1 << 2), + ECLAIR_MENU_TOP_EDGE = (1 << 3) +} Eclair_Menu_Screen_Edge; + static void _eclair_menu_recalc(Eclair_Menu *menu); static void _eclair_menu_resize_cb(Ecore_Evas *menu_window); +static Eclair_Menu_Screen_Edge _eclair_menu_over_screen_edge(Eclair_Menu *menu); +static Eclair_Menu_Screen_Edge _eclair_menu_mouse_on_screen_edge(); +static int _eclair_menu_mouse_is_in(Eclair_Menu *menu); +static void _eclair_menu_update_slide_timer(Eclair_Menu *menu); +static int _eclair_menu_slide_timer_cb(void *data); static int _eclair_menu_mouse_up_cb(void *data, int type, void *event); static int _eclair_menu_mouse_move_cb(void *data, int type, void *event); static void _eclair_menu_item_in_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); @@ -20,9 +34,9 @@ static Evas_List *_eclair_menu_popped_menus = NULL; static Ecore_Event_Handler *_eclair_menu_mouse_up_handler = NULL; static Ecore_Event_Handler *_eclair_menu_mouse_move_handler = NULL; -static int prev_mouse_x = -100000; -static int prev_mouse_y = -100000; - +static Ecore_Timer *_eclair_menu_slide_timer = NULL; +static int _eclair_menu_mouse_x = -100000; +static int _eclair_menu_mouse_y = -100000; //------------------------------ // Eclair_Menu @@ -84,6 +98,7 @@ if (!menu) return; + eclair_menu_pop_down(menu); for (l = menu->items; l; l = l->next) { if ((item = l->data)) @@ -133,9 +148,6 @@ { int x, y; - if (!menu) - return; - ecore_x_pointer_last_xy_get(&x, &y); eclair_menu_popup_at_xy(menu, x, y); } @@ -148,10 +160,13 @@ if (!_eclair_menu_input_window) { - Ecore_X_Window root; + Ecore_X_Window root, parent; int root_x, root_y, root_w, root_h; - root = ecore_x_window_root_first_get(); + root = menu->x_window; + while ((parent = ecore_x_window_parent_get(root)) != 0) + root = parent; + ecore_x_window_geometry_get(root, &root_x, &root_y, &root_w, &root_h); _eclair_menu_input_window = ecore_x_window_input_new(root, root_x, root_y, root_w, root_h); } @@ -161,13 +176,17 @@ _eclair_menu_mouse_move_handler = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_MOVE, _eclair_menu_mouse_move_cb, menu); ecore_x_window_show(_eclair_menu_input_window); ecore_x_keyboard_grab(_eclair_menu_input_window); - ecore_x_pointer_grab(_eclair_menu_input_window); + ecore_x_pointer_confine_grab(_eclair_menu_input_window); _eclair_menu_root = menu; } ecore_evas_move(menu->window, x, y); ecore_evas_show(menu->window); + evas_event_feed_mouse_move(menu->evas, -100000, -100000, NULL); + evas_event_feed_mouse_in(menu->evas, NULL); _eclair_menu_popped_menus = evas_list_append(_eclair_menu_popped_menus, menu); + + _eclair_menu_update_slide_timer(menu); } //Pop down the menu and its childrend @@ -206,7 +225,7 @@ //Return NULL if failed Eclair_Menu_Item *eclair_menu_add_item(Eclair_Menu *menu, const char *label) { - return eclair_menu_item_new(label, menu, ECLAIR_MENU_ITEM_NORMAL_ITEM, ""); + return eclair_menu_item_new(label, menu, ECLAIR_MENU_ITEM_NORMAL_ITEM, NULL); } //Create a new menu item with an icon @@ -222,7 +241,7 @@ //Return NULL if failed Eclair_Menu_Item *eclair_menu_add_seperator(Eclair_Menu *menu) { - return eclair_menu_item_new("", menu, ECLAIR_MENU_ITEM_SEPARATOR_ITEM, ""); + return eclair_menu_item_new(NULL, menu, ECLAIR_MENU_ITEM_SEPARATOR_ITEM, NULL); } //Calculate the size of the menu, resize it and display the arrows if needed @@ -270,8 +289,8 @@ continue; edje_object_size_min_calc(item->edje_object, &item_w, &item->height); - if (w < item_w + 30) - w = item_w + 30; + if (w < item_w) + w = item_w; h += item->height; } ecore_evas_resize(menu->window, w, h); @@ -303,13 +322,171 @@ } } +//Return a flag incating on which edges of the screen the menu is over +static Eclair_Menu_Screen_Edge _eclair_menu_over_screen_edge(Eclair_Menu *menu) +{ + int root_x, root_y, root_w, root_h; + int menu_x, menu_y, menu_w, menu_h; + Eclair_Menu_Screen_Edge result = ECLAIR_MENU_NO_EDGE; + + if (!menu) + return ECLAIR_MENU_NO_EDGE; + + ecore_x_window_geometry_get(_eclair_menu_input_window, &root_x, &root_y, &root_w, &root_h); + ecore_evas_geometry_get(menu->window, &menu_x, &menu_y, &menu_w, &menu_h); + + if (menu_x < root_x) + { + result |= ECLAIR_MENU_LEFT_EDGE; + } + if (menu_x + menu_w > root_x + root_w) + result |= ECLAIR_MENU_RIGHT_EDGE; + if (menu_y < root_y) + result |= ECLAIR_MENU_TOP_EDGE; + if (menu_y + menu_h > root_y + root_h) + result |= ECLAIR_MENU_BOTTOM_EDGE; + + return result; +} + +//Return a flag incating on which edges of the screen the mouse pointer is +static Eclair_Menu_Screen_Edge _eclair_menu_mouse_on_screen_edge() +{ + int root_x, root_y, root_w, root_h; + Eclair_Menu_Screen_Edge result = ECLAIR_MENU_NO_EDGE; + + ecore_x_window_geometry_get(_eclair_menu_input_window, &root_x, &root_y, &root_w, &root_h); + if (_eclair_menu_mouse_x - root_x + 1 >= root_w) + result |= ECLAIR_MENU_RIGHT_EDGE; + if (_eclair_menu_mouse_x <= root_x) + result |= ECLAIR_MENU_LEFT_EDGE; + if (_eclair_menu_mouse_y - root_y + 1 >= root_h) + result |= ECLAIR_MENU_BOTTOM_EDGE; + if (_eclair_menu_mouse_y <= root_y) + result |= ECLAIR_MENU_TOP_EDGE; + + return result; +} + +//Return 1 is the mouse is in the menu +static int _eclair_menu_mouse_is_in(Eclair_Menu *menu) +{ + int menu_x, menu_y, menu_w, menu_h; + + if (!menu) + return 0; + + ecore_evas_geometry_get(menu->window, &menu_x, &menu_y, &menu_w, &menu_h); + return (_eclair_menu_mouse_x >= menu_x && _eclair_menu_mouse_x <= menu_x + menu_w + && _eclair_menu_mouse_y >= menu_y && _eclair_menu_mouse_x <= menu_y + menu_h); +} + +//Start the slide timer if needed +static void _eclair_menu_update_slide_timer(Eclair_Menu *menu) +{ + Eclair_Menu_Screen_Edge mouse_on_edge, menu_over_edge; + + if (!menu) + return; + + mouse_on_edge = _eclair_menu_mouse_on_screen_edge(); + menu_over_edge = _eclair_menu_over_screen_edge(menu); + if (!_eclair_menu_slide_timer && (mouse_on_edge & menu_over_edge) != ECLAIR_MENU_NO_EDGE) + _eclair_menu_slide_timer = ecore_timer_add(1.0 / 60.0, _eclair_menu_slide_timer_cb, NULL); +} + +//Slide the menu (called every 1/60 sec) +static int _eclair_menu_slide_timer_cb(void *data) +{ + Eclair_Menu *menu = NULL, *m; + Evas_List *l; + Eclair_Menu_Screen_Edge mouse_edge, menu_edge = ECLAIR_MENU_NO_EDGE; + int root_x, root_y, root_w, root_h; + int menu_x, menu_y, menu_w, menu_h; + int x, y; + int dx = 0, dy = 0, max_delta = (int)(1.0 / 60.0 * 800); + + //TODO: FIXME: We could have problem with menus bigger than the screen width + + //We first look the menu that is over an edge of the screen + for (l = _eclair_menu_popped_menus; l; l = l->next) + { + if (!(m = l->data)) + continue; + + if ((menu_edge = _eclair_menu_over_screen_edge(m)) != ECLAIR_MENU_NO_EDGE) + { + menu = m; + break; + } + } + if (!menu) + { + _eclair_menu_slide_timer = NULL; + return 0; + } + + //Then we move all the menu windows in the right direction + mouse_edge = _eclair_menu_mouse_on_screen_edge(); + ecore_x_window_geometry_get(_eclair_menu_input_window, &root_x, &root_y, &root_w, &root_h); + ecore_evas_geometry_get(menu->window, &menu_x, &menu_y, &menu_w, &menu_h); + if (mouse_edge & menu_edge & ECLAIR_MENU_LEFT_EDGE) + { + if (max_delta < root_x - menu_x) + dx = max_delta; + else + dx = root_x - menu_x; + } + if (mouse_edge & menu_edge & ECLAIR_MENU_RIGHT_EDGE) + { + if (max_delta < menu_w - root_x - root_w + menu_x) + dx = -max_delta; + else + dx = -menu_w + root_x + root_w - menu_x; + } + if (mouse_edge & menu_edge & ECLAIR_MENU_TOP_EDGE) + { + if (max_delta < root_y - menu_y) + dy = max_delta; + else + dy = root_y - menu_y; + } + if (mouse_edge & menu_edge & ECLAIR_MENU_BOTTOM_EDGE) + { + if (max_delta < menu_h - root_y - root_h + menu_y) + dy = -max_delta; + else + dy = -menu_h + root_y + root_h - menu_y; + } + + if (dx == 0 && dy == 0) + { + _eclair_menu_slide_timer = NULL; + return 0; + } + + for (l = _eclair_menu_popped_menus; l; l = l->next) + { + if (!(m = l->data)) + continue; + + ecore_evas_geometry_get(m->window, &x, &y, NULL, NULL); + ecore_evas_move(m->window, x + dx, y + dy); + + //We feed a mouse move event since the relative position between + //the mouse pointer and the menu window has changed + evas_event_feed_mouse_move(m->evas, _eclair_menu_mouse_x - x, _eclair_menu_mouse_y - y, NULL); + } + + return 1; +} + //Pop down the menus if needed and feed the mouse up event to the menu window static int _eclair_menu_mouse_up_cb(void *data, int type, void *event) { Eclair_Menu *menu, *m; Evas_List *l; Ecore_X_Event_Mouse_Button_Up *mouse_event; - int x, y, w, h; int pointer_over_menu = 0; mouse_event = event; @@ -322,9 +499,7 @@ if (!(m = l->data)) continue; - ecore_evas_geometry_get(m->window, &x, &y, &w, &h); - if ((mouse_event->x >= x) && (mouse_event->x <= x + w) && - (mouse_event->y >= y) && (mouse_event->y <= y + h)) + if (_eclair_menu_mouse_is_in(m)) { pointer_over_menu = 1; evas_event_feed_mouse_up(m->evas, mouse_event->button, EVAS_BUTTON_NONE, NULL); @@ -336,44 +511,33 @@ return 1; } -//Feed the mouse move, in and out events to the menu windows +//Feed the mouse move, in and out events to the menu windows and start to slide the windows if needed static int _eclair_menu_mouse_move_cb(void *data, int type, void *event) { Eclair_Menu *menu, *m; Evas_List *l; Ecore_X_Event_Mouse_Move *mouse_event; - int menu_x, menu_y, menu_w, menu_h; - int mouse_in; + int menu_x, menu_y; mouse_event = event; if (!(menu = data) || mouse_event->win != _eclair_menu_input_window) return 1; + _eclair_menu_mouse_x = mouse_event->x; + _eclair_menu_mouse_y = mouse_event->y; + for (l = _eclair_menu_popped_menus; l; l = l->next) { if (!(m = l->data)) continue; - ecore_evas_geometry_get(m->window, &menu_x, &menu_y, &menu_w, &menu_h); + ecore_evas_geometry_get(m->window, &menu_x, &menu_y, NULL, NULL); evas_event_feed_mouse_move(m->evas, mouse_event->x - menu_x, mouse_event->y - menu_y, NULL); - - mouse_in = (mouse_event->x >= menu_x && mouse_event->x <= menu_x + menu_w && - mouse_event->y >= menu_y && mouse_event->y <= menu_y + menu_h); - if (m->mouse_in && !mouse_in) - { - evas_event_feed_mouse_out(m->evas, NULL); - m->mouse_in = 0; - } - else if (!m->mouse_in && mouse_in) - { - evas_event_feed_mouse_in(m->evas, NULL); - m->mouse_in = 1; - } + + //Start to slide the menu window if we need + _eclair_menu_update_slide_timer(m); } - prev_mouse_x = mouse_event->x; - prev_mouse_y = mouse_event->y; - return 1; } @@ -433,10 +597,12 @@ { icon_size = atoi(icon_size_str); evas_object_image_fill_set(item->icon_object, 0, 0, icon_size, icon_size); + free(icon_size_str); } else evas_object_image_fill_set(item->icon_object, 0, 0, 16, 16); edje_object_part_swallow(item->edje_object, "icon", item->icon_object); + evas_object_pass_events_set(item->icon_object, 1); evas_object_show(item->edje_object); } } @@ -483,11 +649,15 @@ free(item->label); if (!label) - item->label = strdup(""); + { + item->label = NULL; + edje_object_part_text_set(item->edje_object, "label", ""); + } else + { item->label = strdup(label); - - edje_object_part_text_set(item->edje_object, "label", item->label); + edje_object_part_text_set(item->edje_object, "label", item->label); + } _eclair_menu_recalc(item->parent); } =================================================================== RCS file: /cvsroot/enlightenment/e17/apps/eclair/src/eclair_menu.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -3 -r1.1 -r1.2 --- eclair_menu.h 13 Jul 2005 21:27:43 -0000 1.1 +++ eclair_menu.h 14 Jul 2005 20:55:08 -0000 1.2 @@ -15,7 +15,6 @@ Ecore_X_Window x_window; Evas *evas; Evas_Object *edje_object; - unsigned char mouse_in : 1; }; enum _Eclair_Menu_Item_Type @@ -35,9 +34,9 @@ Evas_Object *icon_object; int height; Eclair_Menu_Item_Type type; - unsigned char is_active : 1; void (*item_cb)(Eclair_Menu_Item *item, void *data); void *cb_data; + int is_active : 1; }; Eclair_Menu *eclair_menu_new(Eclair_Engine menu_engine); ------------------------------------------------------- SF.Net email is sponsored by: Discover Easy Linux Migration Strategies from IBM. Find simple to follow Roadmaps, straightforward articles, informative Webcasts and more! Get everything you need to get up to speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs