<commit_before>/*
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */

#include "e.h"
#include "e_mod_main.h"

/* gadcon requirements */
static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
static void _gc_shutdown(E_Gadcon_Client *gcc);
static void _gc_orient(E_Gadcon_Client *gcc);
static char *_gc_label(void);
static Evas_Object *_gc_icon(Evas *evas);
static const char *_gc_id_new(void);
/* and actually define the gadcon class that this module provides (just 1) */
static const E_Gadcon_Client_Class _gadcon_class =
{
   GADCON_CLIENT_CLASS_VERSION,
     "pager",
     {
	_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL
     },
   E_GADCON_CLIENT_STYLE_INSET
};

/* actual module specifics */
typedef struct _Instance Instance;
typedef struct _Pager       Pager;
typedef struct _Pager_Desk  Pager_Desk;
typedef struct _Pager_Win   Pager_Win;
typedef struct _Pager_Popup Pager_Popup;

struct _Instance
{
   E_Gadcon_Client *gcc;
   Evas_Object     *o_pager; /* table */
   Pager           *pager;
   E_Drop_Handler  *drop_handler;
};

struct _Pager
{
   Instance     *inst;
   unsigned char is_popup : 1;
   Evas_Object  *o_table;
   E_Zone       *zone;
   int           xnum, ynum;
   Evas_List    *desks;
   unsigned char dragging : 1;
   unsigned char just_dragged : 1;
   Evas_Coord    dnd_x, dnd_y;
   Pager_Desk   *active_drop_pd;
};

struct _Pager_Desk
{
   Pager           *pager;
   E_Desk          *desk;
   Evas_List       *wins;
   Evas_Object     *o_desk;
   Evas_Object     *o_layout;
   int              xpos, ypos;
   int              current : 1;
   int              urgent;
   struct {
      Pager         *from_pager;
      unsigned char  in_pager : 1;
      unsigned char  start : 1;
      int            x, y;
      int            dx, dy;
      int            button;
   } drag;
};

struct _Pager_Win
{
   E_Border     *border;
   Pager_Desk   *desk;
   Evas_Object  *o_window;
   Evas_Object  *o_icon;
   unsigned char skip_winlist : 1;
   struct {
      Pager         *from_pager;
      unsigned char  start : 1;
      unsigned char  in_pager : 1;
      unsigned char  no_place : 1;
      unsigned char  desktop  : 1;
      int            x, y;
      int            dx, dy;
      int            button;
   } drag;
};

struct _Pager_Popup
{
   E_Popup      *popup;
   Pager        *pager;
   Evas_Object  *o_bg;
   Ecore_Timer  *timer;
   unsigned char urgent : 1;
};

static void _pager_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _menu_cb_post(void *data, E_Menu *m);
static void _pager_inst_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi);
static void _pager_inst_cb_menu_virtual_desktops_dialog(void *data, E_Menu *m, E_Menu_Item *mi);
static void _pager_instance_drop_zone_recalc(Instance *inst);
static int _pager_cb_event_border_resize(void *data, int type, void *event);
static int _pager_cb_event_border_move(void *data, int type, void *event);
static int _pager_cb_event_border_add(void *data, int type, void *event);
static int _pager_cb_event_border_remove(void *data, int type, void *event);
static int _pager_cb_event_border_iconify(void *data, int type, void *event);
static int _pager_cb_event_border_uniconify(void *data, int type, void *event);
static int _pager_cb_event_border_stick(void *data, int type, void *event);
static int _pager_cb_event_border_unstick(void *data, int type, void *event);
static int _pager_cb_event_border_desk_set(void *data, int type, void *event);
static int _pager_cb_event_border_stack(void *data, int type, void *event);
static int _pager_cb_event_border_icon_change(void *data, int type, void *event);
static int _pager_cb_event_border_urgent_change(void *data, int type, void *event);
static int _pager_cb_event_border_property(void *data, int type, void *event);
static int _pager_cb_event_zone_desk_count_set(void *data, int type, void *event);
static int _pager_cb_event_desk_show(void *data, int type, void *event);
static int _pager_cb_event_desk_name_change(void *data, int type, void *event);
static int _pager_cb_event_container_resize(void *data, int type, void *event);
static void _pager_window_cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void *_pager_window_cb_drag_convert(E_Drag *drag, const char *type);
static void _pager_window_cb_drag_finished(E_Drag *drag, int dropped);
static void _pager_inst_cb_enter(void *data, const char *type, void *event_info);
static void _pager_inst_cb_move(void *data, const char *type, void *event_info);
static void _pager_inst_cb_leave(void *data, const char *type, void *event_info);
static void _pager_inst_cb_drop(void *data, const char *type, void *event_info);
static void _pager_inst_cb_scroll(void *data);
static void _pager_update_drop_position(Instance *inst, Evas_Coord x, Evas_Coord y);
static void _pager_desk_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_desk_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_desk_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_desk_cb_drag_finished(E_Drag *drag, int dropped);
static void _pager_desk_cb_mouse_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info);
static int _pager_popup_cb_timeout(void *data);
static Pager *_pager_new(Evas *evas, E_Zone *zone);
static void _pager_free(Pager *p);
static void _pager_fill(Pager *p);
static void _pager_empty(Pager *p);
static Pager_Desk *_pager_desk_new(Pager *p, E_Desk *desk, int xpos, int ypos);
static void _pager_desk_free(Pager_Desk *pd);
static Pager_Desk *_pager_desk_at_coord(Pager *p, Evas_Coord x, Evas_Coord y);
static void _pager_desk_select(Pager_Desk *pd);
static Pager_Desk *_pager_desk_find(Pager *p, E_Desk *desk);
static void _pager_desk_switch(Pager_Desk *pd1, Pager_Desk *pd2);
static Pager_Win *_pager_window_new(Pager_Desk *pd, E_Border *border);
static void _pager_window_free(Pager_Win *pw);
static void _pager_window_move(Pager_Win *pw);
static Pager_Win *_pager_window_find(Pager *p, E_Border *border);
static Pager_Win *_pager_desk_window_find(Pager_Desk *pd, E_Border *border);
static Pager_Popup *_pager_popup_new(E_Zone *zone, int urgent);
static void _pager_popup_free(Pager_Popup *pp);
static Pager_Popup *_pager_popup_find(E_Zone *zone);
static E_Config_Dialog *_pager_config_dialog(E_Container *con, const char *params);

static E_Config_DD *conf_edd = NULL;
static Evas_List *pager_popups = NULL;

Config *pager_config = NULL;

