//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; }
//Popup the menu at the position (x, y) void eclair_menu_popup_at_xy(Eclair_Menu *menu, int x, int y) { if (!menu) return; if (!_eclair_menu_input_window) { Ecore_X_Window root, parent; int root_x, root_y, root_w, root_h; 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); } if (!_eclair_menu_root) { _eclair_menu_mouse_up_handler = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_UP, _eclair_menu_mouse_up_cb, menu); _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_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, ecore_x_current_time_get(), NULL); evas_event_feed_mouse_in(menu->evas, ecore_x_current_time_get(), NULL); _eclair_menu_popped_menus = eina_list_append(_eclair_menu_popped_menus, menu); _eclair_menu_update_slide_timer(menu); }
//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; }
EAPI int elm_main(int argc, char **argv) { Ecore_X_Window *roots = NULL; int num = 0, i = 0; roots = ecore_x_window_root_list(&num); if ((!roots) || (num <= 0)) return EXIT_FAILURE; for (i = 0; i < num; i++) { Ecore_X_Window *zones; int x = 0, count = 0; count = ecore_x_window_prop_window_list_get(roots[i], ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zones); if (!zones) continue; for (x = 0; x < count; x++) { Evas_Object *win; Evas_Object *bg, *box, *btn, *icon; Ecore_X_Window xwin; Ecore_X_Window_State states[2]; char buff[PATH_MAX]; int zx, zy, zw, zh; /* create new window */ win = elm_win_add(NULL, "Illume-Softkey", ELM_WIN_DOCK); elm_win_title_set(win, "Illume Softkey"); evas_object_smart_callback_add(win, "delete-request", _cb_win_del, NULL); evas_object_data_set(win, "zone", (const void *)zones[x]); xwin = elm_win_xwindow_get(win); ecore_x_icccm_hints_set(xwin, 0, 0, 0, 0, 0, 0, 0); states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR; states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER; ecore_x_netwm_window_state_set(xwin, states, 2); bg = elm_bg_add(win); evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, bg); evas_object_show(bg); box = elm_box_add(win); elm_box_horizontal_set(box, EINA_TRUE); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, box); evas_object_show(box); icon = elm_icon_add(win); snprintf(buff, sizeof(buff), "%s/images/back.png", PACKAGE_DATA_DIR); elm_icon_file_set(icon, buff, NULL); evas_object_size_hint_aspect_set(icon, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); btn = elm_button_add(win); elm_button_icon_set(btn, icon); evas_object_smart_callback_add(btn, "clicked", _cb_btn_back_clicked, win); evas_object_size_hint_align_set(btn, 1.0, 0.5); elm_box_pack_end(box, btn); evas_object_show(btn); evas_object_show(icon); icon = elm_icon_add(win); snprintf(buff, sizeof(buff), "%s/images/close.png", PACKAGE_DATA_DIR); elm_icon_file_set(icon, buff, NULL); evas_object_size_hint_aspect_set(icon, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); btn = elm_button_add(win); elm_button_icon_set(btn, icon); evas_object_smart_callback_add(btn, "clicked", _cb_btn_close_clicked, win); evas_object_size_hint_align_set(btn, 1.0, 0.5); elm_box_pack_end(box, btn); evas_object_show(btn); evas_object_show(icon); ecore_x_window_geometry_get(zones[x], &zx, &zy, &zw, &zh); ecore_x_e_illume_softkey_geometry_set(zones[x], zx, (zy + zh - 40), zw, 40); evas_object_move(win, zx, (zy + zh - 40)); evas_object_resize(win, zw, 40); evas_object_show(win); } free(zones); } free(roots); elm_run(); elm_shutdown(); return EXIT_SUCCESS; }
static Window _ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y, Ecore_X_Window *skip, int skip_num) { Window *list = NULL; Window parent_win = 0, child = 0, root_win = 0; int i, j, wx, wy, ww, wh; unsigned int num; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!ecore_x_window_visible_get(base)) return 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh); wx += bx; wy += by; if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh)))) return 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num)) return base; if (list) { int skipit = 0; for (i = num - 1; i >= 0; --i) { skipit = 0; if (skip) for (j = 0; j < skip_num; j++) { if (list[i] == skip[j]) { skipit = 1; goto onward; } } onward: if (!skipit) if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, skip_num))) { XFree(list); return child; } } XFree(list); } return base; }
//Slide the menu (called every 1/60 sec) static int _eclair_menu_slide_timer_cb(void *data) { Eclair_Menu *menu = NULL, *m; Eina_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, ecore_x_current_time_get(), NULL); } return 1; }