#include "e.h" #include "e_mod_main.h" #include "e_mod_ind_win.h" /* local function prototypes */ static void _e_mod_ind_win_cb_free(Ind_Win *iwin); static int _e_mod_ind_win_cb_win_prop(void *data, int type __UNUSED__, void *event); static int _e_mod_ind_win_cb_zone_resize(void *data, int type __UNUSED__, void *event); static void _e_mod_ind_win_cb_resize(E_Win *win); static void _e_mod_ind_win_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event); static void _e_mod_ind_win_cb_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event); static void _e_mod_ind_win_cb_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event); static void _e_mod_ind_win_cb_min_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h); static void _e_mod_ind_win_cb_size_request(void *data __UNUSED__, E_Gadcon *gc __UNUSED__, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__); static Evas_Object *_e_mod_ind_win_cb_frame_request(void *data __UNUSED__, E_Gadcon_Client *gcc __UNUSED__, const char *style __UNUSED__); static void _e_mod_ind_win_cb_menu_items_append(void *data, E_Gadcon_Client *gcc __UNUSED__, E_Menu *mn); static void _e_mod_ind_win_cb_menu_append(Ind_Win *iwin, E_Menu *mn); static void _e_mod_ind_win_cb_menu_pre(void *data, E_Menu *mn); static void _e_mod_ind_win_cb_menu_post(void *data, E_Menu *mn __UNUSED__); static void _e_mod_ind_win_cb_menu_contents(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__); static void _e_mod_ind_win_cb_menu_edit(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__); Ind_Win * e_mod_ind_win_new(E_Zone *zone) { Ind_Win *iwin; Ecore_X_Window_State states[2]; /* create our new indicator window object */ iwin = E_OBJECT_ALLOC(Ind_Win, IND_WIN_TYPE, _e_mod_ind_win_cb_free); if (!iwin) return NULL; iwin->zone = zone; /* create new window */ iwin->win = e_win_new(zone->container); iwin->win->data = iwin; /* set some properties on the window */ e_win_title_set(iwin->win, _("Illume Indicator")); e_win_name_class_set(iwin->win, "Illume-Indicator", "Illume-Indicator"); e_win_no_remember_set(iwin->win, EINA_TRUE); /* hook into window resize so we can resize our objects */ e_win_resize_callback_set(iwin->win, _e_mod_ind_win_cb_resize); /* set this window to not show in taskbar or pager */ states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR; states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER; ecore_x_netwm_window_state_set(iwin->win->evas_win, states, 2); /* set this window to not accept or take focus */ ecore_x_icccm_hints_set(iwin->win->evas_win, 0, 0, 0, 0, 0, 0, 0); /* create our event rectangle */ iwin->o_event = evas_object_rectangle_add(iwin->win->evas); evas_object_color_set(iwin->o_event, 0, 0, 0, 0); evas_object_event_callback_add(iwin->o_event, EVAS_CALLBACK_MOUSE_DOWN, _e_mod_ind_win_cb_mouse_down, iwin); evas_object_event_callback_add(iwin->o_event, EVAS_CALLBACK_MOUSE_UP, _e_mod_ind_win_cb_mouse_up, iwin); evas_object_event_callback_add(iwin->o_event, EVAS_CALLBACK_MOUSE_MOVE, _e_mod_ind_win_cb_mouse_move, iwin); evas_object_move(iwin->o_event, 0, 0); evas_object_show(iwin->o_event); /* create our base object */ iwin->o_base = edje_object_add(iwin->win->evas); if (!e_theme_edje_object_set(iwin->o_base, "base/theme/modules/illume-indicator", "modules/illume-indicator/window")) { char buff[PATH_MAX]; snprintf(buff, sizeof(buff), "%s/e-module-illume-indicator.edj", _ind_mod_dir); edje_object_file_set(iwin->o_base, buff, "modules/illume-indicator/window"); } evas_object_move(iwin->o_base, 0, 0); evas_object_show(iwin->o_base); /* create our gadget container */ iwin->gadcon = e_gadcon_swallowed_new("illume-indicator", zone->id, iwin->o_base, "e.swallow.content"); // iwin->gadcon->instant_edit = 1; edje_extern_object_min_size_set(iwin->gadcon->o_container, zone->w, (32 * e_scale)); edje_object_part_swallow(iwin->o_base, "e.swallow.container", iwin->gadcon->o_container); e_gadcon_min_size_request_callback_set(iwin->gadcon, _e_mod_ind_win_cb_min_size_request, iwin); e_gadcon_size_request_callback_set(iwin->gadcon, _e_mod_ind_win_cb_size_request, iwin); e_gadcon_frame_request_callback_set(iwin->gadcon, _e_mod_ind_win_cb_frame_request, iwin); e_gadcon_orient(iwin->gadcon, E_GADCON_ORIENT_FLOAT); e_gadcon_zone_set(iwin->gadcon, zone); e_gadcon_ecore_evas_set(iwin->gadcon, iwin->win->ecore_evas); e_gadcon_util_menu_attach_func_set(iwin->gadcon, _e_mod_ind_win_cb_menu_items_append, iwin); e_gadcon_populate(iwin->gadcon); /* hook into property change so we can adjust w/ e_scale */ iwin->hdls = eina_list_append(iwin->hdls, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_mod_ind_win_cb_win_prop, iwin)); /* hook into zone resize so we can set minimum window width when zone * size changes */ iwin->hdls = eina_list_append(iwin->hdls, ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE, _e_mod_ind_win_cb_zone_resize, iwin)); /* set minimum size of this window */ e_win_size_min_set(iwin->win, zone->w, (32 * e_scale)); /* position and resize this window */ e_win_move_resize(iwin->win, zone->x, zone->y, zone->w, (32 * e_scale)); /* show the window */ e_win_show(iwin->win); /* set this window on proper zone */ e_border_zone_set(iwin->win->border, zone); /* set this window to be a dock window. This needs to be done after show * as E will sometimes reset the window type */ ecore_x_netwm_window_type_set(iwin->win->evas_win, ECORE_X_WINDOW_TYPE_DOCK); /* tell conformant apps our position and size */ ecore_x_e_illume_indicator_geometry_set(zone->black_win, zone->x, zone->y, zone->w, (32 * e_scale)); return iwin; } /* local function prototypes */ static void _e_mod_ind_win_cb_free(Ind_Win *iwin) { Ecore_Event_Handler *hdl; /* delete the handlers */ EINA_LIST_FREE(iwin->hdls, hdl) ecore_event_handler_del(hdl); /* delete the border hook */ if (iwin->hook) e_border_hook_del(iwin->hook); iwin->hook = NULL; /* delete the menu */ if (iwin->menu) { e_menu_post_deactivate_callback_set(iwin->menu, NULL, NULL); e_object_del(E_OBJECT(iwin->menu)); } iwin->menu = NULL; /* delete the gadget container */ if (iwin->gadcon) e_object_del(E_OBJECT(iwin->gadcon)); iwin->gadcon = NULL; /* delete the objects */ if (iwin->o_base) evas_object_del(iwin->o_base); iwin->o_base = NULL; if (iwin->o_event) evas_object_del(iwin->o_event); iwin->o_event = NULL; /* tell conformant apps our position and size */ ecore_x_e_illume_indicator_geometry_set(iwin->zone->black_win, 0, 0, 0, 0); /* delete the window */ if (iwin->win) e_object_del(E_OBJECT(iwin->win)); iwin->win = NULL; /* free the allocated object */ E_FREE(iwin); } static int _e_mod_ind_win_cb_win_prop(void *data, int type __UNUSED__, void *event) { Ind_Win *iwin; Ecore_X_Event_Window_Property *ev; ev = event; if (!(iwin = data)) return 1; if (ev->win != iwin->win->container->manager->root) return 1; if (ev->atom != ATM_ENLIGHTENMENT_SCALE) return 1; /* set minimum size of this window */ e_win_size_min_set(iwin->win, iwin->zone->w, (32 * e_scale)); /* NB: Not sure why, but we need to tell this border to fetch icccm * size position hints now :( (NOTE: This was not needed a few days ago) * If we do not do this, than indicator does not change w/ scale anymore */ iwin->win->border->client.icccm.fetch.size_pos_hints = 1; /* resize this window */ e_win_resize(iwin->win, iwin->zone->w, (32 * e_scale)); /* tell conformant apps our position and size */ ecore_x_e_illume_indicator_geometry_set(iwin->zone->black_win, iwin->win->x, iwin->win->y, iwin->win->w, (32 * e_scale)); return 1; } static int _e_mod_ind_win_cb_zone_resize(void *data, int type __UNUSED__, void *event) { Ind_Win *iwin; E_Event_Zone_Move_Resize *ev; ev = event; if (!(iwin = data)) return 1; if (ev->zone != iwin->zone) return 1; /* set minimum size of this window to match zone size */ e_win_size_min_set(iwin->win, ev->zone->w, (32 * e_scale)); return 1; } static void _e_mod_ind_win_cb_resize(E_Win *win) { Ind_Win *iwin; if (!(iwin = win->data)) return; if (iwin->o_event) evas_object_resize(iwin->o_event, win->w, win->h); if (iwin->o_base) evas_object_resize(iwin->o_base, win->w, win->h); if (iwin->gadcon->o_container) edje_extern_object_min_size_set(iwin->gadcon->o_container, win->w, win->h); } static void _e_mod_ind_win_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) { Ind_Win *iwin; Evas_Event_Mouse_Down *ev; ev = event; if (!(iwin = data)) return; if (ev->button == 1) { iwin->mouse_down = 1; /* make sure we can drag */ if (iwin->win->border->client.illume.drag.locked) return; iwin->drag.start = 1; iwin->drag.dnd = 0; iwin->drag.y = ev->output.y; iwin->drag.by = iwin->win->border->y; /* change mouse pointer to indicate we are dragging */ if (iwin->win->border->pointer) e_pointer_type_push(iwin->win->border->pointer, iwin->win->border, "move"); } else if (ev->button == 3) { int x, y; /* create our popup menu */ iwin->menu = e_menu_new(); e_menu_post_deactivate_callback_set(iwin->menu, _e_mod_ind_win_cb_menu_post, iwin); /* append items to our menu */ _e_mod_ind_win_cb_menu_append(iwin, iwin->menu); /* show menu */ e_gadcon_canvas_zone_geometry_get(iwin->gadcon, &x, &y, NULL, NULL); e_menu_activate_mouse(iwin->menu, iwin->zone, x + ev->output.x, y + ev->output.y, 1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp); } } static void _e_mod_ind_win_cb_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) { Ind_Win *iwin; Evas_Event_Mouse_Up *ev; ev = event; if (ev->button != 1) return; if (!(iwin = data)) return; /* if we are not dragging, send message to show quickpanel */ if ((!iwin->drag.dnd) && (iwin->mouse_down == 1)) { Ecore_X_Window xwin; xwin = iwin->win->border->zone->black_win; ecore_x_e_illume_quickpanel_state_send (xwin, ECORE_X_ILLUME_QUICKPANEL_STATE_ON); } else if (iwin->drag.dnd) { E_Border *bd; bd = iwin->win->border; /* reset mouse pointer */ if (bd->pointer) e_pointer_type_pop(bd->pointer, bd, "move"); /* tell edj we are done moving */ edje_object_signal_emit(iwin->o_base, "e,action,move,stop", "e"); /* send message that we are done dragging */ ecore_x_e_illume_drag_end_send(bd->client.win); /* update quickpanel position if needed */ if (bd->y != iwin->drag.by) ecore_x_e_illume_quickpanel_position_update_send(bd->client.win); } iwin->drag.start = 0; iwin->drag.dnd = 0; iwin->drag.y = 0; iwin->drag.by = 0; iwin->mouse_down = 0; } static void _e_mod_ind_win_cb_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) { Ind_Win *iwin; Evas_Event_Mouse_Move *ev; E_Border *bd; ev = event; if (!(iwin = data)) return; bd = iwin->win->border; if (iwin->drag.start) { iwin->drag.dnd = 1; iwin->drag.start = 0; /* tell edj we are going to start moving */ edje_object_signal_emit(iwin->o_base, "e,action,move,start", "e"); /* send message that we are going to start dragging */ ecore_x_e_illume_drag_start_send(bd->client.win); } /* make sure we are dragging */ if (iwin->drag.dnd) { int dy, py, ny; /* get current mouse position */ py = ev->cur.output.y; /* do moves in 'chunks' of screen size */ dy = ((bd->zone->h - bd->h) / 8); /* are we moving up or down ? */ if (ev->cur.output.y > ev->prev.output.y) { /* moving down */ if ((py - iwin->drag.y) < dy) return; } else if (ev->cur.output.y < ev->prev.output.y) { /* moving up */ if ((iwin->drag.y - py) < dy) return; } else return; if (py > iwin->drag.y) ny = bd->y + dy; else if (py < iwin->drag.y) ny = bd->y - dy; else return; /* make sure we don't drag off the screen */ if (ny < iwin->zone->y) ny = iwin->zone->y; else if ((ny + bd->h) > (iwin->zone->y + iwin->zone->h)) return; /* move the border if we need to */ if (bd->y != ny) { bd->y = ny; bd->changes.pos = 1; bd->changed = 1; } } } static void _e_mod_ind_win_cb_min_size_request(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h) { Ind_Win *iwin; if (!(iwin = data)) return; if (gc != iwin->gadcon) return; if (h < iwin->win->h) h = iwin->win->h; edje_extern_object_min_size_set(iwin->gadcon->o_container, w, h); } static void _e_mod_ind_win_cb_size_request(void *data __UNUSED__, E_Gadcon *gc __UNUSED__, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__) { return; } static Evas_Object * _e_mod_ind_win_cb_frame_request(void *data __UNUSED__, E_Gadcon_Client *gcc __UNUSED__, const char *style __UNUSED__) { return NULL; } static void _e_mod_ind_win_cb_menu_items_append(void *data, E_Gadcon_Client *gcc __UNUSED__, E_Menu *mn) { Ind_Win *iwin; if (!(iwin = data)) return; _e_mod_ind_win_cb_menu_append(iwin, mn); } static void _e_mod_ind_win_cb_menu_append(Ind_Win *iwin, E_Menu *mn) { E_Menu *subm; E_Menu_Item *mi; char buff[PATH_MAX]; snprintf(buff, sizeof(buff), "%s/e-module-illume-indicator.edj", _ind_mod_dir); subm = e_menu_new(); mi = e_menu_item_new(mn); e_menu_item_label_set(mi, _("Illume Indicator")); e_menu_item_icon_edje_set(mi, buff, "icon"); e_menu_pre_activate_callback_set(subm, _e_mod_ind_win_cb_menu_pre, iwin); e_menu_item_submenu_set(mi, subm); } static void _e_mod_ind_win_cb_menu_pre(void *data, E_Menu *mn) { Ind_Win *iwin; E_Menu_Item *mi; if (!(iwin = data)) return; e_menu_pre_activate_callback_set(mn, NULL, NULL); mi = e_menu_item_new(mn); e_menu_item_label_set(mi, _("Set Contents")); e_util_menu_item_theme_icon_set(mi, "preferences-desktop-shelf"); e_menu_item_callback_set(mi, _e_mod_ind_win_cb_menu_contents, iwin); mi = e_menu_item_new(mn); if (iwin->gadcon->editing) e_menu_item_label_set(mi, _("End Move/Resize Items")); else e_menu_item_label_set(mi, _("Begin Move/Resize Items")); e_util_menu_item_theme_icon_set(mi, "transform-scale"); e_menu_item_callback_set(mi, _e_mod_ind_win_cb_menu_edit, iwin); } static void _e_mod_ind_win_cb_menu_post(void *data, E_Menu *mn __UNUSED__) { Ind_Win *iwin; if (!(iwin = data)) return; if (!iwin->menu) return; e_object_del(E_OBJECT(iwin->menu)); iwin->menu = NULL; } static void _e_mod_ind_win_cb_menu_contents(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__) { Ind_Win *iwin; if (!(iwin = data)) return; if (!iwin->gadcon->config_dialog) e_int_gadcon_config_shelf(iwin->gadcon); } static void _e_mod_ind_win_cb_menu_edit(void *data, E_Menu *mn __UNUSED__, E_Menu_Item *mi __UNUSED__) { Ind_Win *iwin; if (!(iwin = data)) return; if (iwin->gadcon->editing) e_gadcon_edit_end(iwin->gadcon); else e_gadcon_edit_begin(iwin->gadcon); }