945 lines
22 KiB
C
945 lines
22 KiB
C
#include "e_mod_main.h"
|
|
#include <X11/Xlib.h>
|
|
|
|
static int _border_check (Ngi_Box *box, E_Border *bd);
|
|
static Ngi_Item_Taskbar *_border_find (Ngi_Box *box, E_Border *bd);
|
|
|
|
static Eina_Bool _cb_border_event (void *data, int type, void *event);
|
|
static Eina_Bool _cb_desk_show (void *data, int type, void *event);
|
|
|
|
static void _item_new (Ngi_Box *box, E_Border *bd);
|
|
static void _item_cb_free (Ngi_Item *it);
|
|
static void _item_set_icon (Ngi_Item_Taskbar *it);
|
|
static void _item_set_label (Ngi_Item_Taskbar *it);
|
|
|
|
static void _item_cb_mouse_down (Ngi_Item *it, Ecore_Event_Mouse_Button *ev);
|
|
static void _item_cb_mouse_up (Ngi_Item *it, Ecore_Event_Mouse_Button *ev);
|
|
static void _item_cb_mouse_in (Ngi_Item *it);
|
|
static void _item_cb_mouse_out (Ngi_Item *it);
|
|
static void _item_cb_drag_start (Ngi_Item *it);
|
|
static void _item_cb_drag_end (E_Drag *drag, int dropped);
|
|
|
|
static Eina_Bool _cb_show_window (void *data);
|
|
static void _cb_drop_enter (void *data, const char *type, void *event_info);
|
|
static void _cb_drop_move (void *data, const char *type, void *event_info);
|
|
static void _cb_drop_end (void *data, const char *type, void *event_info);
|
|
static void _cb_drop_leave (void *data, const char *type, void *event_info);
|
|
|
|
|
|
static Ecore_X_Atom ECOMORPH_ATOM_THUMBNAIL = 0;
|
|
|
|
void
|
|
ngi_taskbar_init(void)
|
|
{
|
|
ECOMORPH_ATOM_THUMBNAIL = ecore_x_atom_get("__ECOMORPH_THUMBNAIL");
|
|
}
|
|
|
|
void
|
|
ngi_taskbar_new(Ng *ng, Config_Box *cfg)
|
|
{
|
|
Ngi_Box *box = ngi_box_new(ng);
|
|
E_Border *bd;
|
|
E_Border_List *bl;
|
|
Ecore_Event_Handler *h;
|
|
|
|
if (!box) return;
|
|
|
|
box->cfg = cfg;
|
|
cfg->box = box;
|
|
|
|
// "enlightenment/border", "enlightenment/desktop",
|
|
const char *drop[] = {"text/uri-list","text/x-moz-url", "enlightenment/x-file"};
|
|
box->drop_handler = e_drop_handler_add(ng->win->drop_win, box,
|
|
_cb_drop_enter, _cb_drop_move,
|
|
_cb_drop_leave, _cb_drop_end,
|
|
drop, 3, 0, 0, 0, 0);
|
|
|
|
#define HANDLE(_event, _cb) \
|
|
box->handlers = eina_list_append(box->handlers, ecore_event_handler_add(_event, _cb, box));
|
|
|
|
HANDLE(E_EVENT_BORDER_ADD, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_REMOVE, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_ICONIFY, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_UNICONIFY, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_ICON_CHANGE, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_PROPERTY, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_ZONE_SET, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_URGENT_CHANGE, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_FOCUS_IN, _cb_border_event);
|
|
HANDLE(E_EVENT_BORDER_FOCUS_OUT, _cb_border_event);
|
|
HANDLE(E_EVENT_DESK_SHOW, _cb_desk_show);
|
|
#undef HANDLE
|
|
|
|
bl = e_container_border_list_first(box->ng->zone->container);
|
|
|
|
while ((bd = e_container_border_list_next(bl)))
|
|
{
|
|
if (box->ng->zone == bd->zone)
|
|
_item_new(box, bd);
|
|
}
|
|
|
|
e_container_border_list_free(bl);
|
|
}
|
|
|
|
void
|
|
ngi_taskbar_remove(Ngi_Box *box)
|
|
{
|
|
Ecore_Event_Handler *h;
|
|
|
|
e_drop_handler_del(box->drop_handler);
|
|
|
|
EINA_LIST_FREE(box->handlers, h)
|
|
ecore_event_handler_del(h);
|
|
|
|
ngi_box_free(box);
|
|
}
|
|
|
|
static int
|
|
_border_check(Ngi_Box *box, E_Border *bd)
|
|
{
|
|
if (box->ng->zone != bd->zone)
|
|
return 0;
|
|
|
|
if (box->cfg->taskbar_show_iconified == 0 && bd->iconic)
|
|
return 0;
|
|
|
|
if (box->cfg->taskbar_show_iconified == 2 && !bd->iconic)
|
|
return 0;
|
|
|
|
if ((box->cfg->taskbar_skip_dialogs && bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
|
|
|| (bd->user_skip_winlist)
|
|
|| (bd->client.netwm.state.skip_taskbar))
|
|
return 0;
|
|
|
|
/* XXX Xitk menu windows act like normal windows... */
|
|
if (bd->client.icccm.transient_for &&
|
|
bd->client.icccm.class &&
|
|
!strcmp(bd->client.icccm.class, "Xitk"))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static Ngi_Item_Taskbar *
|
|
_border_find(Ngi_Box *box, E_Border *bd)
|
|
{
|
|
Eina_List *l;
|
|
Ngi_Item_Taskbar *it;
|
|
|
|
EINA_LIST_FOREACH(box->items, l, it)
|
|
if (it->border == bd) return it;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* ************************* DND CALLBACKS ************************** */
|
|
|
|
static void
|
|
_cb_drop_enter(void *data, const char *type, void *event_info)
|
|
{
|
|
E_Event_Dnd_Enter *ev = (E_Event_Dnd_Enter *)event_info;
|
|
Ngi_Box *box = (Ngi_Box *)data;
|
|
Ng *ng = box->ng;
|
|
|
|
ng->pos = (ng->horizontal ? ev->x : ev->y);
|
|
|
|
ng->item_active = ngi_item_at_position_get(ng);
|
|
|
|
if (!ng->item_active)
|
|
return; /* FIXME set edge_in before ?*/
|
|
|
|
if (box->dnd_timer)
|
|
ecore_timer_del(box->dnd_timer);
|
|
|
|
box->dnd_timer = ecore_timer_add(0.5, _cb_show_window, ng->item_active);
|
|
|
|
ng->dnd = 1;
|
|
ngi_mouse_in(ng);
|
|
}
|
|
|
|
static void
|
|
_cb_drop_leave(void *data, const char *type, void *event_info)
|
|
{
|
|
Ngi_Box *box = (Ngi_Box *)data;
|
|
Ng *ng = box->ng;
|
|
|
|
if (box->dnd_timer)
|
|
{
|
|
ecore_timer_del(box->dnd_timer);
|
|
box->dnd_timer = NULL;
|
|
}
|
|
|
|
ng->item_active = NULL;
|
|
ngi_mouse_out(ng);
|
|
}
|
|
|
|
static void
|
|
_cb_drop_move(void *data, const char *type, void *event_info)
|
|
{
|
|
E_Event_Dnd_Move *ev = (E_Event_Dnd_Move *)event_info;
|
|
Ngi_Box *box = (Ngi_Box *)data;
|
|
Ng *ng = box->ng;
|
|
Ngi_Item *it;
|
|
|
|
ng->pos = (ng->horizontal ? ev->x : ev->y);
|
|
|
|
it = ngi_item_at_position_get(ng);
|
|
|
|
if (!it || !ng->item_active)
|
|
return;
|
|
|
|
if (ng->item_active != it)
|
|
{
|
|
if (box->dnd_timer)
|
|
ecore_timer_del(box->dnd_timer);
|
|
box->dnd_timer = NULL;
|
|
|
|
if (it)
|
|
{
|
|
ngi_item_activate(ng);
|
|
|
|
box->dnd_timer = ecore_timer_add(0.5, _cb_show_window, it);
|
|
}
|
|
}
|
|
|
|
ngi_animate(ng);
|
|
}
|
|
|
|
static void
|
|
_cb_drop_end(void *data, const char *type, void *event_info)
|
|
{
|
|
Ngi_Box *box = (Ngi_Box *)data;
|
|
Ng *ng = box->ng;
|
|
|
|
if (!ng->item_active)
|
|
return;
|
|
|
|
if (box->dnd_timer)
|
|
{
|
|
ecore_timer_del(box->dnd_timer);
|
|
box->dnd_timer = NULL;
|
|
}
|
|
|
|
ng->item_active = NULL;
|
|
ngi_mouse_out(ng);
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_show_window(void *data)
|
|
{
|
|
Ngi_Item_Taskbar *it = (Ngi_Item_Taskbar*) data;
|
|
E_Desk *desk;
|
|
|
|
if (!it) return EINA_FALSE;
|
|
|
|
desk = e_desk_current_get(it->border->zone);
|
|
|
|
if (desk != it->border->desk && !it->border->sticky)
|
|
{
|
|
e_desk_show(it->border->desk);
|
|
}
|
|
|
|
if (it->border->shaded)
|
|
{
|
|
e_border_unshade(it->border, E_DIRECTION_UP);
|
|
}
|
|
|
|
if (!it->border->visible)
|
|
{
|
|
e_border_show(it->border);
|
|
}
|
|
|
|
if (it->border->iconic)
|
|
{
|
|
e_border_uniconify(it->border);
|
|
}
|
|
else
|
|
{
|
|
e_border_raise(it->border);
|
|
}
|
|
|
|
e_border_focus_set(it->border, 1, 1);
|
|
|
|
it->base.box->dnd_timer = NULL;
|
|
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
/* ************************** BORDER CALLBACKS ************************* */
|
|
|
|
static Eina_Bool
|
|
_cb_border_event(void *data, int type, void *event)
|
|
{
|
|
E_Event_Border_Add *ev = event;
|
|
Ngi_Box *box = data;
|
|
Ngi_Item *it;
|
|
E_Border *bd = ev->border;
|
|
|
|
/* XXX workaround for e sending event after the
|
|
* border_remove event */
|
|
/* if (bd->already_unparented)
|
|
* return ECORE_CALLBACK_PASS_ON; */
|
|
|
|
it = (Ngi_Item*)_border_find(box, bd);
|
|
|
|
if (type == E_EVENT_BORDER_FOCUS_IN)
|
|
{
|
|
if (it) ngi_item_signal_emit(it, "e,state,taskbar,focus,on");
|
|
}
|
|
else if (type == E_EVENT_BORDER_FOCUS_OUT)
|
|
{
|
|
if (it) ngi_item_signal_emit(it, "e,state,taskbar,focus,off");
|
|
}
|
|
else if (type == E_EVENT_BORDER_ICONIFY)
|
|
{
|
|
if (it) ngi_item_signal_emit(it, "e,state,taskbar,iconic,on");
|
|
}
|
|
else if (type == E_EVENT_BORDER_UNICONIFY)
|
|
{
|
|
if (it) ngi_item_signal_emit(it, "e,state,taskbar,iconic,off");
|
|
}
|
|
else if (type == E_EVENT_BORDER_ICON_CHANGE)
|
|
{
|
|
if (it) _item_set_icon((Ngi_Item_Taskbar *)it);
|
|
}
|
|
else if (type == E_EVENT_BORDER_ADD)
|
|
{
|
|
_item_new(box, bd);
|
|
}
|
|
else if (type == E_EVENT_BORDER_REMOVE)
|
|
{
|
|
if (it) ngi_item_remove(it);
|
|
}
|
|
else if (type == E_EVENT_BORDER_ZONE_SET)
|
|
{
|
|
if (box->ng->zone == bd->zone)
|
|
_item_new(box, bd);
|
|
else if (it)
|
|
ngi_item_remove(it);
|
|
}
|
|
else if ((type == E_EVENT_BORDER_URGENT_CHANGE) && (it))
|
|
{
|
|
if (bd->client.icccm.urgent)
|
|
{
|
|
((Ngi_Item_Taskbar *)it)->urgent = 1;
|
|
ngi_item_signal_emit(it, "e,state,taskbar,urgent,on");
|
|
|
|
if (box->ng->cfg->autohide_show_urgent)
|
|
{
|
|
ngi_bar_lock(box->ng, 1);
|
|
ngi_animate(box->ng);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
((Ngi_Item_Taskbar *)it)->urgent = 0;
|
|
ngi_item_signal_emit(it, "e,state,taskbar,urgent,off");
|
|
|
|
if (box->ng->cfg->autohide_show_urgent)
|
|
{
|
|
ngi_bar_lock(box->ng, 0);
|
|
ngi_animate(box->ng);
|
|
}
|
|
}
|
|
}
|
|
else if (type == E_EVENT_BORDER_PROPERTY)
|
|
{
|
|
if (it)
|
|
{
|
|
if (!_border_check(box, bd))
|
|
ngi_item_remove(it);
|
|
else
|
|
_item_set_label((Ngi_Item_Taskbar *)it);
|
|
}
|
|
else
|
|
{
|
|
_item_new(box, ev->border);
|
|
}
|
|
}
|
|
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_desk_show(void *data, int type, void *event)
|
|
{
|
|
E_Event_Desk_Show *ev = event;
|
|
Ngi_Box *box = data;
|
|
Ngi_Item_Taskbar *it;
|
|
Eina_List *l;
|
|
|
|
if (ev->desk->zone != box->ng->zone)
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
|
|
if (!box->cfg->taskbar_show_desktop)
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
|
|
EINA_LIST_FOREACH(box->items, l, it)
|
|
{
|
|
if ((it->border->desk == ev->desk) || (it->border->sticky))
|
|
{
|
|
evas_object_show(it->base.obj);
|
|
evas_object_show(it->base.over);
|
|
it->base.scale = 1.0;
|
|
}
|
|
else
|
|
{
|
|
evas_object_hide(it->base.obj);
|
|
evas_object_hide(it->base.over);
|
|
it->base.scale = 0.0;
|
|
}
|
|
}
|
|
|
|
ngi_thaw(box->ng);
|
|
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
/* *************************** TASKBAR ITEM *************************** */
|
|
|
|
static void
|
|
_item_new(Ngi_Box *box, E_Border *bd)
|
|
{
|
|
Ngi_Item_Taskbar *it, *l_it = NULL, *ll_it = NULL;
|
|
Ngi_Item *item;
|
|
Eina_List *l;
|
|
|
|
if (!_border_check(box, bd))
|
|
return;
|
|
|
|
if (_border_find(box, bd))
|
|
return;
|
|
|
|
it = E_NEW(Ngi_Item_Taskbar, 1);
|
|
it->base.box = box;
|
|
item = (Ngi_Item*) it;
|
|
ngi_item_init_defaults(item);
|
|
|
|
e_object_ref(E_OBJECT(bd));
|
|
it->border = bd;
|
|
|
|
it->base.cb_free = _item_cb_free;
|
|
it->base.cb_mouse_in = _item_cb_mouse_in;
|
|
it->base.cb_mouse_out = _item_cb_mouse_out;
|
|
it->base.cb_mouse_down = _item_cb_mouse_down;
|
|
it->base.cb_mouse_up = _item_cb_mouse_up;
|
|
it->base.cb_drag_start = _item_cb_drag_start;
|
|
|
|
_item_set_icon(it);
|
|
_item_set_label(it);
|
|
|
|
if ((box->cfg->taskbar_group_apps) &&
|
|
(bd->client.icccm.class && bd->client.icccm.class[0]))
|
|
{
|
|
it->class = eina_stringshare_ref(bd->client.icccm.class);
|
|
|
|
EINA_LIST_FOREACH(box->items, l, l_it)
|
|
{
|
|
if (!l_it->class)
|
|
{
|
|
continue;
|
|
}
|
|
else if (l_it->class == it->class)
|
|
{
|
|
ll_it = l_it;
|
|
}
|
|
else if ((ll_it) && (l_it->class != it->class))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ll_it)
|
|
box->items = eina_list_append_relative(box->items, it, ll_it);
|
|
else if (box->cfg->taskbar_append_right)
|
|
box->items = eina_list_append(box->items, it);
|
|
else
|
|
box->items = eina_list_prepend(box->items, it);
|
|
|
|
if ((box->cfg->taskbar_show_desktop) &&
|
|
(bd->desk != e_desk_current_get(box->ng->zone)) &&
|
|
(!bd->sticky))
|
|
{
|
|
ngi_item_show(item, 1);
|
|
item->scale = 0.0;
|
|
}
|
|
else
|
|
{
|
|
ngi_item_show(item, 0);
|
|
}
|
|
|
|
if (bd->iconic)
|
|
ngi_item_signal_emit(item, "e,state,taskbar,iconic,on");
|
|
|
|
it->urgent = bd->client.icccm.urgent;
|
|
if (it->urgent)
|
|
ngi_item_signal_emit(item, "e,state,taskbar,urgent,on");
|
|
}
|
|
|
|
static void
|
|
_item_cb_free(Ngi_Item *item)
|
|
{
|
|
Ngi_Item_Taskbar *it = (Ngi_Item_Taskbar *) item;
|
|
|
|
if (it->urgent)
|
|
ngi_bar_lock(item->box->ng, 0);
|
|
|
|
if (it->border)
|
|
e_object_unref(E_OBJECT(it->border));
|
|
|
|
if (it->o_icon)
|
|
evas_object_del(it->o_icon);
|
|
|
|
if (it->o_proxy)
|
|
edje_object_part_unswallow(it->base.obj, it->o_proxy);
|
|
|
|
E_FREE(it);
|
|
}
|
|
|
|
Evas_Object *
|
|
_border_icon_add(E_Border *bd, Evas *evas)
|
|
{
|
|
Evas_Object *o;
|
|
|
|
E_OBJECT_CHECK_RETURN(bd, NULL);
|
|
E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
|
|
|
|
o = NULL;
|
|
|
|
if (bd->internal)
|
|
{
|
|
if (!bd->internal_icon)
|
|
{
|
|
o = e_icon_add(evas);
|
|
e_util_icon_theme_set(o, "enlightenment");
|
|
}
|
|
else if (!bd->internal_icon_key)
|
|
{
|
|
char *ext;
|
|
ext = strrchr(bd->internal_icon, '.');
|
|
if ((ext) && ((!strcmp(ext, ".edj"))))
|
|
{
|
|
o = edje_object_add(evas);
|
|
if (!edje_object_file_set(o, bd->internal_icon, "icon"))
|
|
e_util_icon_theme_set(o, "enlightenment");
|
|
}
|
|
else if (ext)
|
|
{
|
|
o = e_icon_add(evas);
|
|
e_icon_file_set(o, bd->internal_icon);
|
|
}
|
|
else
|
|
{
|
|
o = e_icon_add(evas);
|
|
e_icon_scale_size_set(o, 128);
|
|
if (!e_util_icon_theme_set(o, bd->internal_icon))
|
|
e_util_icon_theme_set(o, "enlightenment");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
o = edje_object_add(evas);
|
|
edje_object_file_set(o, bd->internal_icon, bd->internal_icon_key);
|
|
}
|
|
|
|
return o;
|
|
}
|
|
|
|
if (bd->client.netwm.icons)
|
|
{
|
|
if (e_config->use_app_icon)
|
|
goto _use_netwm_icon;
|
|
|
|
if (bd->remember && (bd->remember->prop.icon_preference == E_ICON_PREF_NETWM))
|
|
goto _use_netwm_icon;
|
|
}
|
|
|
|
if (bd->desktop)
|
|
{
|
|
o = e_util_desktop_icon_add(bd->desktop, 128, evas);
|
|
if (o) return o;
|
|
}
|
|
|
|
_use_netwm_icon:
|
|
if (bd->client.netwm.icons)
|
|
{
|
|
int i, size, tmp, found = 0;
|
|
o = e_icon_add(evas);
|
|
|
|
size = bd->client.netwm.icons[0].width;
|
|
|
|
for (i = 1; i < bd->client.netwm.num_icons; i++)
|
|
{
|
|
if ((tmp = bd->client.netwm.icons[i].width) > size)
|
|
{
|
|
size = tmp;
|
|
found = i;
|
|
}
|
|
}
|
|
|
|
e_icon_data_set(o, bd->client.netwm.icons[found].data,
|
|
bd->client.netwm.icons[found].width,
|
|
bd->client.netwm.icons[found].height);
|
|
e_icon_alpha_set(o, 1);
|
|
return o;
|
|
}
|
|
|
|
o = e_border_icon_add(bd, evas);
|
|
if (o) return o;
|
|
|
|
o = edje_object_add(evas);
|
|
e_util_icon_theme_set(o, "unknown");
|
|
|
|
return o;
|
|
}
|
|
|
|
static void
|
|
_item_set_icon(Ngi_Item_Taskbar *it)
|
|
{
|
|
Evas_Object *o, *oo;
|
|
Evas *e = it->base.box->ng->evas;
|
|
|
|
if (it->o_icon)
|
|
{
|
|
edje_object_part_unswallow(it->base.obj, it->o_icon);
|
|
evas_object_del(it->o_icon);
|
|
}
|
|
if (it->o_proxy)
|
|
{
|
|
edje_object_part_unswallow(it->base.obj, it->o_proxy);
|
|
evas_object_del(it->o_proxy);
|
|
}
|
|
|
|
o = _border_icon_add(it->border, e);
|
|
edje_object_part_swallow(it->base.obj, "e.swallow.content", o);
|
|
evas_object_show(o);
|
|
it->o_icon = o;
|
|
|
|
oo = evas_object_image_filled_add(e);
|
|
evas_object_image_fill_set(oo, 0, 0, 1, 1);
|
|
evas_object_image_source_set(oo, it->base.obj);
|
|
edje_object_part_swallow(it->base.over, "e.swallow.content", oo);
|
|
evas_object_show(oo);
|
|
it->o_proxy = oo;
|
|
|
|
if (it->border->iconic)
|
|
ngi_item_signal_emit((Ngi_Item*)it, "e,state,taskbar,iconic,on");
|
|
if (it->urgent)
|
|
ngi_item_signal_emit((Ngi_Item*)it, "e,state,taskbar,urgent,on");
|
|
}
|
|
|
|
static void
|
|
_item_set_label(Ngi_Item_Taskbar *it)
|
|
{
|
|
const char *title;
|
|
unsigned int max_len = 36;
|
|
|
|
title = e_border_name_get(it->border);
|
|
|
|
if ((!title) || (!title[0]))
|
|
title = D_("No name!");
|
|
|
|
if (strlen(title) > max_len)
|
|
{
|
|
char *abbv;
|
|
const char *left, *right;
|
|
|
|
abbv = E_NEW(char, E_CLIENTLIST_MAX_CAPTION_LEN + 4);
|
|
left = title;
|
|
right = title + (strlen(title) - (max_len / 2));
|
|
|
|
strncpy(abbv, left, max_len / 2);
|
|
strncat(abbv, "...", 3);
|
|
strncat(abbv, right, max_len / 2);
|
|
|
|
ngi_item_label_set((Ngi_Item*)it, abbv);
|
|
E_FREE(abbv);
|
|
|
|
return;
|
|
}
|
|
|
|
ngi_item_label_set((Ngi_Item*)it, title);
|
|
}
|
|
|
|
/* ************************** ITEM CALLBACKS ************************** */
|
|
|
|
static void
|
|
_item_cb_mouse_down(Ngi_Item *item, Ecore_Event_Mouse_Button *ev)
|
|
{
|
|
Ngi_Item_Taskbar *it = (Ngi_Item_Taskbar *) item;
|
|
Evas_Coord x, y, w, h;
|
|
E_Border *bd;
|
|
Ng *ng;
|
|
|
|
ng = item->box->ng;
|
|
bd = it->border;
|
|
|
|
if (ev->buttons == 3 && bd)
|
|
{
|
|
int dir = E_MENU_POP_DIRECTION_AUTO;
|
|
evas_object_geometry_get(item->obj, &x, &y, &w, &h);
|
|
|
|
x += ng->win->popup->x + ng->zone->x;
|
|
y += ng->win->popup->y + ng->zone->y;
|
|
|
|
switch(ng->cfg->orient)
|
|
{
|
|
case E_GADCON_ORIENT_TOP:
|
|
dir = E_MENU_POP_DIRECTION_DOWN;
|
|
y += h;
|
|
break;
|
|
|
|
case E_GADCON_ORIENT_BOTTOM:
|
|
dir = E_MENU_POP_DIRECTION_UP;
|
|
break;
|
|
|
|
case E_GADCON_ORIENT_LEFT:
|
|
dir = E_MENU_POP_DIRECTION_RIGHT;
|
|
x += w;
|
|
break;
|
|
|
|
case E_GADCON_ORIENT_RIGHT:
|
|
dir = E_MENU_POP_DIRECTION_LEFT;
|
|
break;
|
|
} /* switch */
|
|
ngi_border_menu_show(item->box, it->border, x, y, dir, ev->timestamp);
|
|
}
|
|
else if (ev->buttons == 1 && ev->double_click && !it->border->iconic)
|
|
{
|
|
e_border_iconify(it->border);
|
|
}
|
|
else
|
|
item->mouse_down = 1;
|
|
}
|
|
|
|
static void
|
|
_item_cb_mouse_up(Ngi_Item *item, Ecore_Event_Mouse_Button *ev)
|
|
{
|
|
Ngi_Item_Taskbar *it = (Ngi_Item_Taskbar *) item;
|
|
E_Border *bd = it->border;
|
|
|
|
if (!item->mouse_down)
|
|
return;
|
|
|
|
item->mouse_down = 0;
|
|
|
|
if (it->urgent)
|
|
{
|
|
it->urgent = 0;
|
|
|
|
ngi_item_signal_emit((Ngi_Item*)it, "e,state,taskbar,urgent,off");
|
|
ngi_bar_lock(item->box->ng, 0);
|
|
}
|
|
|
|
if (ev->buttons != 1)
|
|
return;
|
|
|
|
if (bd->shaded)
|
|
e_border_unshade(bd, E_DIRECTION_UP);
|
|
|
|
if (bd->shaded)
|
|
e_border_unshade(bd, E_DIRECTION_UP);
|
|
|
|
if ((e_desk_current_get(bd->zone) != bd->desk) && (!bd->sticky))
|
|
e_desk_show(bd->desk);
|
|
|
|
if (bd->iconic)
|
|
{
|
|
e_border_uniconify(bd);
|
|
|
|
if (it->border_was_fullscreen)
|
|
e_border_fullscreen(bd, (E_Fullscreen)e_config->fullscreen_policy);
|
|
|
|
it->border_was_fullscreen = 0;
|
|
}
|
|
else
|
|
{
|
|
e_border_raise(bd);
|
|
}
|
|
if (bd->focused)
|
|
{
|
|
char buf[1024];
|
|
E_Action *act = e_action_find("scale-windows");
|
|
Eina_List *l;
|
|
Ngi_Item_Taskbar *l_it;
|
|
int cnt = 0;
|
|
|
|
if (!act) return;
|
|
if (!it->class) return;
|
|
|
|
EINA_LIST_FOREACH(it->base.box->items, l, l_it)
|
|
if (l_it->class == it->class)
|
|
cnt++;
|
|
|
|
if (cnt < 2)
|
|
return;
|
|
|
|
snprintf(buf, 1024, "go_scale_class:%s", bd->client.icccm.class);
|
|
act->func.go(NULL, buf);
|
|
}
|
|
else
|
|
e_border_focus_set(bd, 1, 1);
|
|
}
|
|
|
|
|
|
static void
|
|
_item_cb_drag_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Ng *ng = data;
|
|
|
|
ngi_bar_lock(ng, 0);
|
|
ngi_thaw(ng);
|
|
}
|
|
|
|
static void
|
|
_item_cb_drag_start(Ngi_Item *item)
|
|
{
|
|
Ngi_Item_Taskbar *it = (Ngi_Item_Taskbar *) item;
|
|
E_Drag *d;
|
|
Evas_Object *o;
|
|
Evas_Coord x, y, w, h, px, py;
|
|
Ng *ng = item->box->ng;
|
|
|
|
if (!it->border)
|
|
return;
|
|
|
|
edje_object_signal_emit(ng->o_label, "e,state,label,hide", "e");
|
|
|
|
evas_object_geometry_get(it->o_icon, &x, &y, &w, &h);
|
|
|
|
if (!ngi_config->use_composite)
|
|
{
|
|
x -= ng->win->rect.x;
|
|
y -= ng->win->rect.y;
|
|
}
|
|
|
|
const char *drag_types[] = { "enlightenment/border" };
|
|
|
|
d = e_drag_new(ng->zone->container, x, y, drag_types, 1,
|
|
it->border, -1, NULL, _item_cb_drag_end);
|
|
|
|
o = _border_icon_add(it->border,e_drag_evas_get(d));
|
|
e_object_ref(E_OBJECT(it->border));
|
|
e_drag_object_set(d, o);
|
|
e_drag_resize(d, w, h);
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _item_cb_drag_del, ng);
|
|
|
|
ecore_x_pointer_xy_get(ng->win->input, &px, &py);
|
|
e_drag_start(d, px, py);
|
|
|
|
ngi_bar_lock(ng, 1);
|
|
}
|
|
|
|
static void
|
|
_item_cb_drag_end(E_Drag *drag, int dropped)
|
|
{
|
|
E_Border *bd = (E_Border *)drag->data;
|
|
|
|
if (dropped)
|
|
{
|
|
e_object_unref(E_OBJECT(bd));
|
|
return;
|
|
}
|
|
|
|
E_Desk *desk = e_desk_current_get(bd->zone);
|
|
int w = bd->zone->w;
|
|
int h = bd->zone->h;
|
|
|
|
if (desk != bd->desk)
|
|
e_border_desk_set(bd, desk);
|
|
|
|
if ((bd->w < w) && (bd->h < w))
|
|
{
|
|
int dx = abs(drag->x - w/2);
|
|
int dy = abs(drag->y - h/2);
|
|
|
|
if (sqrt(dx*dx + dy*dy) < w/8)
|
|
{
|
|
drag->x = w/2;
|
|
drag->y = h/2;
|
|
}
|
|
|
|
int x = drag->x - bd->w/2;
|
|
|
|
if (bd->w < w - 50)
|
|
{
|
|
if (x < 50) x = 50;
|
|
if (x + bd->w > w) x = w - bd->w - 50;
|
|
}
|
|
else x = bd->x;
|
|
|
|
int y = drag->y - bd->h/2;
|
|
|
|
if (bd->h < h - 50)
|
|
{
|
|
if (y < 50) y = 50;
|
|
if (y + bd->h > h) y = h - bd->h - 50;
|
|
}
|
|
else y = bd->y;
|
|
|
|
e_border_move(bd, x, y);
|
|
}
|
|
|
|
if (bd->iconic)
|
|
e_border_uniconify(bd);
|
|
else
|
|
e_border_raise(bd);
|
|
|
|
if (bd->shaded)
|
|
e_border_unshade(bd, E_DIRECTION_UP);
|
|
|
|
e_object_unref(E_OBJECT(bd));
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_preview_hide(void *data)
|
|
{
|
|
Ng *ng = data;
|
|
|
|
ng->effect_timer = NULL;
|
|
|
|
ecore_x_client_message32_send(e_manager_current_get()->root,
|
|
ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
|
|
SubstructureNotifyMask,
|
|
0, 0, 0, 0, 0);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
static void
|
|
_item_cb_mouse_in(Ngi_Item *item)
|
|
{
|
|
Ngi_Item_Taskbar *it = (Ngi_Item_Taskbar *) item;
|
|
|
|
Ng *ng = item->box->ng;
|
|
|
|
if (ng->cfg->ecomorph_features)
|
|
{
|
|
if (ng->effect_timer)
|
|
ecore_timer_del(ng->effect_timer);
|
|
|
|
ng->effect_timer = NULL;
|
|
|
|
ecore_x_client_message32_send(e_manager_current_get()->root,
|
|
ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
|
|
SubstructureNotifyMask,
|
|
it->border->win, item->pos,
|
|
(double)ng->size * item->scale,
|
|
ng->cfg->orient,0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_item_cb_mouse_out(Ngi_Item *it)
|
|
{
|
|
Ng *ng = it->box->ng;
|
|
if (ng->cfg->ecomorph_features)
|
|
{
|
|
if (ng->effect_timer)
|
|
ecore_timer_del(ng->effect_timer);
|
|
|
|
ng->effect_timer = ecore_timer_add(0.2, _cb_preview_hide, ng);
|
|
}
|
|
}
|
|
|