static E_Gadcon_Client *
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
{
   Pager *p;
   Evas_Object *o;
   E_Gadcon_Client *gcc;
   Instance *inst;
   Evas_Coord x, y, w, h;
   const char *drop[] = { "enlightenment/pager_win", "enlightenment/border", "enlightenment/vdesktop"};

   inst = E_NEW(Instance, 1);

   p = _pager_new(gc->evas, gc->zone);
   p->inst = inst;
   inst->pager = p;
   o = p->o_table;
   gcc = e_gadcon_client_new(gc, name, id, style, o);
   gcc->data = inst;

   inst->gcc = gcc;
   inst->o_pager = o;

   evas_object_geometry_get(o, &x, &y, &w, &h);
   inst->drop_handler =
     e_drop_handler_add(E_OBJECT(inst->gcc), inst,
			_pager_inst_cb_enter, _pager_inst_cb_move,
			_pager_inst_cb_leave, _pager_inst_cb_drop,
			drop, 3, x, y, w, h);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
				  _pager_cb_obj_moveresize, inst);
   evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
				  _pager_cb_obj_moveresize, inst);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
				  _button_cb_mouse_down, inst);
   pager_config->instances = evas_list_append(pager_config->instances, inst);
   return gcc;
}

static void
_gc_shutdown(E_Gadcon_Client *gcc)
{
   Instance *inst;

   inst = gcc->data;
   pager_config->instances = evas_list_remove(pager_config->instances, inst);
   e_drop_handler_del(inst->drop_handler);
   _pager_free(inst->pager);
   E_FREE(inst);
}

static void
_gc_orient(E_Gadcon_Client *gcc)
{
   Instance *inst;

   inst = gcc->data;
   e_gadcon_client_aspect_set(gcc,
			      inst->pager->xnum * inst->pager->zone->w,
			      inst->pager->ynum * inst->pager->zone->h);
   e_gadcon_client_min_size_set(gcc, 16, 16);
}

static char *
_gc_label(void)
{
   return _("Pager");
}

static Evas_Object *
_gc_icon(Evas *evas)
{
   Evas_Object *o;
   char buf[4096];

   o = edje_object_add(evas);
   snprintf(buf, sizeof(buf), "%s/e-module-pager.edj",
	    e_module_dir_get(pager_config->module));
   edje_object_file_set(o, buf, "icon");
   return o;
}

static const char *
_gc_id_new(void)
{
   return _gadcon_class.name;
}

static Pager *
_pager_new(Evas *evas, E_Zone *zone)
{
   Pager *p;

   p = E_NEW(Pager, 1);
   p->o_table = e_table_add(evas);
   e_table_homogenous_set(p->o_table, 1);
   p->zone = zone;
   _pager_fill(p);
   return p;
}

static void
_pager_free(Pager *p)
{
   _pager_empty(p);
   evas_object_del(p->o_table);
   free(p);
}

static void
_pager_fill(Pager *p)
{
   int x, y;

   e_zone_desk_count_get(p->zone, &(p->xnum), &(p->ynum));
   for (x = 0; x < p->xnum; x++)
     {
	for (y = 0; y < p->ynum; y++)
	  {
	     Pager_Desk *pd;
	     E_Desk     *desk;

	     desk = e_desk_at_xy_get(p->zone, x, y);
	     pd = _pager_desk_new(p, desk, x, y);
	     if (pd)
	       {
		  p->desks = evas_list_append(p->desks, pd);
		  if (desk == e_desk_current_get(desk->zone))
		    _pager_desk_select(pd);
	       }
	  }
     }
}

static void
_pager_empty(Pager *p)
{
   // if (p->popup) _pager_popup_free(p->popup);

   while (p->desks)
     {
	_pager_desk_free(p->desks->data);
	p->desks = evas_list_remove_list(p->desks, p->desks);
     }
}

static Pager_Desk *
_pager_desk_new(Pager *p, E_Desk *desk, int xpos, int ypos)
{
   Pager_Desk    *pd;
   Evas_Object   *o;
   E_Border_List *bl;
   E_Border      *bd;

   pd = E_NEW(Pager_Desk, 1);
   if (!pd) return NULL;

   pd->xpos = xpos;
   pd->ypos = ypos;

   pd->urgent = 0;

   pd->desk = desk;
   e_object_ref(E_OBJECT(desk));
   pd->pager = p;

   o = edje_object_add(evas_object_evas_get(p->o_table));
   pd->o_desk = o;
   e_theme_edje_object_set(o, "base/theme/modules/pager",
			   "e/modules/pager/desk");
   edje_object_part_text_set(o, "label", desk->name);
   e_table_pack(p->o_table, o, xpos, ypos, 1, 1);
   e_table_pack_options_set(o, 1, 1, 1, 1, 0.5, 0.5, 0, 0, -1, -1);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _pager_desk_cb_mouse_down, pd);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _pager_desk_cb_mouse_up, pd);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _pager_desk_cb_mouse_move, pd);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _pager_desk_cb_mouse_wheel, pd);
   evas_object_show(o);

   o = e_layout_add(evas_object_evas_get(p->o_table));
   pd->o_layout = o;

   e_layout_virtual_size_set(o, desk->zone->w, desk->zone->h);
   edje_object_part_swallow(pd->o_desk, "items", pd->o_layout);
   evas_object_show(o);

   bl = e_container_border_list_first(desk->zone->container);
   while ((bd = e_container_border_list_next(bl)))
     {
	Pager_Win   *pw;

	if ((bd->new_client) || ((bd->desk != desk) && (!bd->sticky))) continue;
	pw = _pager_window_new(pd, bd);
	if (pw) pd->wins = evas_list_append(pd->wins, pw);
     }
   e_container_border_list_free(bl);
   return pd;
}

static void
_pager_desk_free(Pager_Desk *pd)
{
   Evas_List *l;

   evas_object_del(pd->o_desk);
   evas_object_del(pd->o_layout);
   for (l = pd->wins; l; l = l->next)
     _pager_window_free(l->data);
   evas_list_free(pd->wins);
   e_object_unref(E_OBJECT(pd->desk));
   free(pd);
}

static Pager_Desk *
_pager_desk_at_coord(Pager *p, Evas_Coord x, Evas_Coord y)
{
   Evas_List *l;

   for (l = p->desks; l; l = l->next)
     {
	Pager_Desk *pd;
	Evas_Coord dx, dy, dw, dh;

	pd = l->data;
	evas_object_geometry_get(pd->o_desk, &dx, &dy, &dw, &dh);
	if (E_INSIDE(x, y, dx, dy, dw, dh)) return pd;
     }
   return NULL;
}

