work on contact.

SVN revision: 83822
This commit is contained in:
Carsten Haitzler 2013-02-11 12:26:30 +00:00
parent 08dbfd4c7f
commit c75b38a9d9
7 changed files with 596 additions and 1 deletions

View File

@ -9,7 +9,11 @@ contactpkgdir = $(MDIR)/contact/$(MODULE_ARCH)
contactpkg_LTLIBRARIES = contact/module.la
contact_module_la_SOURCES = contact/e_mod_main.c \
contact/e_mod_main.h
contact/e_mod_main.h \
contact/e_policy.c \
contact/e_policy.h \
contact/e_edges.c \
contact/e_edges.h
# TODO: incomplete
.PHONY: contact install-contact

View File

@ -0,0 +1,250 @@
#include "e_mod_main.h"
typedef struct _Edgeset Edgeset;
typedef struct _Edgehandler Edgehandler;
struct _Edgeset
{
E_Zone *zone;
struct {
Evas_Object *obj;
} l, r, t, b;
struct {
int button, x, y;
Eina_Bool recognized : 1;
} down;
};
struct _Edgehandler
{
E_Edges_Event event;
void (*func) (void *data, int d, double v);
void *data;
};
static Edgehandler *_handler_find(E_Edges_Event event);
static Evas_Object *_input_obj(Edgeset *es, int x, int y, int w, int h);
static Edgeset *_edgeset_new(E_Zone *zone);
static void _edgeset_free(Edgeset *es);
static void _cb_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event);
static void _cb_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event);
static void _cb_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event);
static Eina_List *edges = NULL;
static Eina_List *handlers = NULL;
void
e_edges_init(void)
{
Eina_List *l, *ll, *lll;
E_Manager *man;
E_Container *con;
E_Zone *zone;
EINA_LIST_FOREACH(e_manager_list(), l, man)
{
EINA_LIST_FOREACH(man->containers, ll, con)
{
EINA_LIST_FOREACH(con->zones, lll, zone)
{
Edgeset *es = _edgeset_new(zone);
if (es) edges = eina_list_append(edges, es);
}
}
}
}
void
e_edges_shutdown(void)
{
Edgeset *es;
Edgehandler *eh;
EINA_LIST_FREE(edges, es) _edgeset_free(es);
EINA_LIST_FREE(handlers, eh) free(eh);
}
void
e_edges_handler_set(E_Edges_Event event, void (*func) (void *data, int d, double v), void *data)
{
Edgehandler *eh;
eh = _handler_find(event);
if (!eh)
{
eh = calloc(1, sizeof(*eh));
if (!eh) return;
handlers = eina_list_append(handlers, eh);
}
eh->event = event;
eh->func = func;
eh->data = data;
}
static Edgehandler *
_handler_find(E_Edges_Event event)
{
Eina_List *l;
Edgehandler *eh;
EINA_LIST_FOREACH(handlers, l, eh)
{
if (eh->event == event)
{
handlers = eina_list_promote_list(handlers, l);
return eh;
}
}
return NULL;
}
static void
_handler_call(E_Edges_Event event, int d, double v)
{
Edgehandler *eh = _handler_find(event);
if (!eh) return;
if (!eh->func) return;
eh->func(eh->data, d, v);
}
static Evas_Object *
_input_obj(Edgeset *es, int x, int y, int w, int h)
{
E_Comp *c = es->zone->container->manager->comp;
Evas_Object *o = evas_object_rectangle_add(c->evas);
evas_object_color_set(o, 0, 0, 0, 0);
evas_object_move(o, x, y);
evas_object_resize(o, w, h);
evas_object_layer_set(o, 999);
evas_object_show(o);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _cb_down, es);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _cb_up, es);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _cb_move, es);
return o;
}
static Edgeset *
_edgeset_new(E_Zone *zone)
{
Edgeset *es = calloc(1, sizeof(*es));
if (!es) return NULL;
es->zone = zone;
es->t.obj = _input_obj(es, zone->x, zone->y, zone->w, 8);
es->b.obj = _input_obj(es, zone->x, zone->y + zone->h - 8, zone->w, 8);
es->l.obj = _input_obj(es, zone->x, zone->y, 8, zone->h);
es->r.obj = _input_obj(es, zone->x + zone->w - 8, zone->y, 8, zone->h);
return es;
}
static void
_edgeset_free(Edgeset *es)
{
evas_object_del(es->t.obj);
evas_object_del(es->b.obj);
evas_object_del(es->l.obj);
evas_object_del(es->r.obj);
free(es);
}
static void
_cb_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
{
Edgeset *es = data;
Evas_Event_Mouse_Down *ev = event;
if (ev->button != 1) return;
es->down.button = ev->button;
es->down.x = ev->canvas.x;
es->down.y = ev->canvas.y;
es->down.recognized = EINA_FALSE;
}
static void
_cb_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
{
Edgeset *es = data;
Evas_Event_Mouse_Up *ev = event;
if (ev->button != 1) return;
es->down.button = 0;
}
static void
_cb_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event)
{
Edgeset *es = data;
Evas_Event_Mouse_Move *ev = event;
int dx, dy, d;
double v;
if (!es->down.button) return;
dx = ev->cur.canvas.x - es->down.x;
dy = ev->cur.canvas.y - es->down.y;
d = 40;
if (obj == es->l.obj)
{
if ((!es->down.recognized) && (dx > d) && (abs(dy) < d))
{
es->down.recognized = EINA_TRUE;
_handler_call(E_EDGES_LEFT_IN_BEGIN, 0, 0);
}
if (es->down.recognized)
{
d = (dx - d);
if (d < 0) d = 0;
if (es->zone->w > 1) v = (double)d / (es->zone->w / 2);
else v = 1.0;
_handler_call(E_EDGES_LEFT_IN_SLIDE, d, v);
}
}
else if (obj == es->r.obj)
{
if ((!es->down.recognized) && (-dx > d) && (abs(dy) < d))
{
es->down.recognized = EINA_TRUE;
_handler_call(E_EDGES_RIGHT_IN_BEGIN, 0, 0);
}
if (es->down.recognized)
{
d = (-dx - d);
if (d < 0) d = 0;
if (es->zone->w > 1) v = (double)d / (es->zone->w / 2);
else v = 1.0;
_handler_call(E_EDGES_RIGHT_IN_SLIDE, d, v);
}
}
else if (obj == es->t.obj)
{
if ((!es->down.recognized) && (dy > d) && (abs(dx) < d))
{
es->down.recognized = EINA_TRUE;
_handler_call(E_EDGES_TOP_IN_BEGIN, 0, 0);
}
if (es->down.recognized)
{
d = (dy - d);
if (d < 0) d = 0;
if (es->zone->h > 1) v = (double)d / (es->zone->h / 2);
else v = 1.0;
_handler_call(E_EDGES_TOP_IN_SLIDE, d, v);
}
}
else if (obj == es->b.obj)
{
if ((!es->down.recognized) && (-dy > d) && (abs(dx) < d))
{
es->down.recognized = EINA_TRUE;
_handler_call(E_EDGES_BOTTOM_IN_BEGIN, 0, 0);
}
if (es->down.recognized)
{
d = (-dy - d);
if (d < 0) d = 0;
if (es->zone->h > 1) v = (double)d / (es->zone->h / 2);
else v = 1.0;
_handler_call(E_EDGES_BOTTOM_IN_SLIDE, d, v);
}
}
}

