1309 lines
35 KiB
C
1309 lines
35 KiB
C
/*
|
|
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
*/
|
|
#include "e.h"
|
|
#include "e_mod_main.h"
|
|
#include "e_mod_config.h"
|
|
#include <math.h>
|
|
|
|
#include "Ecore_X.h"
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xutil.h>
|
|
|
|
/* Currently unused */
|
|
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
|
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
|
|
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
|
|
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
|
|
#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
|
|
/* ---------------- */
|
|
|
|
#define XEMBED_EMBEDDED_NOTIFY 0
|
|
|
|
#define TRAY_ICON_SIZE 27
|
|
|
|
/* Bug List:
|
|
*
|
|
* Changing the number of rows breaks the layout.
|
|
* It's magically fixed when the module is moved.
|
|
*
|
|
* TODO List:
|
|
*
|
|
* Make sure only one tray exists.
|
|
* Use the abovestated defines.
|
|
* Change the size of the tray icons.
|
|
* Use the shape extension for the ecore_x_window so that the "gray"
|
|
* itself is not visible, but the tray icons are.
|
|
*
|
|
* The Big Picture:
|
|
*
|
|
* Get rid of the ecore_x_window stuff.
|
|
* Make the tray survive an E restart.
|
|
*
|
|
*/
|
|
|
|
static int box_count;
|
|
static E_Config_DD *conf_edd;
|
|
static E_Config_DD *conf_box_edd;
|
|
|
|
/* const strings */
|
|
static const char *_itray_main_orientation[] =
|
|
{"left", "right", "top", "bottom"};
|
|
|
|
/* module private routines */
|
|
static ITray *_itray_new();
|
|
static void _itray_free(ITray *it);
|
|
static void _itray_config_menu_new(ITray *it);
|
|
|
|
static ITray_Box *_itray_box_new(ITray *it, E_Container *con);
|
|
static void _itray_box_free(ITray_Box *itb);
|
|
static void _itray_box_menu_new(ITray_Box *itb);
|
|
static void _itray_box_disable(ITray_Box *itb);
|
|
static void _itray_box_frame_resize(ITray_Box *itb);
|
|
static void _itray_box_edge_change(ITray_Box *itb, int edge);
|
|
static void _itray_box_update_policy(ITray_Box *itb);
|
|
|
|
static void _itray_box_cb_gmc_change(void *data, E_Gadman_Client *gmc, E_Gadman_Change change);
|
|
static void _itray_box_cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _itray_box_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _itray_box_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _itray_box_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _itray_box_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
|
|
static void _itray_box_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi);
|
|
static void _itray_box_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
|
|
|
|
/* Config Updated Function Protos */
|
|
static void _itray_box_cb_width_auto(void *data);
|
|
|
|
/* Tray */
|
|
static void _itray_tray_init(ITray_Box *itb);
|
|
static void _itray_tray_shutdown(ITray_Box *itb);
|
|
static int _itray_tray_cb_msg(void *data, int type, void *event);
|
|
static int _itray_tray_cb_destroy(void *data, int type, void *event);
|
|
static int _itray_tray_cb_hide(void *data, int type, void *event);
|
|
static int _itray_tray_cb_shape(void *data, int type, void *event);
|
|
static int _itray_exists(ITray_Box *itb, Ecore_X_Window win);
|
|
static void _itray_reshape(ITray_Box *itb);
|
|
static void _itray_tray_active_set();
|
|
|
|
static void _itray_tray_add(ITray_Box *itb, Ecore_X_Window win);
|
|
static void _itray_tray_remove(ITray_Box *itb, Ecore_X_Window win);
|
|
|
|
static void _itray_tray_cb_move(void *data, Evas_Object *o, Evas_Coord x, Evas_Coord y);
|
|
static void _itray_tray_cb_resize(void *data, Evas_Object *o, Evas_Coord w, Evas_Coord h);
|
|
|
|
static void _itray_tray_layout(ITray_Box *itb);
|
|
|
|
/* public module routines. all modules must have these */
|
|
EAPI E_Module_Api e_modapi =
|
|
{
|
|
E_MODULE_API_VERSION,
|
|
"ITray"
|
|
};
|
|
|
|
EAPI void *
|
|
e_modapi_init(E_Module *m)
|
|
{
|
|
ITray *it;
|
|
|
|
/* actually init ibox */
|
|
it = _itray_new();
|
|
m->config_menu = it->config_menu;
|
|
return it;
|
|
}
|
|
|
|
EAPI int
|
|
e_modapi_shutdown(E_Module *m)
|
|
{
|
|
ITray *it;
|
|
|
|
if (m->config_menu)
|
|
m->config_menu = NULL;
|
|
|
|
it = m->data;
|
|
if (it)
|
|
{
|
|
if (it->config_dialog)
|
|
{
|
|
e_object_del(E_OBJECT(it->config_dialog));
|
|
it->config_dialog = NULL;
|
|
}
|
|
_itray_free(it);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
EAPI int
|
|
e_modapi_save(E_Module *m)
|
|
{
|
|
ITray *it;
|
|
|
|
it = m->data;
|
|
e_config_domain_save("module.itray", conf_edd, it->conf);
|
|
return 1;
|
|
}
|
|
|
|
EAPI int
|
|
e_modapi_info(E_Module *m)
|
|
{
|
|
char buf[4096];
|
|
|
|
snprintf(buf, sizeof(buf), "%s/module_icon.png", e_module_dir_get(m));
|
|
m->icon_file = strdup(buf);
|
|
return 1;
|
|
}
|
|
|
|
EAPI int
|
|
e_modapi_about(E_Module *m)
|
|
{
|
|
e_module_dialog_show(_("Enlightenment ITray Module"),
|
|
_("This is the ITray system tray module for Enlightenment.<br>"
|
|
"It will hold system tray icons.<br>"
|
|
"Beware that this can be buggy due to many systray providing<br>"
|
|
"applications not handling the protocol properly, and the way<br>"
|
|
"systray icons work being very limiting and hacky. Do not use<br>"
|
|
"this module unless you absolutely must, and if you do, beware<br>"
|
|
"of issues that will appear."
|
|
));
|
|
return 1;
|
|
}
|
|
|
|
EAPI int
|
|
e_modapi_config(E_Module *m)
|
|
{
|
|
ITray *e;
|
|
Evas_List *l;
|
|
|
|
e = m->data;
|
|
if (!e) return 0;
|
|
if (!e->boxes) return 0;
|
|
|
|
for (l = e->boxes; l; l = l->next)
|
|
{
|
|
ITray_Box *face;
|
|
face = l->data;
|
|
if (!face) return 0;
|
|
if (face->con == e_container_current_get(e_manager_current_get()))
|
|
{
|
|
_config_itray_module(face->con, face->itray);
|
|
break;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* module private routines */
|
|
static ITray *
|
|
_itray_new()
|
|
{
|
|
ITray *it;
|
|
Evas_List *managers, *l, *l2, *cl;
|
|
|
|
box_count = 0;
|
|
it = E_NEW(ITray, 1);
|
|
if (!it) return NULL;
|
|
|
|
conf_box_edd = E_CONFIG_DD_NEW("ITray_Config_Box", Config_Box);
|
|
#undef T
|
|
#undef D
|
|
#define T Config_Box
|
|
#define D conf_box_edd
|
|
E_CONFIG_VAL(D, T, enabled, UCHAR);
|
|
|
|
conf_edd = E_CONFIG_DD_NEW("ITray_Config", Config);
|
|
#undef T
|
|
#undef D
|
|
#define T Config
|
|
#define D conf_edd
|
|
E_CONFIG_VAL(D, T, rowsize, INT);
|
|
E_CONFIG_VAL(D, T, width, INT);
|
|
E_CONFIG_LIST(D, T, boxes, conf_box_edd);
|
|
|
|
it->conf = e_config_domain_load("module.itray", conf_edd);
|
|
if (!it->conf)
|
|
{
|
|
it->conf = E_NEW(Config, 1);
|
|
it->conf->rowsize = 1;
|
|
it->conf->width = ITRAY_WIDTH_AUTO;
|
|
}
|
|
E_CONFIG_LIMIT(it->conf->rowsize, 1, 6);
|
|
E_CONFIG_LIMIT(it->conf->width, -2, -1);
|
|
|
|
_itray_config_menu_new(it);
|
|
|
|
managers = e_manager_list();
|
|
cl = it->conf->boxes;
|
|
for (l = managers; l; l = l->next)
|
|
{
|
|
E_Manager *man;
|
|
|
|
man = l->data;
|
|
for (l2 = man->containers; l2; l2 = l2->next)
|
|
{
|
|
E_Container *con;
|
|
ITray_Box *itb;
|
|
/* Config */
|
|
con = l2->data;
|
|
itb = _itray_box_new(it, con);
|
|
if (itb)
|
|
{
|
|
E_Menu_Item *mi;
|
|
|
|
if (!cl)
|
|
{
|
|
itb->conf = E_NEW(Config_Box, 1);
|
|
itb->conf->enabled = 1;
|
|
it->conf->boxes = evas_list_append(it->conf->boxes, itb->conf);
|
|
}
|
|
else
|
|
{
|
|
itb->conf = cl->data;
|
|
cl = cl->next;
|
|
}
|
|
|
|
/* Menu */
|
|
_itray_box_menu_new(itb);
|
|
|
|
/* Add main menu to box menu */
|
|
mi = e_menu_item_new(it->config_menu);
|
|
e_menu_item_label_set(mi, con->name);
|
|
e_menu_item_submenu_set(mi, itb->menu);
|
|
|
|
/* Setup */
|
|
if (!itb->conf->enabled)
|
|
_itray_box_disable(itb);
|
|
}
|
|
}
|
|
}
|
|
return it;
|
|
}
|
|
|
|
static void
|
|
_itray_free(ITray *it)
|
|
{
|
|
E_CONFIG_DD_FREE(conf_edd);
|
|
E_CONFIG_DD_FREE(conf_box_edd);
|
|
|
|
while (it->boxes)
|
|
_itray_box_free(it->boxes->data);
|
|
|
|
e_object_del(E_OBJECT(it->config_menu));
|
|
evas_list_free(it->conf->boxes);
|
|
free(it->conf);
|
|
free(it);
|
|
}
|
|
|
|
static ITray_Box *
|
|
_itray_box_new(ITray *it, E_Container *con)
|
|
{
|
|
ITray_Box *itb;
|
|
Evas_Object *o;
|
|
E_Gadman_Policy policy;
|
|
Evas_Coord x, y, w, h;
|
|
|
|
itb = E_NEW(ITray_Box, 1);
|
|
if (!itb) return NULL;
|
|
itb->itray = it;
|
|
it->boxes = evas_list_append(it->boxes, itb);
|
|
|
|
itb->con = con;
|
|
e_object_ref(E_OBJECT(con));
|
|
itb->evas = con->bg_evas;
|
|
|
|
itb->tray = NULL;
|
|
|
|
itb->x = itb->y = itb->w = itb->h = -1;
|
|
|
|
evas_event_freeze(itb->evas);
|
|
o = edje_object_add(itb->evas);
|
|
itb->box_object = o;
|
|
e_theme_edje_object_set(o, "base/theme/modules/itray",
|
|
"modules/itray/main");
|
|
evas_object_show(o);
|
|
|
|
o = evas_object_rectangle_add(itb->evas);
|
|
itb->event_object = o;
|
|
evas_object_layer_set(o, 2);
|
|
evas_object_repeat_events_set(o, 1);
|
|
evas_object_color_set(o, 0, 0, 0, 0);
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN, _itray_box_cb_mouse_in, itb);
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, _itray_box_cb_mouse_out, itb);
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _itray_box_cb_mouse_down, itb);
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _itray_box_cb_mouse_up, itb);
|
|
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _itray_box_cb_mouse_move, itb);
|
|
evas_object_show(o);
|
|
|
|
o = e_box_add(itb->evas);
|
|
itb->item_object = o;
|
|
_itray_tray_init(itb);
|
|
e_box_freeze(o);
|
|
edje_object_part_swallow(itb->box_object, "tray", o);
|
|
evas_object_show(o);
|
|
|
|
e_box_align_set(itb->item_object, 0.5, 0.5);
|
|
|
|
evas_object_resize(itb->box_object, 1000, 1000);
|
|
edje_object_calc_force(itb->box_object);
|
|
edje_object_part_geometry_get(itb->box_object, "tray", &x, &y, &w, &h);
|
|
itb->box_inset.l = x;
|
|
itb->box_inset.r = 1000 - (x + w);
|
|
itb->box_inset.t = y;
|
|
itb->box_inset.b = 1000 - (y + h);
|
|
|
|
e_box_thaw(itb->item_object);
|
|
|
|
itb->gmc = e_gadman_client_new(itb->con->gadman);
|
|
e_gadman_client_domain_set(itb->gmc, "module.itray", box_count++);
|
|
policy = E_GADMAN_POLICY_EDGES | E_GADMAN_POLICY_HMOVE | E_GADMAN_POLICY_VMOVE;
|
|
if (itb->itray->conf->width == ITRAY_WIDTH_FIXED)
|
|
policy |= E_GADMAN_POLICY_VSIZE;
|
|
e_gadman_client_policy_set(itb->gmc, policy);
|
|
e_gadman_client_min_size_set(itb->gmc, 8, 8);
|
|
e_gadman_client_max_size_set(itb->gmc, 3200, 3200);
|
|
e_gadman_client_auto_size_set(itb->gmc, -1, -1);
|
|
e_gadman_client_align_set(itb->gmc, 0.0, 1.0);
|
|
e_gadman_client_resize(itb->gmc, 400, 32);
|
|
e_gadman_client_change_func_set(itb->gmc, _itray_box_cb_gmc_change, itb);
|
|
e_gadman_client_edge_set(itb->gmc, E_GADMAN_EDGE_BOTTOM);
|
|
e_gadman_client_load(itb->gmc);
|
|
|
|
evas_event_thaw(itb->evas);
|
|
|
|
/* We need to resize, if the width is auto and the number
|
|
* of apps has changed since last startup */
|
|
_itray_box_frame_resize(itb);
|
|
return itb;
|
|
}
|
|
|
|
static void
|
|
_itray_box_free(ITray_Box *itb)
|
|
{
|
|
e_object_unref(E_OBJECT(itb->con));
|
|
e_object_del(E_OBJECT(itb->menu));
|
|
|
|
evas_object_del(itb->box_object);
|
|
evas_object_del(itb->item_object);
|
|
evas_object_del(itb->event_object);
|
|
|
|
if (itb->tray)
|
|
{
|
|
_itray_tray_shutdown(itb);
|
|
itb->tray = NULL;
|
|
}
|
|
|
|
e_gadman_client_save(itb->gmc);
|
|
e_object_del(E_OBJECT(itb->gmc));
|
|
|
|
itb->itray->boxes = evas_list_remove(itb->itray->boxes, itb);
|
|
|
|
free(itb->conf);
|
|
free(itb);
|
|
box_count--;
|
|
}
|
|
|
|
static void
|
|
_itray_box_menu_new(ITray_Box *itb)
|
|
{
|
|
E_Menu *mn;
|
|
E_Menu_Item *mi;
|
|
|
|
mn = e_menu_new();
|
|
itb->menu = mn;
|
|
|
|
/* Config */
|
|
mi = e_menu_item_new(mn);
|
|
e_menu_item_label_set(mi, _("Configuration"));
|
|
e_util_menu_item_edje_icon_set(mi, "enlightenment/configuration");
|
|
e_menu_item_callback_set(mi, _itray_box_cb_menu_configure, itb);
|
|
|
|
/* Edit */
|
|
mi = e_menu_item_new(mn);
|
|
e_menu_item_label_set(mi, _("Edit Mode"));
|
|
e_util_menu_item_edje_icon_set(mi, "enlightenment/gadgets");
|
|
e_menu_item_callback_set(mi, _itray_box_cb_menu_edit, itb);
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi)
|
|
{
|
|
ITray_Box *itb;
|
|
|
|
itb = (ITray_Box *)data;
|
|
if (!itb) return;
|
|
_config_itray_module(itb->con, itb->itray);
|
|
}
|
|
|
|
static void
|
|
_itray_box_disable(ITray_Box *itb)
|
|
{
|
|
itb->conf->enabled = 0;
|
|
evas_object_hide(itb->box_object);
|
|
evas_object_hide(itb->item_object);
|
|
evas_object_hide(itb->event_object);
|
|
e_config_save_queue();
|
|
}
|
|
|
|
void
|
|
_itray_config_menu_new(ITray *it)
|
|
{
|
|
E_Menu *mn;
|
|
|
|
mn = e_menu_new();
|
|
it->config_menu = mn;
|
|
}
|
|
|
|
static void
|
|
_itray_box_frame_resize(ITray_Box *itb)
|
|
{
|
|
Evas_Coord w, h, bw, bh;
|
|
int icons_per_row;
|
|
/* Not finished loading config yet! */
|
|
if ((itb->x == -1) ||
|
|
(itb->y == -1) ||
|
|
(itb->w == -1) ||
|
|
(itb->h == -1))
|
|
return;
|
|
|
|
evas_event_freeze(itb->evas);
|
|
e_box_freeze(itb->item_object);
|
|
|
|
if (e_box_pack_count_get(itb->item_object))
|
|
e_box_min_size_get(itb->item_object, &w, &h);
|
|
else
|
|
{
|
|
if (!itb->tray)
|
|
w = h = TRAY_ICON_SIZE + itb->box_inset.l + itb->box_inset.r;
|
|
else if (!itb->tray->icons)
|
|
w = h = TRAY_ICON_SIZE + itb->box_inset.l + itb->box_inset.r;
|
|
else
|
|
{
|
|
if (itb->tray->rows > 0) itb->tray->rows = 1;
|
|
icons_per_row = (itb->tray->icons +
|
|
(itb->tray->icons % itb->tray->rows)) / itb->tray->rows;
|
|
w = (icons_per_row * TRAY_ICON_SIZE)
|
|
+ itb->box_inset.l + itb->box_inset.r;
|
|
h = (itb->tray->rows * TRAY_ICON_SIZE)
|
|
+ itb->box_inset.t + itb->box_inset.b;
|
|
}
|
|
}
|
|
edje_object_part_unswallow(itb->box_object, itb->item_object);
|
|
/* edje_extern_object_min_size_set(itb->item_object, w, h);*/
|
|
/* edje_object_part_swallow(itb->box_object, "tray", itb->item_object);*/
|
|
/* edje_object_size_min_calc(itb->box_object, &bw, &bh);*/
|
|
edje_extern_object_min_size_set(itb->item_object, 0, 0);
|
|
edje_object_part_swallow(itb->box_object, "tray", itb->item_object);
|
|
|
|
e_box_thaw(itb->item_object);
|
|
evas_event_thaw(itb->evas);
|
|
|
|
if (itb->itray->conf->width == ITRAY_WIDTH_AUTO)
|
|
{
|
|
if ((e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_LEFT) ||
|
|
(e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_RIGHT))
|
|
{
|
|
e_gadman_client_resize(itb->gmc, h, w);
|
|
}
|
|
else if ((e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_TOP) ||
|
|
(e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_BOTTOM))
|
|
{
|
|
e_gadman_client_resize(itb->gmc, w, h);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_LEFT) ||
|
|
(e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_RIGHT))
|
|
{
|
|
/* h is the width of the box */
|
|
e_gadman_client_resize(itb->gmc, bw, itb->h);
|
|
}
|
|
else if ((e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_TOP) ||
|
|
(e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_BOTTOM))
|
|
{
|
|
/* w is the width of the box */
|
|
e_gadman_client_resize(itb->gmc, itb->w, bh);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_edge_change(ITray_Box *itb, int edge)
|
|
{
|
|
Evas_Coord bw, bh, tmp;
|
|
Evas_Object *o;
|
|
E_Gadman_Policy policy;
|
|
int changed;
|
|
|
|
evas_event_freeze(itb->evas);
|
|
o = itb->box_object;
|
|
edje_object_signal_emit(o, "set_orientation", _itray_main_orientation[edge]);
|
|
edje_object_message_signal_process(o);
|
|
|
|
e_box_freeze(itb->item_object);
|
|
e_box_align_set(itb->item_object, 0.5, 0.5);
|
|
|
|
policy = E_GADMAN_POLICY_EDGES | E_GADMAN_POLICY_HMOVE | E_GADMAN_POLICY_VMOVE;
|
|
if ((edge == E_GADMAN_EDGE_BOTTOM) ||
|
|
(edge == E_GADMAN_EDGE_TOP))
|
|
{
|
|
changed = (e_box_orientation_get(itb->item_object) != 1);
|
|
if (changed)
|
|
{
|
|
e_box_orientation_set(itb->item_object, 1);
|
|
if (itb->itray->conf->width == ITRAY_WIDTH_FIXED)
|
|
policy |= E_GADMAN_POLICY_HSIZE;
|
|
e_gadman_client_policy_set(itb->gmc, policy);
|
|
tmp = itb->w;
|
|
itb->w = itb->h;
|
|
itb->h = tmp;
|
|
}
|
|
}
|
|
else if ((edge == E_GADMAN_EDGE_LEFT) ||
|
|
(edge == E_GADMAN_EDGE_RIGHT))
|
|
{
|
|
changed = (e_box_orientation_get(itb->item_object) != 0);
|
|
if (changed)
|
|
{
|
|
e_box_orientation_set(itb->item_object, 0);
|
|
if (itb->itray->conf->width == ITRAY_WIDTH_FIXED)
|
|
policy |= E_GADMAN_POLICY_VSIZE;
|
|
e_gadman_client_policy_set(itb->gmc, policy);
|
|
tmp = itb->w;
|
|
itb->w = itb->h;
|
|
itb->h = tmp;
|
|
}
|
|
}
|
|
|
|
e_box_thaw(itb->item_object);
|
|
evas_event_thaw(itb->evas);
|
|
|
|
_itray_box_frame_resize(itb);
|
|
}
|
|
|
|
static void
|
|
_itray_box_update_policy(ITray_Box *itb)
|
|
{
|
|
E_Gadman_Policy policy;
|
|
|
|
policy = E_GADMAN_POLICY_EDGES | E_GADMAN_POLICY_HMOVE | E_GADMAN_POLICY_VMOVE;
|
|
if ((e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_BOTTOM) ||
|
|
(e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_TOP))
|
|
{
|
|
if (itb->itray->conf->width == ITRAY_WIDTH_FIXED)
|
|
policy |= E_GADMAN_POLICY_HSIZE;
|
|
e_gadman_client_policy_set(itb->gmc, policy);
|
|
}
|
|
else if ((e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_LEFT) ||
|
|
(e_gadman_client_edge_get(itb->gmc) == E_GADMAN_EDGE_RIGHT))
|
|
{
|
|
if (itb->itray->conf->width == ITRAY_WIDTH_FIXED)
|
|
policy |= E_GADMAN_POLICY_VSIZE;
|
|
e_gadman_client_policy_set(itb->gmc, policy);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Evas_Event_Mouse_In *ev;
|
|
ITray_Box *itb;
|
|
|
|
ev = event_info;
|
|
itb = data;
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Out *ev;
|
|
ITray_Box *itb;
|
|
|
|
ev = event_info;
|
|
itb = data;
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Down *ev;
|
|
ITray_Box *itb;
|
|
|
|
ev = event_info;
|
|
itb = data;
|
|
/*
|
|
if (ev->button == 3)
|
|
{
|
|
e_menu_activate_mouse(itb->menu, e_zone_current_get(itb->con),
|
|
ev->output.x, ev->output.y, 1, 1,
|
|
E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
|
|
e_util_container_fake_mouse_up_later(itb->con, 3);
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
Ecore_X_Window win;
|
|
int x, y, w, h, xx, yy;
|
|
Evas_List *l;
|
|
|
|
for (l = itb->tray->wins; l; l = l->next)
|
|
{
|
|
win = (Ecore_X_Window)l->data;
|
|
|
|
evas_pointer_output_xy_get(itb->evas, &xx, &yy);
|
|
evas_object_geometry_get(itb->item_object, &x, &y, NULL, NULL);
|
|
xx -= x;
|
|
yy -= y;
|
|
ecore_x_window_geometry_get(win, &x, &y, &w, &h);
|
|
if (E_CONTAINS(x, y, w, h, xx, yy, 1, 1))
|
|
{
|
|
x = xx - x;
|
|
y = yy - y;
|
|
win = ecore_x_window_at_xy_begin_get(win, x, y);
|
|
ecore_x_pointer_ungrab();
|
|
ecore_x_flush();
|
|
ecore_x_mouse_down_send(win, x, y, ev->button);
|
|
e_util_container_fake_mouse_up_later(itb->con, ev->button);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Up *ev;
|
|
ITray_Box *itb;
|
|
|
|
ev = event_info;
|
|
itb = data;
|
|
/*
|
|
if (ev->button == 3)
|
|
{
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
Ecore_X_Window win;
|
|
int x, y, w, h, xx, yy;
|
|
Evas_List *l;
|
|
|
|
for (l = itb->tray->wins; l; l = l->next)
|
|
{
|
|
win = (Ecore_X_Window)l->data;
|
|
|
|
evas_pointer_output_xy_get(itb->evas, &xx, &yy);
|
|
evas_object_geometry_get(itb->item_object, &x, &y, NULL, NULL);
|
|
xx -= x;
|
|
yy -= y;
|
|
ecore_x_window_geometry_get(win, &x, &y, &w, &h);
|
|
if (E_CONTAINS(x, y, w, h, xx, yy, 1, 1))
|
|
{
|
|
x = xx - x;
|
|
y = yy - y;
|
|
win = ecore_x_window_at_xy_begin_get(win, x, y);
|
|
ecore_x_mouse_up_send(win, x, y, ev->button);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
Evas_Event_Mouse_Move *ev;
|
|
ITray_Box *itb;
|
|
|
|
ev = event_info;
|
|
itb = data;
|
|
{
|
|
Ecore_X_Window win;
|
|
int x, y, w, h, xx, yy;
|
|
Evas_List *l;
|
|
|
|
for (l = itb->tray->wins; l; l = l->next)
|
|
{
|
|
win = (Ecore_X_Window)l->data;
|
|
|
|
evas_pointer_output_xy_get(itb->evas, &xx, &yy);
|
|
evas_object_geometry_get(itb->item_object, &x, &y, NULL, NULL);
|
|
xx -= x;
|
|
yy -= y;
|
|
ecore_x_window_geometry_get(win, &x, &y, &w, &h);
|
|
if (E_CONTAINS(x, y, w, h, xx, yy, 1, 1))
|
|
{
|
|
x = xx - x;
|
|
y = yy - y;
|
|
win = ecore_x_window_at_xy_begin_get(win, x, y);
|
|
ecore_x_mouse_move_send(win, x, y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_gmc_change(void *data, E_Gadman_Client *gmc, E_Gadman_Change change)
|
|
{
|
|
ITray_Box *itb;
|
|
|
|
itb = data;
|
|
switch (change)
|
|
{
|
|
case E_GADMAN_CHANGE_MOVE_RESIZE:
|
|
e_gadman_client_geometry_get(itb->gmc, &itb->x, &itb->y, &itb->w, &itb->h);
|
|
|
|
edje_extern_object_min_size_set(itb->item_object, 0, 0);
|
|
edje_object_part_swallow(itb->box_object, "tray", itb->item_object);
|
|
|
|
evas_object_move(itb->box_object, itb->x, itb->y);
|
|
evas_object_resize(itb->box_object, itb->w, itb->h);
|
|
break;
|
|
case E_GADMAN_CHANGE_EDGE:
|
|
_itray_box_edge_change(itb, e_gadman_client_edge_get(itb->gmc));
|
|
break;
|
|
case E_GADMAN_CHANGE_RAISE:
|
|
case E_GADMAN_CHANGE_ZONE:
|
|
/* Ignore */
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_width_auto(void *data)
|
|
{
|
|
ITray *it;
|
|
ITray_Box *itb;
|
|
Evas_List *l;
|
|
|
|
it = (ITray *)data;
|
|
for (l = it->boxes; l; l = l->next)
|
|
{
|
|
itb = l->data;
|
|
_itray_box_update_policy(itb);
|
|
_itray_box_frame_resize(itb);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_box_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi)
|
|
{
|
|
ITray_Box *itb;
|
|
|
|
itb = data;
|
|
e_gadman_mode_set(itb->gmc->gadman, E_GADMAN_MODE_EDIT);
|
|
}
|
|
|
|
void
|
|
_itray_box_cb_config_updated(void *data)
|
|
{
|
|
/* Call Any Needed Funcs To Let Module Handle Config Changes */
|
|
_itray_box_cb_width_auto(data);
|
|
}
|
|
|
|
void
|
|
_itray_tray_init(ITray_Box *itb)
|
|
{
|
|
Evas_Coord x, y, w, h;
|
|
Ecore_X_Window *windows;
|
|
int wnum;
|
|
|
|
/* FIXME - temp */
|
|
itb->tray = malloc(sizeof(ITray_Tray));
|
|
itb->tray->icons = 0;
|
|
itb->tray->w = 1;
|
|
itb->tray->h = 1;
|
|
itb->tray->wins = NULL;
|
|
|
|
evas_object_resize(itb->item_object, itb->tray->w, itb->tray->h);
|
|
evas_object_color_set(itb->item_object, 0, 0, 0, 0);
|
|
evas_object_intercept_move_callback_add(itb->item_object, _itray_tray_cb_move, itb);
|
|
evas_object_intercept_resize_callback_add(itb->item_object, _itray_tray_cb_resize, itb);
|
|
|
|
_itray_tray_active_set(itb, 1);
|
|
|
|
evas_object_geometry_get(itb->item_object, &x, &y, &w, &h);
|
|
itb->tray->win = ecore_x_window_new(itb->con->bg_win, x, y, w, h);
|
|
ecore_x_window_container_manage(itb->tray->win);
|
|
/* this sucks because some icons inherit the bg pixmap/color of the parent win and thus the color... and are not shaped */
|
|
ecore_x_window_background_color_set(itb->tray->win, 0xffff, 0xffff, 0xffff);
|
|
|
|
itb->tray->msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _itray_tray_cb_msg, itb);
|
|
itb->tray->dst_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _itray_tray_cb_destroy, itb);
|
|
|
|
windows = ecore_x_window_children_get(itb->con->manager->root, &wnum);
|
|
if (windows)
|
|
{
|
|
int i;
|
|
Ecore_X_Atom atom_xmbed, atom_kde_netwm_systray, atom_kwm_dockwindow,
|
|
atom_window;
|
|
|
|
atom_window = ecore_x_atom_get("WINDOW");
|
|
atom_xmbed = ecore_x_atom_get("_XEMBED_INFO");
|
|
atom_kde_netwm_systray = ecore_x_atom_get("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR");
|
|
atom_kwm_dockwindow = ecore_x_atom_get("KWM_DOCKWINDOW");
|
|
for (i = 0; i < wnum; i++)
|
|
{
|
|
Ecore_X_Window_Attributes att;
|
|
|
|
if (ecore_x_window_attributes_get(windows[i], &att))
|
|
{
|
|
// if (0)
|
|
// if (att.visible)
|
|
{
|
|
unsigned char *data = NULL;
|
|
int count;
|
|
|
|
if (!ecore_x_window_prop_property_get(windows[i],
|
|
atom_xmbed,
|
|
atom_xmbed, 32,
|
|
&data, &count))
|
|
data = NULL;
|
|
if (!data)
|
|
{
|
|
if (!ecore_x_window_prop_property_get(windows[i],
|
|
atom_kde_netwm_systray,
|
|
atom_xmbed, 32,
|
|
&data, &count))
|
|
data = NULL;
|
|
}
|
|
if (!data)
|
|
{
|
|
if (!ecore_x_window_prop_property_get(windows[i],
|
|
atom_kwm_dockwindow,
|
|
atom_kwm_dockwindow, 32,
|
|
&data, &count))
|
|
data = NULL;
|
|
}
|
|
if (data)
|
|
{
|
|
printf("found %x\n", windows[i]);
|
|
_itray_tray_add(itb, windows[i]);
|
|
free(data);
|
|
data = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(windows);
|
|
}
|
|
_itray_reshape(itb);
|
|
}
|
|
|
|
void
|
|
_itray_tray_shutdown(ITray_Box *itb)
|
|
{
|
|
_itray_tray_active_set(itb, 0);
|
|
|
|
while (itb->tray->wins)
|
|
{
|
|
Ecore_X_Window win;
|
|
Ecore_X_Window_Attributes att;
|
|
|
|
win = (Ecore_X_Window)(itb->tray->wins->data);
|
|
ecore_x_window_hide(win);
|
|
ecore_x_window_reparent(win, itb->con->manager->root, 0, 0);
|
|
itb->tray->wins = evas_list_remove_list(itb->tray->wins, itb->tray->wins);
|
|
}
|
|
evas_object_del(itb->item_object);
|
|
|
|
ecore_event_handler_del(itb->tray->msg_handler);
|
|
ecore_event_handler_del(itb->tray->dst_handler);
|
|
ecore_x_window_del(itb->tray->win);
|
|
}
|
|
|
|
static void
|
|
_itray_tray_active_set(ITray_Box *itb, int active)
|
|
{
|
|
Ecore_X_Window win;
|
|
Display *display;
|
|
char buf[32];
|
|
Ecore_X_Atom selection_atom;
|
|
|
|
win = 0;
|
|
if (active)
|
|
win = itb->con->bg_win;
|
|
|
|
display = ecore_x_display_get();
|
|
snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", itb->con->manager->num);
|
|
selection_atom = ecore_x_atom_get(buf);
|
|
/* FIXXME: nasty xlib snippets! */
|
|
XSetSelectionOwner(display, selection_atom, win, CurrentTime);
|
|
if ((active) &&
|
|
(XGetSelectionOwner(display, selection_atom) == itb->con->bg_win))
|
|
{
|
|
printf("send message thast we own the tray now\n");
|
|
ecore_x_client_message32_send(itb->con->manager->root,
|
|
ecore_x_atom_get("MANAGER"),
|
|
ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
|
|
CurrentTime, selection_atom, win, 0, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_itray_tray_add(ITray_Box *itb, Ecore_X_Window win)
|
|
{
|
|
if (!win) return;
|
|
if (evas_list_find(itb->tray->wins, (void *)win))
|
|
return;
|
|
e_stolen_win_add(win);
|
|
ecore_x_window_show(itb->tray->win);
|
|
evas_object_show(itb->item_object);
|
|
|
|
/* FIXME: adding a window id AS a pointer - BAD! */
|
|
/* FIXME: need to listen for shape change events on icons */
|
|
/* FIXME: on shape change need to inherit shape */
|
|
|
|
/* properties u might find on sample windows:
|
|
*
|
|
* GDK_TIMESTAMP_PROP(GDK_TIMESTAMP_PROP) = 0x61
|
|
* _NET_WM_SYNC_REQUEST_COUNTER(CARDINAL) = 29360209
|
|
* _XEMBED_INFO(_XEMBED_INFO) = 0x1, 0x1
|
|
* WM_CLIENT_LEADER(WINDOW): window id # 0x1c00001
|
|
* _NET_WM_PID(CARDINAL) = 17802
|
|
* WM_LOCALE_NAME(STRING) = "ja_JP.UTF-8"
|
|
* WM_CLIENT_MACHINE(STRING) = "icky"
|
|
* WM_NORMAL_HINTS(WM_SIZE_HINTS):
|
|
* program specified minimum size: 24 by 24
|
|
* window gravity: NorthWest
|
|
* WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_SYNC_REQUEST
|
|
* WM_CLASS(STRING) = "gaim", "Gaim"
|
|
* WM_ICON_NAME(STRING) = "Gaim"
|
|
* _NET_WM_ICON_NAME(UTF8_STRING) = 0x47, 0x61, 0x69, 0x6d
|
|
* WM_NAME(STRING) = "Gaim"
|
|
* _NET_WM_NAME(UTF8_STRING) = 0x47, 0x61, 0x69, 0x6d
|
|
*---
|
|
* GDK_TIMESTAMP_PROP(GDK_TIMESTAMP_PROP) = 0x61
|
|
* _NET_WM_SYNC_REQUEST_COUNTER(CARDINAL) = 29360172
|
|
* _XEMBED_INFO(_XEMBED_INFO) = 0x1, 0x1
|
|
* WM_CLIENT_LEADER(WINDOW): window id # 0x1c00001
|
|
* _NET_WM_PID(CARDINAL) = 17841
|
|
* WM_LOCALE_NAME(STRING) = "ja_JP.UTF-8"
|
|
* WM_CLIENT_MACHINE(STRING) = "icky"
|
|
* WM_NORMAL_HINTS(WM_SIZE_HINTS):
|
|
* program specified minimum size: 16 by 16
|
|
* window gravity: NorthWest
|
|
* WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_SYNC_REQUEST
|
|
* WM_CLASS(STRING) = "gnomemeeting", "Gnomemeeting"
|
|
* WM_ICON_NAME(STRING) = "GnomeMeeting Tray Icon"
|
|
* _NET_WM_ICON_NAME(UTF8_STRING) = 0x47, 0x6e, 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x54, 0x72, 0x61, 0x79, 0x20, 0x49, 0x63, 0x6f, 0x6e
|
|
* WM_NAME(STRING) = "GnomeMeeting Tray Icon"
|
|
* _NET_WM_NAME(UTF8_STRING) = 0x47, 0x6e, 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x54, 0x72, 0x61, 0x79, 0x20, 0x49, 0x63, 0x6f, 0x6e
|
|
*---
|
|
* _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR(WINDOW): window id # 0x0
|
|
* KWM_DOCKWINDOW(KWM_DOCKWINDOW) = 0x0
|
|
* WM_CLIENT_LEADER(WINDOW): window id # 0x1c00006
|
|
* WM_WINDOW_ROLE(STRING) = "skypedock"
|
|
* _NET_WM_PID(CARDINAL) = 18018
|
|
* _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
|
|
* WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING
|
|
* WM_NAME(STRING) = "skype"
|
|
* WM_LOCALE_NAME(STRING) = "ja_JP.UTF-8"
|
|
* WM_CLASS(STRING) = "skypedock", "Skype"
|
|
* WM_HINTS(WM_HINTS):
|
|
* Initial state is Normal State.
|
|
* bitmap id # to use for icon: 0x1c00025
|
|
* bitmap id # of mask for icon: 0x1c00026
|
|
* window id # to use for icon: 0x1c000b1
|
|
* window id # of group leader: 0x1c000b1
|
|
* WM_NORMAL_HINTS(WM_SIZE_HINTS):
|
|
* user specified size: 22 by 22
|
|
* program specified size: 22 by 22
|
|
* program specified minimum size: 22 by 22
|
|
* program specified maximum size: 22 by 22
|
|
* window gravity: NorthWest
|
|
* WM_CLIENT_MACHINE(STRING) = "icky"
|
|
*
|
|
*/
|
|
/* we want to insert at the end, so as not to move all icons on each add */
|
|
itb->tray->wins = evas_list_append(itb->tray->wins, (void *)win);
|
|
itb->tray->icons++;
|
|
ecore_x_window_client_manage(win);
|
|
ecore_x_window_resize(win, TRAY_ICON_SIZE, TRAY_ICON_SIZE);
|
|
|
|
ecore_x_window_save_set_add(win);
|
|
ecore_x_window_shape_events_select(win, 1);
|
|
ecore_x_window_reparent(win, itb->tray->win, 0, 0);
|
|
ecore_x_window_raise(itb->con->event_win);
|
|
_itray_tray_layout(itb);
|
|
_itray_box_frame_resize(itb);
|
|
|
|
ecore_x_window_show(win);
|
|
|
|
}
|
|
|
|
static void
|
|
_itray_tray_remove(ITray_Box *itb, Ecore_X_Window win)
|
|
{
|
|
|
|
if (!win)
|
|
return;
|
|
if (!evas_list_find(itb->tray->wins, (void *)win)) /* if was not found */
|
|
return;
|
|
e_stolen_win_del(win);
|
|
itb->tray->wins = evas_list_remove(itb->tray->wins, (void *)win);
|
|
itb->tray->icons--;
|
|
_itray_tray_layout(itb);
|
|
_itray_box_frame_resize(itb);
|
|
if (itb->tray->icons == 0)
|
|
{
|
|
ecore_x_window_hide(itb->tray->win);
|
|
evas_object_show(itb->item_object);
|
|
}
|
|
}
|
|
|
|
static int
|
|
_itray_tray_cb_msg(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Client_Message *ev;
|
|
ITray_Box *itb;
|
|
static Ecore_X_Atom atom_opcode = 0;
|
|
static Ecore_X_Atom atom_message = 0;
|
|
static Ecore_X_Atom atom_xmbed = 0;
|
|
|
|
itb = data;
|
|
ev = event;
|
|
if (atom_opcode == 0)
|
|
atom_opcode = ecore_x_atom_get("_NET_SYSTEM_TRAY_OPCODE");
|
|
if (atom_message == 0)
|
|
atom_message = ecore_x_atom_get("_NET_SYSTEM_TRAY_MESSAGE_DATA");
|
|
if (atom_xmbed == 0)
|
|
atom_xmbed = ecore_x_atom_get("_XEMBED");
|
|
if (ev->message_type == atom_opcode)
|
|
{
|
|
if (ev->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
|
|
{
|
|
_itray_tray_add(itb, (Ecore_X_Window)ev->data.l[2]);
|
|
/* Should proto be set according to clients _XEMBED_INFO? */
|
|
ecore_x_client_message32_send(ev->data.l[2],
|
|
atom_xmbed,
|
|
ECORE_X_EVENT_MASK_NONE, CurrentTime,
|
|
XEMBED_EMBEDDED_NOTIFY, 0, itb->con->bg_win, /*proto*/1);
|
|
|
|
_itray_reshape(itb);
|
|
}
|
|
else if (ev->data.l[1] == SYSTEM_TRAY_BEGIN_MESSAGE)
|
|
{
|
|
printf("begin message\n");
|
|
}
|
|
else if (ev->data.l[1] == SYSTEM_TRAY_CANCEL_MESSAGE)
|
|
{
|
|
printf("cancel message\n");
|
|
}
|
|
}
|
|
else if (ev->message_type == atom_message)
|
|
{
|
|
printf("got message\n");
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
|
|
static int
|
|
_itray_tray_cb_destroy(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Window_Destroy *ev;
|
|
ITray_Box *itb;
|
|
int exists;
|
|
|
|
itb = data;
|
|
ev = event;
|
|
exists = _itray_exists(itb, ev->win);
|
|
_itray_tray_remove(itb, ev->win);
|
|
if (exists) _itray_reshape(itb);
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_itray_tray_cb_hide(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Window_Destroy *ev;
|
|
ITray_Box *itb;
|
|
int exists;
|
|
|
|
itb = data;
|
|
ev = event;
|
|
exists = _itray_exists(itb, ev->win);
|
|
_itray_tray_remove(itb, ev->win);
|
|
if (exists) _itray_reshape(itb);
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_itray_tray_cb_shape(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Window_Shape *ev;
|
|
ITray_Box *itb;
|
|
Evas_List *l;
|
|
|
|
itb = data;
|
|
ev = event;
|
|
if (_itray_exists(itb, ev->win)) _itray_reshape(itb);
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_itray_exists(ITray_Box *itb, Ecore_X_Window win)
|
|
{
|
|
Evas_List *l;
|
|
|
|
for (l = itb->tray->wins; l; l = l->next)
|
|
{
|
|
Ecore_X_Window w;
|
|
|
|
w = (Ecore_X_Window)l->data;
|
|
if (w == win) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
_itray_reshape(ITray_Box *itb)
|
|
{
|
|
Evas_List *l;
|
|
Ecore_X_Window twin;
|
|
int i;
|
|
|
|
printf("reshape %p win %x\n", itb, itb->tray->win);
|
|
twin = ecore_x_window_override_new(itb->tray->win, 0, 0, 100, 100);
|
|
for (i = 0, l = itb->tray->wins; l; l = l->next, i++)
|
|
{
|
|
Ecore_X_Window win;
|
|
Ecore_X_Rectangle *rects;
|
|
int num;
|
|
int x, y, w, h;
|
|
|
|
win = (Ecore_X_Window)l->data;
|
|
printf("SH%i %x\n", i, win);
|
|
ecore_x_window_geometry_get(win, &x, &y, &w, &h);
|
|
rects = ecore_x_window_shape_rectangles_get(win, &num);
|
|
if (rects)
|
|
{
|
|
printf("shaped! %i\n", num);
|
|
if (i == 0)
|
|
{
|
|
ecore_x_window_shape_window_set_xy(twin, win, x, y);
|
|
}
|
|
else
|
|
{
|
|
ecore_x_window_shape_window_add_xy(twin, win, x, y);
|
|
}
|
|
free(rects);
|
|
}
|
|
else
|
|
{
|
|
printf("not shaped!\n");
|
|
if (i == 0)
|
|
{
|
|
ecore_x_window_shape_rectangle_set(twin, x, y, w, h);
|
|
}
|
|
else
|
|
{
|
|
ecore_x_window_shape_rectangle_add(twin, x, y, w, h);
|
|
}
|
|
}
|
|
if (i > 1000) break;
|
|
}
|
|
ecore_x_window_shape_window_set(itb->tray->win, twin);
|
|
ecore_x_window_del(twin);
|
|
}
|
|
|
|
static void
|
|
_itray_tray_cb_move(void *data, Evas_Object *o, Evas_Coord x, Evas_Coord y)
|
|
{
|
|
ITray_Box *itb;
|
|
|
|
itb = data;
|
|
evas_object_move(o, x, y);
|
|
evas_object_move(itb->event_object, x, y);
|
|
ecore_x_window_move(itb->tray->win, (int) x, (int) y);
|
|
}
|
|
|
|
static void
|
|
_itray_tray_cb_resize(void *data, Evas_Object *o, Evas_Coord w, Evas_Coord h)
|
|
{
|
|
ITray_Box *itb;
|
|
|
|
itb = data;
|
|
evas_object_resize(o, w, h);
|
|
evas_object_resize(itb->event_object, w, h);
|
|
|
|
_itray_tray_layout(itb);
|
|
_itray_box_frame_resize(itb);
|
|
}
|
|
|
|
static void
|
|
_itray_tray_layout(ITray_Box *itb)
|
|
{
|
|
Evas_Coord w, h, c, d;
|
|
int x, y;
|
|
Evas_List *wins;
|
|
E_Gadman_Edge edge;
|
|
|
|
if (!itb->gmc) return;
|
|
edge = e_gadman_client_edge_get(itb->gmc);
|
|
h = itb->itray->conf->rowsize * TRAY_ICON_SIZE;
|
|
if (h < TRAY_ICON_SIZE)
|
|
h = TRAY_ICON_SIZE;
|
|
c = (h - (h % TRAY_ICON_SIZE)) / TRAY_ICON_SIZE;
|
|
if (itb->tray->icons > 0 && itb->tray->icons < c + 1)
|
|
{
|
|
c = itb->tray->icons;
|
|
h = c * TRAY_ICON_SIZE;
|
|
}
|
|
w = ((itb->tray->icons + (itb->tray->icons % c)) / c) * TRAY_ICON_SIZE;
|
|
|
|
if (edge == E_GADMAN_EDGE_BOTTOM || edge == E_GADMAN_EDGE_TOP)
|
|
{
|
|
edje_object_part_unswallow(itb->box_object, itb->item_object);
|
|
evas_object_resize(itb->item_object, w, h);
|
|
ecore_x_window_resize(itb->tray->win, (int) w, (int) h);
|
|
|
|
edje_extern_object_min_size_set(itb->item_object, w, h);
|
|
edje_extern_object_max_size_set(itb->item_object, w, h);
|
|
edje_object_part_swallow(itb->box_object, "tray", itb->item_object);
|
|
}
|
|
else
|
|
{
|
|
edje_object_part_unswallow(itb->box_object, itb->item_object);
|
|
evas_object_resize(itb->item_object, h, w);
|
|
ecore_x_window_resize(itb->tray->win, (int) h, (int) w);
|
|
|
|
edje_extern_object_min_size_set(itb->item_object, w, h);
|
|
edje_extern_object_max_size_set(itb->item_object, w, h);
|
|
edje_object_part_swallow(itb->box_object, "tray", itb->item_object);
|
|
}
|
|
|
|
x = 0;
|
|
if (edge == E_GADMAN_EDGE_BOTTOM || edge == E_GADMAN_EDGE_RIGHT)
|
|
y = h - TRAY_ICON_SIZE;
|
|
else
|
|
y = 0;
|
|
d = 0;
|
|
for (wins = itb->tray->wins; wins; wins = wins->next)
|
|
{
|
|
if (edge == E_GADMAN_EDGE_BOTTOM || edge == E_GADMAN_EDGE_TOP)
|
|
ecore_x_window_move((Ecore_X_Window) wins->data, x, y);
|
|
else
|
|
ecore_x_window_move((Ecore_X_Window) wins->data, y, x);
|
|
|
|
d++;
|
|
if (d % c == 0)
|
|
{
|
|
x += TRAY_ICON_SIZE;
|
|
if (edge == E_GADMAN_EDGE_BOTTOM || edge == E_GADMAN_EDGE_RIGHT)
|
|
y = h - TRAY_ICON_SIZE;
|
|
else
|
|
y = 0;
|
|
}
|
|
else if (edge == E_GADMAN_EDGE_BOTTOM || edge == E_GADMAN_EDGE_RIGHT)
|
|
y -= TRAY_ICON_SIZE;
|
|
else
|
|
y += TRAY_ICON_SIZE;
|
|
}
|
|
itb->tray->rows = c;
|
|
}
|