static void
_pager_desk_select(Pager_Desk *pd)
{
   Evas_List *l;

   if (pd->current) return;
   for (l = pd->pager->desks; l; l = l->next)
     {
	Pager_Desk *pd2;

	pd2 = l->data;
	if (pd == pd2)
	  {
	     pd2->current = 1;
	     edje_object_signal_emit(pd2->o_desk, "e,state,selected", "e");
	  }
	else
	  {
	     if (pd2->current)
	       {
		  pd2->current = 0;
		  edje_object_signal_emit(pd2->o_desk, "e,state,unselected", "e");
	       }
	  }
     }
}

static Pager_Desk *
_pager_desk_find(Pager *p, E_Desk *desk)
{
   Evas_List *l;

   for (l = p->desks; l; l = l->next)
     {
	Pager_Desk *pd;

	pd = l->data;
	if (pd->desk == desk) return pd;
     }
   return NULL;
}

static void
_pager_desk_switch(Pager_Desk *pd1, Pager_Desk *pd2)
{
   int c;
   E_Zone     *zone1, *zone2;
   E_Desk     *desk1, *desk2;
   Pager_Win  *pw;
   Evas_List  *l;

   if ((!pd1) || (!pd2) || (!pd1->desk) || (!pd2->desk)) return;
   if (pd1 == pd2) return;

   desk1 = pd1->desk;
   desk2 = pd2->desk;
   zone1 = pd1->desk->zone;
   zone2 = pd2->desk->zone;

   /* Move opened windows from on desk to the other */
   for (l = pd1->wins; l; l = l->next)
     {
	pw = l->data;
	if (!pw || !pw->border || pw->border->iconic) continue;
	e_border_desk_set(pw->border, desk2);
     }
   for (l = pd2->wins; l; l = l->next)
     {
	pw = l->data;
	if (!pw || !pw->border || pw->border->iconic) continue;
	e_border_desk_set(pw->border, desk1);
     }

   /* Modify desktop names in the config */
   for (l = e_config->desktop_names, c = 0; l && c < 2; l = l->next)
     {
	E_Config_Desktop_Name *tmp_dn;

	tmp_dn = l->data;
	if (!tmp_dn) continue;
	if (tmp_dn->desk_x == desk1->x &&
	    tmp_dn->desk_y == desk1->y &&
	    tmp_dn->zone   == desk1->zone->num)
	  {
	     tmp_dn->desk_x = desk2->x;
	     tmp_dn->desk_y = desk2->y;
	     tmp_dn->zone   = desk2->zone->num;
	     c++;
	  }
	else if (tmp_dn->desk_x == desk2->x &&
		 tmp_dn->desk_y == desk2->y &&
		 tmp_dn->zone   == desk2->zone->num)
	  {
	     tmp_dn->desk_x = desk1->x;
	     tmp_dn->desk_y = desk1->y;
	     tmp_dn->zone   = desk1->zone->num;
	     c++;
	  }
     }
   if (c > 0) e_config_save();
   e_desk_name_update();

   /* Modify desktop backgrounds in the config */
   for (l = e_config->desktop_backgrounds, c = 0; l && c < 2; l = l->next)
     {
	E_Config_Desktop_Background *tmp_db;

	tmp_db = l->data;
	if (!tmp_db) continue;
	if (tmp_db->desk_x == desk1->x &&
	    tmp_db->desk_y == desk1->y &&
	    tmp_db->zone   == desk1->zone->num)
	  {
	     tmp_db->desk_x = desk2->x;
	     tmp_db->desk_y = desk2->y;
	     tmp_db->zone   = desk2->zone->num;
	     c++;
	  }
	else if (tmp_db->desk_x == desk2->x &&
		 tmp_db->desk_y == desk2->y &&
		 tmp_db->zone   == desk2->zone->num)
	  {
	     tmp_db->desk_x = desk1->x;
	     tmp_db->desk_y = desk1->y;
	     tmp_db->zone   = desk1->zone->num;
	     c++;
	  }
     }
   if (c > 0) e_config_save();

   /* If the current desktop has been switched, force to update of the screen */
   if (desk2 == e_desk_current_get(zone2))
     {
	desk2->visible = 0;
	e_desk_show(desk2);
     }
   if (desk1 == e_desk_current_get(zone1))
     {
	desk1->visible = 0;
	e_desk_show(desk1);
     }
}

static Pager_Win  *
_pager_window_new(Pager_Desk *pd, E_Border *border)
{
   Pager_Win   *pw;
   Evas_Object *o;
   int          visible;

   if (!border) return NULL;
   pw = E_NEW(Pager_Win, 1);
   if (!pw) return NULL;

   pw->border = border;
   e_object_ref(E_OBJECT(border));

   visible = !border->iconic && !border->client.netwm.state.skip_pager;
   pw->skip_winlist = border->client.netwm.state.skip_pager;
   pw->desk = pd;

   o = edje_object_add(evas_object_evas_get(pd->pager->o_table));
   pw->o_window = o;
   e_theme_edje_object_set(o, "base/theme/modules/pager",
			   "e/modules/pager/window");
   if (visible) evas_object_show(o);

   e_layout_pack(pd->o_layout, pw->o_window);
   e_layout_child_raise(pw->o_window);

   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN,  _pager_window_cb_mouse_in,  pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, _pager_window_cb_mouse_out, pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _pager_window_cb_mouse_down, pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _pager_window_cb_mouse_up, pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _pager_window_cb_mouse_move, pw);

   o = e_border_icon_add(border, evas_object_evas_get(pd->pager->o_table));
   if (o)
     {
	pw->o_icon = o;
	evas_object_show(o);
	edje_object_part_swallow(pw->o_window, "icon", o);
     }

   if (border->client.icccm.urgent)
     {
	if (!(border->iconic))
	  edje_object_signal_emit(pd->o_desk,
				  "e,state,urgent", "e");
	edje_object_signal_emit(pw->o_window,
				"e,state,urgent", "e");
     }

   evas_object_show(o);

   _pager_window_move(pw);
   return pw;
}

static void
_pager_window_free(Pager_Win *pw)
{
   if ((pw->drag.from_pager) && (pw->desk->pager->dragging))
     pw->desk->pager->dragging = 0;
   if (pw->o_window) evas_object_del(pw->o_window);
   if (pw->o_icon) evas_object_del(pw->o_icon);
   e_object_unref(E_OBJECT(pw->border));
   free(pw);
}

static void
_pager_window_move(Pager_Win *pw)
{
   e_layout_child_move(pw->o_window,
		       pw->border->x - pw->desk->desk->zone->x,
		       pw->border->y - pw->desk->desk->zone->y);
   e_layout_child_resize(pw->o_window, pw->border->w, pw->border->h);
}