View File

@ -0,0 +1,20 @@
#ifndef E_EDGES_H
# define E_EDGES_H
typedef enum
{
E_EDGES_LEFT_IN_BEGIN,
E_EDGES_RIGHT_IN_BEGIN,
E_EDGES_TOP_IN_BEGIN,
E_EDGES_BOTTOM_IN_BEGIN,
E_EDGES_LEFT_IN_SLIDE,
E_EDGES_RIGHT_IN_SLIDE,
E_EDGES_TOP_IN_SLIDE,
E_EDGES_BOTTOM_IN_SLIDE
} E_Edges_Event;
void e_edges_init(void);
void e_edges_shutdown(void);
void e_edges_handler_set(E_Edges_Event event, void (*func) (void *data, int d, double v), void *data);
#endif

View File

@ -2,15 +2,83 @@
EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Contact" };
static void
_cb_in_left(void *data, int d, double v)
{
// show PREV window in list from urrent focused window on top of current
// window but in an inital "off to the right" state in comp
}
static void
_cb_in_left_go(void *data, int d, double v)
{
// as v > 0 (and heads towards 1.0) flip/slide new window in unbtil v > 1.0
// and once over 1.0 just do transition until end
}
static void
_cb_in_right(void *data, int d, double v)
{
// show NEXT window in list from urrent focused window on top of current
// window but in an inital "off to the right" state in comp
}
static void
_cb_in_right_go(void *data, int d, double v)
{
// as v > 0 (and heads towards 1.0) flip/slide new window in unbtil v > 1.0
// and once over 1.0 just do transition until end
}
static void
_cb_in_top(void *data, int d, double v)
{
// show/populate top controls if not already there and start in offscreen
// state and beign slide in anim and place controls at final spot
}
static void
_cb_in_top_go(void *data, int d, double v)
{
// for now nothing - but animation would be nice for top controls
}
static void
_cb_in_bottom(void *data, int d, double v)
{
// force kbd activation if no kbd
e_policy_kbd_override_set(EINA_TRUE);
// if kbd already up... hmmm show app menu?
}
static void
_cb_in_bottom_go(void *data, int d, double v)
{
// for now nothing - but slide animation is nice
}
EAPI void *
e_modapi_init(E_Module *m __UNUSED__)
{
e_policy_init();
e_edges_init();
e_edges_handler_set(E_EDGES_LEFT_IN_BEGIN, _cb_in_left, NULL);
e_edges_handler_set(E_EDGES_LEFT_IN_SLIDE, _cb_in_left_go, NULL);
e_edges_handler_set(E_EDGES_RIGHT_IN_BEGIN, _cb_in_right, NULL);
e_edges_handler_set(E_EDGES_RIGHT_IN_SLIDE, _cb_in_right_go, NULL);
e_edges_handler_set(E_EDGES_TOP_IN_BEGIN, _cb_in_top, NULL);
e_edges_handler_set(E_EDGES_TOP_IN_SLIDE, _cb_in_top_go, NULL);
e_edges_handler_set(E_EDGES_BOTTOM_IN_BEGIN, _cb_in_bottom, NULL);
e_edges_handler_set(E_EDGES_BOTTOM_IN_SLIDE, _cb_in_bottom_go, NULL);
return m;
}
EAPI int
e_modapi_shutdown(E_Module *m __UNUSED__)
{
e_edges_shutdown();
e_policy_shutdown();
return 1;
}

View File

@ -2,5 +2,7 @@
# define E_MOD_MAIN_H
# include "e.h"
# include "e_policy.h"
# include "e_edges.h"
#endif

View File

@ -0,0 +1,243 @@
#include "e_mod_main.h"
static Eina_Bool _cb_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event);
static Eina_Bool _cb_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event);
static void _cb_hook_post_fetch(void *data __UNUSED__, void *data2);
static void _cb_hook_post_assign(void *data __UNUSED__, void *data2);
static void _cb_hook_layout(void *data __UNUSED__, void *data2);
static Eina_List *hooks = NULL;
static Eina_List *handlers = NULL;
static Eina_Bool kbd_on = EINA_FALSE;
static Eina_Bool kbd_override = EINA_FALSE;
#define LADD(l, f) l = eina_list_append(l, f)
void
e_policy_init(void)
{
LADD(hooks, e_border_hook_add(E_BORDER_HOOK_EVAL_POST_FETCH,
_cb_hook_post_fetch, NULL));
LADD(hooks, e_border_hook_add(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN,
_cb_hook_post_assign, NULL));
LADD(hooks, e_border_hook_add(E_BORDER_HOOK_CONTAINER_LAYOUT,
_cb_hook_layout, NULL));
LADD(handlers, ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN,
_cb_event_focus_in, NULL));
LADD(handlers, ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT,
_cb_event_focus_out, NULL));
}
void
e_policy_shutdown(void)
{
E_Border_Hook *bh;
Ecore_Event_Handler *eh;
EINA_LIST_FREE(hooks, bh) e_border_hook_del(bh);
EINA_LIST_FREE(handlers, eh) ecore_event_handler_del(eh);
}
static Eina_Bool
_cb_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
{
E_Border *bd = event;
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_cb_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
{
E_Border *bd = event;
if (kbd_on) e_policy_kbd_override_set(EINA_FALSE);
return ECORE_CALLBACK_PASS_ON;
}
static void
_cb_hook_post_fetch(void *data __UNUSED__, void *data2)
{
E_Border *bd = data2;
if (!bd) return;
/* NB: for this policy we disable all remembers set on a border */
if (bd->remember) e_remember_del(bd->remember);
bd->remember = NULL;
/* set this border to borderless */
bd->borderless = 1;
bd->client.border.changed = 1;
}
static void
_cb_hook_post_assign(void *data __UNUSED__, void *data2)
{
E_Border *bd = data2;
if (!bd) return;
bd->internal_no_remember = 1;
/* do not allow client to change these properties */
bd->lock_client_size = 1;
bd->lock_client_shade = 1;
bd->lock_client_maximize = 1;
bd->lock_client_location = 1;
bd->lock_client_stacking = 1;
/* do not allow the user to change these properties */
bd->lock_user_location = 1;
bd->lock_user_size = 1;
bd->lock_user_shade = 1;
/* clear any centered states */
/* NB: this is mainly needed for E's main config dialog */
bd->client.e.state.centered = 0;
/* lock the border type so user/client cannot change */
bd->lock_border = 1;
}
void
e_policy_kbd_override_set(Eina_Bool override)
{
Eina_List *l;
E_Border *bd, *kbd = NULL;;
if (kbd_override == override) return;
kbd_override = override;
EINA_LIST_FOREACH(e_border_client_list(), l, bd)
{
if (bd->client.vkbd.vkbd)
{
kbd = bd;
}
}
if (kbd)
{
bd = kbd;
e_border_uniconify(bd);
e_border_raise(bd);
e_border_show(bd);
}
}
static void
_cb_hook_layout(void *data __UNUSED__, void *data2)
{
E_Container *con = data2;
Eina_List *l;
E_Border *bd, *kbd = NULL;;
Eina_Bool want_kbd = EINA_FALSE;
Eina_Bool have_focused = EINA_FALSE;
int kx = 0, ky = 0, kw = 0, kh = 0;
if (!con) return;
EINA_LIST_FOREACH(e_border_client_list(), l, bd)
{
if (bd->focused) have_focused = EINA_TRUE;
if ((bd->focused) &&
(bd->client.vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF))
want_kbd = EINA_TRUE;
if (bd->client.vkbd.vkbd) kbd = bd;
}
if ((have_focused) && (kbd_override)) want_kbd = EINA_TRUE;
if (kbd)
{
kw = kbd->zone->w;
kh = kbd->client.icccm.min_h;
kx = kbd->zone->x;
ky = kbd->zone->y + kbd->zone->h - kh;
}
EINA_LIST_FOREACH(e_border_client_list(), l, bd)
{
int x, y, w, h;
if (!bd->zone) continue;
w = bd->zone->w;
h = bd->zone->h;
x = bd->zone->x;
y = bd->zone->y;
if (bd->client.vkbd.vkbd)
{
x = kx; y = ky; w = kw; h = kh;
if (want_kbd)
{
e_border_uniconify(bd);
e_border_raise(bd);
e_border_show(bd);
}
else
{
e_border_iconify(bd);
}
}
else if (((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) ||
(bd->client.icccm.transient_for != 0)) &&
((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
(bd->client.icccm.min_h == bd->client.icccm.max_h)))
{
// center dialog at min size
w = bd->client.icccm.min_w;
h = bd->client.icccm.min_h;
if (w > (bd->zone->w)) w = bd->zone->w;
if (h > (bd->zone->h - kh)) h = (bd->zone->h - kh);
x = bd->zone->x + ((bd->zone->w - w) / 2);
y = bd->zone->y + ((bd->zone->h - kh - h) / 2);
}
else
{
if (bd->client.illume.conformant.conformant)
{
if (kbd_on != want_kbd)
{
if (want_kbd)
ecore_x_e_illume_keyboard_geometry_set(bd->client.win,
kx, ky, kw, kh);
else
ecore_x_e_illume_keyboard_geometry_set(bd->client.win,
0, 0, 0, 0);
}
}
else
{
// just make all windows fill the zone...
if (want_kbd)
{
w = bd->zone->w;
h = bd->zone->h - kh;
x = bd->zone->x;
y = bd->zone->y;
}
}
}
// implement the positioning/sizing
if ((bd->x != x) || (bd->y != y))
{
bd->placed = 1;
bd->x = x;
bd->y = y;
bd->changes.pos = 1;
bd->changed = 1;
}
if ((bd->w != w) || (bd->h != h))
{
bd->w = w;
bd->h = h;
bd->client.w = (bd->w - (bd->client_inset.l + bd->client_inset.r));
bd->client.h = (bd->h - (bd->client_inset.t + bd->client_inset.b));
bd->changes.size = 1;
bd->changed = 1;
}
}
kbd_on = want_kbd;
}

View File

@ -0,0 +1,8 @@
#ifndef E_POLICY_H
# define E_POLICY_H
void e_policy_init(void);
void e_policy_shutdown(void);
void e_policy_kbd_override_set(Eina_Bool override);
#endif