static Pager_Win *
_pager_window_find(Pager *p, E_Border *border)
{
   Evas_List  *l;

   for (l = p->desks; l; l = l->next)
     {
	Pager_Desk *pd;
	Pager_Win *pw;

	pd = l->data;
	pw = _pager_desk_window_find(pd, border);
	if (pw) return pw;
     }
   return NULL;
}

static Pager_Win *
_pager_desk_window_find(Pager_Desk *pd, E_Border *border)
{
   Evas_List  *l;

   for (l = pd->wins; l; l = l->next)
     {
	Pager_Win  *pw;

	pw = l->data;
	if (pw->border == border) return pw;
     }
   return NULL;
}

static Pager_Popup *
_pager_popup_new(E_Zone *zone, int urgent)
{
   Pager_Popup *pp;
   Evas_Coord w, h;
   int x, y, height, width;
   E_Desk *desk;

   pp = E_NEW(Pager_Popup, 1);
   if (!pp) return NULL;

   /* Show popup */
   pp->popup = e_popup_new(zone, 0, 0, 1, 1);
   if (!pp->popup)
     {
	free(pp);
	return NULL;
     }
   e_popup_layer_set(pp->popup, 255);

   pp->pager = _pager_new(pp->popup->evas, zone);

   pp->pager->is_popup = 1;

   e_zone_desk_count_get(zone, &x, &y);
   height = pager_config->popup_pager_height * y;
   width = ((zone->w * x)/(zone->h * y)) * height;

   evas_object_move(pp->pager->o_table, 0, 0);
   evas_object_resize(pp->pager->o_table, width, height);

   pp->o_bg = edje_object_add(pp->popup->evas);
   e_theme_edje_object_set(pp->o_bg,
			   "base/theme/modules/pager",
			   "e/widgets/pager/popup");
   desk = e_desk_current_get(zone);
   if (desk)
     edje_object_part_text_set(pp->o_bg, "text", desk->name);
   evas_object_show(pp->o_bg);

   edje_extern_object_min_size_set(pp->pager->o_table, width, height);
   edje_object_part_swallow(pp->o_bg, "pager", pp->pager->o_table);
   edje_object_size_min_calc(pp->o_bg, &w, &h);

   evas_object_move(pp->o_bg, 0, 0);
   evas_object_resize(pp->o_bg, w, h);
   e_popup_edje_bg_object_set(pp->popup, pp->o_bg);
   //e_popup_ignore_events_set(pp->popup, 1);
   e_popup_move_resize(pp->popup, ((zone->w - w) / 2),
		       ((zone->h - h) / 2), w, h);
   e_bindings_mouse_grab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_bindings_wheel_grab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_popup_show(pp->popup);

   if (!urgent)
     {
	pp->timer = ecore_timer_add(pager_config->popup_speed,
				    _pager_popup_cb_timeout, pp);
     }
   else
     {
	if (!pager_config->popup_urgent_stick)
	  pp->timer = ecore_timer_add(pager_config->popup_urgent_speed,
				      _pager_popup_cb_timeout, pp);
     }
   pp->urgent = urgent;

   pager_popups = evas_list_append(pager_popups, pp);

   return pp;
}

static void
_pager_popup_free(Pager_Popup *pp)
{
   if (pp->timer) ecore_timer_del(pp->timer);
   evas_object_del(pp->o_bg);
   _pager_free(pp->pager);
   e_bindings_mouse_ungrab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_bindings_wheel_ungrab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_object_del(E_OBJECT(pp->popup));
   pager_popups = evas_list_remove(pager_popups, pp);
   free(pp);
}

static Pager_Popup *
_pager_popup_find(E_Zone *zone)
{
   Pager_Popup *pp;
   Evas_List *l;

   for(l = pager_popups; l; l = l->next)
     {
	pp = l->data;
	pp->pager->zone == zone;
	return pp;
     }
   return NULL;
}

static void
_pager_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   Instance *inst;

   inst = data;
   _pager_instance_drop_zone_recalc(inst);
}

static void
_button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   Instance *inst;
   Evas_Event_Mouse_Down *ev;

   inst = data;
   ev = event_info;
   if ((ev->button == 3) && (!pager_config->menu))
     {
	E_Menu *mn;
	E_Menu_Item *mi;
	int cx, cy, cw, ch;

	mn = e_menu_new();
	e_menu_post_deactivate_callback_set(mn, _menu_cb_post, inst);
	pager_config->menu = mn;

	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, _pager_inst_cb_menu_configure, NULL);

	if (e_configure_registry_exists("screen/virtual_desktops"))
	  {
	     mi = e_menu_item_new(mn);
	     e_menu_item_label_set(mi, _("Virtual Desktops Configuration"));
	     e_util_menu_item_edje_icon_set(mi, "enlightenment/vdesktops");
	     e_menu_item_callback_set(mi, _pager_inst_cb_menu_virtual_desktops_dialog, inst);
	  }

	e_gadcon_client_util_menu_items_append(inst->gcc, mn, 0);

	e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
	e_menu_activate_mouse(mn,
			      e_util_zone_current_get(e_manager_current_get()),
			      cx + ev->output.x, cy + ev->output.y, 1, 1,
			      E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
	e_util_evas_fake_mouse_up_later(inst->gcc->gadcon->evas, ev->button);
     }
}

static void
_menu_cb_post(void *data, E_Menu *m)
{
   if (!pager_config->menu) return;
   e_object_del(E_OBJECT(pager_config->menu));
   pager_config->menu = NULL;
}

static void
_pager_inst_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi)
{
   if (!pager_config) return;
   if (pager_config->config_dialog) return;
   /* FIXME: pass zone config item */
   _config_pager_module(NULL);
}

static E_Config_Dialog *
_pager_config_dialog(E_Container *con, const char *params)
{
   if (!pager_config) return;
   if (pager_config->config_dialog) return;
   /* FIXME: pass zone config item */
   _config_pager_module(NULL);  
   return pager_config->config_dialog;
}

static void
_pager_inst_cb_menu_virtual_desktops_dialog(void *data, E_Menu *m, E_Menu_Item *mi)
{
   Instance *inst;

   inst = data;
   e_configure_registry_call("screen/virtual_desktops", inst->gcc->gadcon->zone->container, NULL);
}<commit_msg>Fix check for correct pager popup. Add return values.<commit_after>/*
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */

#include "e.h"
#include "e_mod_main.h"

/* gadcon requirements */
static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
static void _gc_shutdown(E_Gadcon_Client *gcc);
static void _gc_orient(E_Gadcon_Client *gcc);
static char *_gc_label(void);
static Evas_Object *_gc_icon(Evas *evas);
static const char *_gc_id_new(void);
/* and actually define the gadcon class that this module provides (just 1) */
static const E_Gadcon_Client_Class _gadcon_class =
{
   GADCON_CLIENT_CLASS_VERSION,
     "pager",
     {
	_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL
     },
   E_GADCON_CLIENT_STYLE_INSET
};

/* actual module specifics */
typedef struct _Instance Instance;
typedef struct _Pager       Pager;
typedef struct _Pager_Desk  Pager_Desk;
typedef struct _Pager_Win   Pager_Win;
typedef struct _Pager_Popup Pager_Popup;

struct _Instance
{
   E_Gadcon_Client *gcc;
   Evas_Object     *o_pager; /* table */
   Pager           *pager;
   E_Drop_Handler  *drop_handler;
};

struct _Pager
{
   Instance     *inst;
   unsigned char is_popup : 1;
   Evas_Object  *o_table;
   E_Zone       *zone;
   int           xnum, ynum;
   Evas_List    *desks;
   unsigned char dragging : 1;
   unsigned char just_dragged : 1;
   Evas_Coord    dnd_x, dnd_y;
   Pager_Desk   *active_drop_pd;
};

struct _Pager_Desk
{
   Pager           *pager;
   E_Desk          *desk;
   Evas_List       *wins;
   Evas_Object     *o_desk;
   Evas_Object     *o_layout;
   int              xpos, ypos;
   int              current : 1;
   int              urgent;
   struct {
      Pager         *from_pager;
      unsigned char  in_pager : 1;
      unsigned char  start : 1;
      int            x, y;
      int            dx, dy;
      int            button;
   } drag;
};

struct _Pager_Win
{
   E_Border     *border;
   Pager_Desk   *desk;
   Evas_Object  *o_window;
   Evas_Object  *o_icon;
   unsigned char skip_winlist : 1;
   struct {
      Pager         *from_pager;
      unsigned char  start : 1;
      unsigned char  in_pager : 1;
      unsigned char  no_place : 1;
      unsigned char  desktop  : 1;
      int            x, y;
      int            dx, dy;
      int            button;
   } drag;
};

struct _Pager_Popup
{
   E_Popup      *popup;
   Pager        *pager;
   Evas_Object  *o_bg;
   Ecore_Timer  *timer;
   unsigned char urgent : 1;
};

static void _pager_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _menu_cb_post(void *data, E_Menu *m);
static void _pager_inst_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi);
static void _pager_inst_cb_menu_virtual_desktops_dialog(void *data, E_Menu *m, E_Menu_Item *mi);
static void _pager_instance_drop_zone_recalc(Instance *inst);
static int _pager_cb_event_border_resize(void *data, int type, void *event);
static int _pager_cb_event_border_move(void *data, int type, void *event);
static int _pager_cb_event_border_add(void *data, int type, void *event);
static int _pager_cb_event_border_remove(void *data, int type, void *event);
static int _pager_cb_event_border_iconify(void *data, int type, void *event);
static int _pager_cb_event_border_uniconify(void *data, int type, void *event);
static int _pager_cb_event_border_stick(void *data, int type, void *event);
static int _pager_cb_event_border_unstick(void *data, int type, void *event);
static int _pager_cb_event_border_desk_set(void *data, int type, void *event);
static int _pager_cb_event_border_stack(void *data, int type, void *event);
static int _pager_cb_event_border_icon_change(void *data, int type, void *event);
static int _pager_cb_event_border_urgent_change(void *data, int type, void *event);
static int _pager_cb_event_border_property(void *data, int type, void *event);
static int _pager_cb_event_zone_desk_count_set(void *data, int type, void *event);
static int _pager_cb_event_desk_show(void *data, int type, void *event);
static int _pager_cb_event_desk_name_change(void *data, int type, void *event);
static int _pager_cb_event_container_resize(void *data, int type, void *event);
static void _pager_window_cb_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_window_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void *_pager_window_cb_drag_convert(E_Drag *drag, const char *type);
static void _pager_window_cb_drag_finished(E_Drag *drag, int dropped);
static void _pager_inst_cb_enter(void *data, const char *type, void *event_info);
static void _pager_inst_cb_move(void *data, const char *type, void *event_info);
static void _pager_inst_cb_leave(void *data, const char *type, void *event_info);
static void _pager_inst_cb_drop(void *data, const char *type, void *event_info);
static void _pager_inst_cb_scroll(void *data);
static void _pager_update_drop_position(Instance *inst, Evas_Coord x, Evas_Coord y);
static void _pager_desk_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_desk_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_desk_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _pager_desk_cb_drag_finished(E_Drag *drag, int dropped);
static void _pager_desk_cb_mouse_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info);
static int _pager_popup_cb_timeout(void *data);
static Pager *_pager_new(Evas *evas, E_Zone *zone);
static void _pager_free(Pager *p);
static void _pager_fill(Pager *p);
static void _pager_empty(Pager *p);
static Pager_Desk *_pager_desk_new(Pager *p, E_Desk *desk, int xpos, int ypos);
static void _pager_desk_free(Pager_Desk *pd);
static Pager_Desk *_pager_desk_at_coord(Pager *p, Evas_Coord x, Evas_Coord y);
static void _pager_desk_select(Pager_Desk *pd);
static Pager_Desk *_pager_desk_find(Pager *p, E_Desk *desk);
static void _pager_desk_switch(Pager_Desk *pd1, Pager_Desk *pd2);
static Pager_Win *_pager_window_new(Pager_Desk *pd, E_Border *border);
static void _pager_window_free(Pager_Win *pw);
static void _pager_window_move(Pager_Win *pw);
static Pager_Win *_pager_window_find(Pager *p, E_Border *border);
static Pager_Win *_pager_desk_window_find(Pager_Desk *pd, E_Border *border);
static Pager_Popup *_pager_popup_new(E_Zone *zone, int urgent);
static void _pager_popup_free(Pager_Popup *pp);
static Pager_Popup *_pager_popup_find(E_Zone *zone);
static E_Config_Dialog *_pager_config_dialog(E_Container *con, const char *params);

static E_Config_DD *conf_edd = NULL;
static Evas_List *pager_popups = NULL;

Config *pager_config = NULL;

static E_Gadcon_Client *
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
{
   Pager *p;
   Evas_Object *o;
   E_Gadcon_Client *gcc;
   Instance *inst;
   Evas_Coord x, y, w, h;
   const char *drop[] = { "enlightenment/pager_win", "enlightenment/border", "enlightenment/vdesktop"};

   inst = E_NEW(Instance, 1);

   p = _pager_new(gc->evas, gc->zone);
   p->inst = inst;
   inst->pager = p;
   o = p->o_table;
   gcc = e_gadcon_client_new(gc, name, id, style, o);
   gcc->data = inst;

   inst->gcc = gcc;
   inst->o_pager = o;

   evas_object_geometry_get(o, &x, &y, &w, &h);
   inst->drop_handler =
     e_drop_handler_add(E_OBJECT(inst->gcc), inst,
			_pager_inst_cb_enter, _pager_inst_cb_move,
			_pager_inst_cb_leave, _pager_inst_cb_drop,
			drop, 3, x, y, w, h);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
				  _pager_cb_obj_moveresize, inst);
   evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
				  _pager_cb_obj_moveresize, inst);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
				  _button_cb_mouse_down, inst);
   pager_config->instances = evas_list_append(pager_config->instances, inst);
   return gcc;
}

static void
_gc_shutdown(E_Gadcon_Client *gcc)
{
   Instance *inst;

   inst = gcc->data;
   pager_config->instances = evas_list_remove(pager_config->instances, inst);
   e_drop_handler_del(inst->drop_handler);
   _pager_free(inst->pager);
   E_FREE(inst);
}

static void
_gc_orient(E_Gadcon_Client *gcc)
{
   Instance *inst;

   inst = gcc->data;
   e_gadcon_client_aspect_set(gcc,
			      inst->pager->xnum * inst->pager->zone->w,
			      inst->pager->ynum * inst->pager->zone->h);
   e_gadcon_client_min_size_set(gcc, 16, 16);
}

static char *
_gc_label(void)
{
   return _("Pager");
}

static Evas_Object *
_gc_icon(Evas *evas)
{
   Evas_Object *o;
   char buf[4096];

   o = edje_object_add(evas);
   snprintf(buf, sizeof(buf), "%s/e-module-pager.edj",
	    e_module_dir_get(pager_config->module));
   edje_object_file_set(o, buf, "icon");
   return o;
}

static const char *
_gc_id_new(void)
{
   return _gadcon_class.name;
}

static Pager *
_pager_new(Evas *evas, E_Zone *zone)
{
   Pager *p;

   p = E_NEW(Pager, 1);
   p->o_table = e_table_add(evas);
   e_table_homogenous_set(p->o_table, 1);
   p->zone = zone;
   _pager_fill(p);
   return p;
}

static void
_pager_free(Pager *p)
{
   _pager_empty(p);
   evas_object_del(p->o_table);
   free(p);
}

static void
_pager_fill(Pager *p)
{
   int x, y;

   e_zone_desk_count_get(p->zone, &(p->xnum), &(p->ynum));
   for (x = 0; x < p->xnum; x++)
     {
	for (y = 0; y < p->ynum; y++)
	  {
	     Pager_Desk *pd;
	     E_Desk     *desk;

	     desk = e_desk_at_xy_get(p->zone, x, y);
	     pd = _pager_desk_new(p, desk, x, y);
	     if (pd)
	       {
		  p->desks = evas_list_append(p->desks, pd);
		  if (desk == e_desk_current_get(desk->zone))
		    _pager_desk_select(pd);
	       }
	  }
     }
}

static void
_pager_empty(Pager *p)
{
   // if (p->popup) _pager_popup_free(p->popup);

   while (p->desks)
     {
	_pager_desk_free(p->desks->data);
	p->desks = evas_list_remove_list(p->desks, p->desks);
     }
}

static Pager_Desk *
_pager_desk_new(Pager *p, E_Desk *desk, int xpos, int ypos)
{
   Pager_Desk    *pd;
   Evas_Object   *o;
   E_Border_List *bl;
   E_Border      *bd;

   pd = E_NEW(Pager_Desk, 1);
   if (!pd) return NULL;

   pd->xpos = xpos;
   pd->ypos = ypos;

   pd->urgent = 0;

   pd->desk = desk;
   e_object_ref(E_OBJECT(desk));
   pd->pager = p;

   o = edje_object_add(evas_object_evas_get(p->o_table));
   pd->o_desk = o;
   e_theme_edje_object_set(o, "base/theme/modules/pager",
			   "e/modules/pager/desk");
   edje_object_part_text_set(o, "label", desk->name);
   e_table_pack(p->o_table, o, xpos, ypos, 1, 1);
   e_table_pack_options_set(o, 1, 1, 1, 1, 0.5, 0.5, 0, 0, -1, -1);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _pager_desk_cb_mouse_down, pd);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _pager_desk_cb_mouse_up, pd);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _pager_desk_cb_mouse_move, pd);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _pager_desk_cb_mouse_wheel, pd);
   evas_object_show(o);

   o = e_layout_add(evas_object_evas_get(p->o_table));
   pd->o_layout = o;

   e_layout_virtual_size_set(o, desk->zone->w, desk->zone->h);
   edje_object_part_swallow(pd->o_desk, "items", pd->o_layout);
   evas_object_show(o);

   bl = e_container_border_list_first(desk->zone->container);
   while ((bd = e_container_border_list_next(bl)))
     {
	Pager_Win   *pw;

	if ((bd->new_client) || ((bd->desk != desk) && (!bd->sticky))) continue;
	pw = _pager_window_new(pd, bd);
	if (pw) pd->wins = evas_list_append(pd->wins, pw);
     }
   e_container_border_list_free(bl);
   return pd;
}

static void
_pager_desk_free(Pager_Desk *pd)
{
   Evas_List *l;

   evas_object_del(pd->o_desk);
   evas_object_del(pd->o_layout);
   for (l = pd->wins; l; l = l->next)
     _pager_window_free(l->data);
   evas_list_free(pd->wins);
   e_object_unref(E_OBJECT(pd->desk));
   free(pd);
}

static Pager_Desk *
_pager_desk_at_coord(Pager *p, Evas_Coord x, Evas_Coord y)
{
   Evas_List *l;

   for (l = p->desks; l; l = l->next)
     {
	Pager_Desk *pd;
	Evas_Coord dx, dy, dw, dh;

	pd = l->data;
	evas_object_geometry_get(pd->o_desk, &dx, &dy, &dw, &dh);
	if (E_INSIDE(x, y, dx, dy, dw, dh)) return pd;
     }
   return NULL;
}

static void
_pager_desk_select(Pager_Desk *pd)
{
   Evas_List *l;

   if (pd->current) return;
   for (l = pd->pager->desks; l; l = l->next)
     {
	Pager_Desk *pd2;

	pd2 = l->data;
	if (pd == pd2)
	  {
	     pd2->current = 1;
	     edje_object_signal_emit(pd2->o_desk, "e,state,selected", "e");
	  }
	else
	  {
	     if (pd2->current)
	       {
		  pd2->current = 0;
		  edje_object_signal_emit(pd2->o_desk, "e,state,unselected", "e");
	       }
	  }
     }
}

static Pager_Desk *
_pager_desk_find(Pager *p, E_Desk *desk)
{
   Evas_List *l;

   for (l = p->desks; l; l = l->next)
     {
	Pager_Desk *pd;

	pd = l->data;
	if (pd->desk == desk) return pd;
     }
   return NULL;
}

static void
_pager_desk_switch(Pager_Desk *pd1, Pager_Desk *pd2)
{
   int c;
   E_Zone     *zone1, *zone2;
   E_Desk     *desk1, *desk2;
   Pager_Win  *pw;
   Evas_List  *l;

   if ((!pd1) || (!pd2) || (!pd1->desk) || (!pd2->desk)) return;
   if (pd1 == pd2) return;

   desk1 = pd1->desk;
   desk2 = pd2->desk;
   zone1 = pd1->desk->zone;
   zone2 = pd2->desk->zone;

   /* Move opened windows from on desk to the other */
   for (l = pd1->wins; l; l = l->next)
     {
	pw = l->data;
	if (!pw || !pw->border || pw->border->iconic) continue;
	e_border_desk_set(pw->border, desk2);
     }
   for (l = pd2->wins; l; l = l->next)
     {
	pw = l->data;
	if (!pw || !pw->border || pw->border->iconic) continue;
	e_border_desk_set(pw->border, desk1);
     }

   /* Modify desktop names in the config */
   for (l = e_config->desktop_names, c = 0; l && c < 2; l = l->next)
     {
	E_Config_Desktop_Name *tmp_dn;

	tmp_dn = l->data;
	if (!tmp_dn) continue;
	if (tmp_dn->desk_x == desk1->x &&
	    tmp_dn->desk_y == desk1->y &&
	    tmp_dn->zone   == desk1->zone->num)
	  {
	     tmp_dn->desk_x = desk2->x;
	     tmp_dn->desk_y = desk2->y;
	     tmp_dn->zone   = desk2->zone->num;
	     c++;
	  }
	else if (tmp_dn->desk_x == desk2->x &&
		 tmp_dn->desk_y == desk2->y &&
		 tmp_dn->zone   == desk2->zone->num)
	  {
	     tmp_dn->desk_x = desk1->x;
	     tmp_dn->desk_y = desk1->y;
	     tmp_dn->zone   = desk1->zone->num;
	     c++;
	  }
     }
   if (c > 0) e_config_save();
   e_desk_name_update();

   /* Modify desktop backgrounds in the config */
   for (l = e_config->desktop_backgrounds, c = 0; l && c < 2; l = l->next)
     {
	E_Config_Desktop_Background *tmp_db;

	tmp_db = l->data;
	if (!tmp_db) continue;
	if (tmp_db->desk_x == desk1->x &&
	    tmp_db->desk_y == desk1->y &&
	    tmp_db->zone   == desk1->zone->num)
	  {
	     tmp_db->desk_x = desk2->x;
	     tmp_db->desk_y = desk2->y;
	     tmp_db->zone   = desk2->zone->num;
	     c++;
	  }
	else if (tmp_db->desk_x == desk2->x &&
		 tmp_db->desk_y == desk2->y &&
		 tmp_db->zone   == desk2->zone->num)
	  {
	     tmp_db->desk_x = desk1->x;
	     tmp_db->desk_y = desk1->y;
	     tmp_db->zone   = desk1->zone->num;
	     c++;
	  }
     }
   if (c > 0) e_config_save();

   /* If the current desktop has been switched, force to update of the screen */
   if (desk2 == e_desk_current_get(zone2))
     {
	desk2->visible = 0;
	e_desk_show(desk2);
     }
   if (desk1 == e_desk_current_get(zone1))
     {
	desk1->visible = 0;
	e_desk_show(desk1);
     }
}

static Pager_Win  *
_pager_window_new(Pager_Desk *pd, E_Border *border)
{
   Pager_Win   *pw;
   Evas_Object *o;
   int          visible;

   if (!border) return NULL;
   pw = E_NEW(Pager_Win, 1);
   if (!pw) return NULL;

   pw->border = border;
   e_object_ref(E_OBJECT(border));

   visible = !border->iconic && !border->client.netwm.state.skip_pager;
   pw->skip_winlist = border->client.netwm.state.skip_pager;
   pw->desk = pd;

   o = edje_object_add(evas_object_evas_get(pd->pager->o_table));
   pw->o_window = o;
   e_theme_edje_object_set(o, "base/theme/modules/pager",
			   "e/modules/pager/window");
   if (visible) evas_object_show(o);

   e_layout_pack(pd->o_layout, pw->o_window);
   e_layout_child_raise(pw->o_window);

   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN,  _pager_window_cb_mouse_in,  pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, _pager_window_cb_mouse_out, pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _pager_window_cb_mouse_down, pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _pager_window_cb_mouse_up, pw);
   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _pager_window_cb_mouse_move, pw);

   o = e_border_icon_add(border, evas_object_evas_get(pd->pager->o_table));
   if (o)
     {
	pw->o_icon = o;
	evas_object_show(o);
	edje_object_part_swallow(pw->o_window, "icon", o);
     }

   if (border->client.icccm.urgent)
     {
	if (!(border->iconic))
	  edje_object_signal_emit(pd->o_desk,
				  "e,state,urgent", "e");
	edje_object_signal_emit(pw->o_window,
				"e,state,urgent", "e");
     }

   evas_object_show(o);

   _pager_window_move(pw);
   return pw;
}

static void
_pager_window_free(Pager_Win *pw)
{
   if ((pw->drag.from_pager) && (pw->desk->pager->dragging))
     pw->desk->pager->dragging = 0;
   if (pw->o_window) evas_object_del(pw->o_window);
   if (pw->o_icon) evas_object_del(pw->o_icon);
   e_object_unref(E_OBJECT(pw->border));
   free(pw);
}

static void
_pager_window_move(Pager_Win *pw)
{
   e_layout_child_move(pw->o_window,
		       pw->border->x - pw->desk->desk->zone->x,
		       pw->border->y - pw->desk->desk->zone->y);
   e_layout_child_resize(pw->o_window, pw->border->w, pw->border->h);
}

static Pager_Win *
_pager_window_find(Pager *p, E_Border *border)
{
   Evas_List  *l;

   for (l = p->desks; l; l = l->next)
     {
	Pager_Desk *pd;
	Pager_Win *pw;

	pd = l->data;
	pw = _pager_desk_window_find(pd, border);
	if (pw) return pw;
     }
   return NULL;
}

static Pager_Win *
_pager_desk_window_find(Pager_Desk *pd, E_Border *border)
{
   Evas_List  *l;

   for (l = pd->wins; l; l = l->next)
     {
	Pager_Win  *pw;

	pw = l->data;
	if (pw->border == border) return pw;
     }
   return NULL;
}

static Pager_Popup *
_pager_popup_new(E_Zone *zone, int urgent)
{
   Pager_Popup *pp;
   Evas_Coord w, h;
   int x, y, height, width;
   E_Desk *desk;

   pp = E_NEW(Pager_Popup, 1);
   if (!pp) return NULL;

   /* Show popup */
   pp->popup = e_popup_new(zone, 0, 0, 1, 1);
   if (!pp->popup)
     {
	free(pp);
	return NULL;
     }
   e_popup_layer_set(pp->popup, 255);

   pp->pager = _pager_new(pp->popup->evas, zone);

   pp->pager->is_popup = 1;

   e_zone_desk_count_get(zone, &x, &y);
   height = pager_config->popup_pager_height * y;
   width = ((zone->w * x)/(zone->h * y)) * height;

   evas_object_move(pp->pager->o_table, 0, 0);
   evas_object_resize(pp->pager->o_table, width, height);

   pp->o_bg = edje_object_add(pp->popup->evas);
   e_theme_edje_object_set(pp->o_bg,
			   "base/theme/modules/pager",
			   "e/widgets/pager/popup");
   desk = e_desk_current_get(zone);
   if (desk)
     edje_object_part_text_set(pp->o_bg, "text", desk->name);
   evas_object_show(pp->o_bg);

   edje_extern_object_min_size_set(pp->pager->o_table, width, height);
   edje_object_part_swallow(pp->o_bg, "pager", pp->pager->o_table);
   edje_object_size_min_calc(pp->o_bg, &w, &h);

   evas_object_move(pp->o_bg, 0, 0);
   evas_object_resize(pp->o_bg, w, h);
   e_popup_edje_bg_object_set(pp->popup, pp->o_bg);
   //e_popup_ignore_events_set(pp->popup, 1);
   e_popup_move_resize(pp->popup, ((zone->w - w) / 2),
		       ((zone->h - h) / 2), w, h);
   e_bindings_mouse_grab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_bindings_wheel_grab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_popup_show(pp->popup);

   if (!urgent)
     {
	pp->timer = ecore_timer_add(pager_config->popup_speed,
				    _pager_popup_cb_timeout, pp);
     }
   else
     {
	if (!pager_config->popup_urgent_stick)
	  pp->timer = ecore_timer_add(pager_config->popup_urgent_speed,
				      _pager_popup_cb_timeout, pp);
     }
   pp->urgent = urgent;

   pager_popups = evas_list_append(pager_popups, pp);

   return pp;
}

static void
_pager_popup_free(Pager_Popup *pp)
{
   if (pp->timer) ecore_timer_del(pp->timer);
   evas_object_del(pp->o_bg);
   _pager_free(pp->pager);
   e_bindings_mouse_ungrab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_bindings_wheel_ungrab(E_BINDING_CONTEXT_POPUP, pp->popup->evas_win);
   e_object_del(E_OBJECT(pp->popup));
   pager_popups = evas_list_remove(pager_popups, pp);
   free(pp);
}

static Pager_Popup *
_pager_popup_find(E_Zone *zone)
{
   Pager_Popup *pp;
   Evas_List *l;

   for (l = pager_popups; l; l = l->next)
     {
	pp = l->data;
	if (pp->pager->zone == zone)
	  return pp;
     }
   return NULL;
}

static void
_pager_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   Instance *inst;

   inst = data;
   _pager_instance_drop_zone_recalc(inst);
}

static void
_button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   Instance *inst;
   Evas_Event_Mouse_Down *ev;

   inst = data;
   ev = event_info;
   if ((ev->button == 3) && (!pager_config->menu))
     {
	E_Menu *mn;
	E_Menu_Item *mi;
	int cx, cy, cw, ch;

	mn = e_menu_new();
	e_menu_post_deactivate_callback_set(mn, _menu_cb_post, inst);
	pager_config->menu = mn;

	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, _pager_inst_cb_menu_configure, NULL);

	if (e_configure_registry_exists("screen/virtual_desktops"))
	  {
	     mi = e_menu_item_new(mn);
	     e_menu_item_label_set(mi, _("Virtual Desktops Configuration"));
	     e_util_menu_item_edje_icon_set(mi, "enlightenment/vdesktops");
	     e_menu_item_callback_set(mi, _pager_inst_cb_menu_virtual_desktops_dialog, inst);
	  }

	e_gadcon_client_util_menu_items_append(inst->gcc, mn, 0);

	e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
	e_menu_activate_mouse(mn,
			      e_util_zone_current_get(e_manager_current_get()),
			      cx + ev->output.x, cy + ev->output.y, 1, 1,
			      E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
	e_util_evas_fake_mouse_up_later(inst->gcc->gadcon->evas, ev->button);
     }
}

static void
_menu_cb_post(void *data, E_Menu *m)
{
   if (!pager_config->menu) return;
   e_object_del(E_OBJECT(pager_config->menu));
   pager_config->menu = NULL;
}

static void
_pager_inst_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi)
{
   if (!pager_config) return;
   if (pager_config->config_dialog) return;
   /* FIXME: pass zone config item */
   _config_pager_module(NULL);
}

static E_Config_Dialog *
_pager_config_dialog(E_Container *con, const char *params)
{
   if (!pager_config) return NULL;
   if (pager_config->config_dialog) return NULL;
   /* FIXME: pass zone config item */
   _config_pager_module(NULL);  
   return pager_config->config_dialog;
}

static void
_pager_inst_cb_menu_virtual_desktops_dialog(void *data, E_Menu *m, E_Menu_Item *mi)
{
   Instance *inst;

   inst = data;
   e_configure_registry_call("screen/virtual_desktops", inst->gcc->gadcon->zone->container, NULL);
}
{'fraction_non_alphanumeric': 0.13327542740927484, 'fraction_numerical': 0.006313158061987585, 'mean_word_length': 3.9309516348062257, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 659, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7462636', 'n_tokens_mistral': 20347, 'n_tokens_neox': 19685, 'n_words': 3750}