e17 now handles shaped client windows.. and if they change shape...

it also handles clients that re-configfure size and position whilst
shaiding & unshading and whilst shaded. it also doesnt segv if a window
closes/vanishes whilst shading (i added a subsystem to handle stopping
of continuing timed out actions if their object goes away)


SVN revision: 4006
This commit is contained in:
Carsten Haitzler 2000-12-18 21:28:44 +00:00
parent 5f743162c9
commit 6e67eca120
8 changed files with 287 additions and 29 deletions

BIN
data/orig/border.xcf Normal file

Binary file not shown.

View File

@ -16,6 +16,7 @@ icccm.c \
main.c \
resist.c \
util.c \
view.c \
e.h
enlightenment_LDADD = @evas_libs@ @edb_libs@ @ebits_libs@ @ecore_libs@ -lm $(INTLLIBS)

View File

@ -2,6 +2,7 @@
static Evas_List action_protos = NULL;
static Evas_List current_actions = NULL;
static Evas_List current_timers = NULL;
static void _e_action_find(char *action, int act, int button, char *key, Ev_Key_Modifiers mods, void *o);
static void _e_action_free(E_Action *a);
@ -292,6 +293,7 @@ e_action_stop_by_object(void *o, void *data, int x, int y, int rx, int ry)
{
Evas_List l;
e_actions_del_timer_object(o);
again:
for (l = current_actions; l; l = l->next)
{
@ -336,6 +338,64 @@ e_action_add_proto(char *action,
action_protos = evas_list_append(action_protos, ap);
}
void
e_actions_del_timer(void *o, char *name)
{
Evas_List l;
again:
for (l = current_timers; l; l = l->next)
{
E_Active_Action_Timer *at;
at = l->data;
if ((at->object == o) &&
(name) &&
(at->name) &&
(!strcmp(at->name, name)))
{
e_del_event_timer(at->name);
current_timers = evas_list_remove(current_timers, at);
IF_FREE(at->name);
FREE(at);
goto again;
}
}
}
void
e_actions_add_timer(void *o, char *name)
{
E_Active_Action_Timer *at;
at = NEW(E_Active_Action_Timer, 1);
at->object = o;
at->name = strdup(name);
current_timers = evas_list_append(current_timers, at);
}
void
e_actions_del_timer_object(void *o)
{
Evas_List l;
again:
for (l = current_timers; l; l = l->next)
{
E_Active_Action_Timer *at;
at = l->data;
if (at->object == o)
{
e_del_event_timer(at->name);
current_timers = evas_list_remove(current_timers, at);
IF_FREE(at->name);
FREE(at);
goto again;
}
}
}
void
e_actions_init(void)
{
@ -733,10 +793,17 @@ e_act_cb_shade(int val, void *data)
static double t = 0.0;
double dif;
int si;
int pix_per_sec = 1600;
int pix_per_sec = 3200;
b = data;
if (val == 0) t = e_get_time();
if (val == 0)
{
OBJ_REF(b);
t = e_get_time();
e_window_gravity_set(b->win.client, SouthWestGravity);
e_actions_del_timer(b, "shader");
e_actions_add_timer(b, "shader");
}
dif = e_get_time() - t;
@ -745,9 +812,15 @@ e_act_cb_shade(int val, void *data)
b->current.shaded = si;
b->changed = 1;
e_border_adjust_limits(b);
e_border_apply_border(b);
if (si < b->client.h)
e_add_event_timer("shader", 0.01, e_act_cb_shade, 1, data);
e_border_apply_border(b);
else
{
e_actions_del_timer(b, "shader");
e_window_gravity_reset(b->win.client);
OBJ_UNREF(b);
}
}
static void e_act_cb_unshade(int val, void *data);
@ -758,10 +831,17 @@ e_act_cb_unshade(int val, void *data)
static double t = 0.0;
double dif;
int si;
int pix_per_sec = 1600;
int pix_per_sec = 3200;
b = data;
if (val == 0) t = e_get_time();
if (val == 0)
{
OBJ_REF(b);
t = e_get_time();
e_window_gravity_set(b->win.client, SouthWestGravity);
e_actions_del_timer(b, "shader");
e_actions_add_timer(b, "shader");
}
dif = e_get_time() - t;
@ -771,9 +851,15 @@ e_act_cb_unshade(int val, void *data)
b->current.shaded = si;
b->changed = 1;
e_border_adjust_limits(b);
e_border_apply_border(b);
if (si > 0)
e_add_event_timer("shader", 0.01, e_act_cb_unshade, 1, data);
e_border_apply_border(b);
else
{
e_actions_del_timer(b, "shader");
e_window_gravity_reset(b->win.client);
OBJ_UNREF(b);
}
}
static void

View File

@ -119,7 +119,24 @@ e_configure_request(Eevent * ev)
if (e->mask & EV_VALUE_W)
b->current.requested.w = e->w + pl + pr;
if (e->mask & EV_VALUE_H)
b->current.requested.h = e->h + pt + pb;
{
if (b->current.shaded == b->client.h)
{
b->current.shaded = e->h;
}
else if (b->current.shaded != 0)
{
b->current.shaded += b->client.h - e->h;
if (b->current.shaded > b->client.h)
b->current.shaded = b->client.h;
if (b->current.shaded < 1)
b->current.shaded = 1;
}
b->client.w = e->w;
b->client.h = e->h;
b->current.requested.h = e->h + pt + pb;
}
if ((e->mask & EV_VALUE_SIBLING) && (e->mask & EV_VALUE_STACKING))
{
E_Border *b_rel;
@ -335,8 +352,11 @@ e_shape(Eevent * ev)
E_Border *b;
b = e_border_find_by_window(e->win);
if (b)
if ((b) && (e->win == b->win.client))
{
b->current.shaped_client = e_icccm_is_shaped(e->win);
b->changed = 1;
b->shape_changed = 1;
}
}
current_ev = NULL;
@ -1014,6 +1034,91 @@ e_border_apply_border(E_Border *b)
e_icccm_set_frame_size(b->win.client, pl, pr, pt, pb);
}
void
e_border_reshape(E_Border *b)
{
static Window shape_win = 0;
int pl, pr, pt, pb;
if ((b->current.shaped_client == b->previous.shaped_client) &&
(b->current.shape_changes == b->previous.shape_changes) &&
(b->current.has_shape == b->previous.has_shape) &&
(!b->shape_changed))
return;
if (!shape_win) shape_win = e_window_override_new(0, 0, 0, 1, 1);
pl = pr = pt = pb = 0;
if (b->bits.t) ebits_get_insets(b->bits.t, &pl, &pr, &pt, &pb);
b->shape_changed = 0;
if ((!b->current.shaped_client) && (!b->current.has_shape))
{
e_window_set_shape_mask(b->win.main, 0);
return;
}
if ((b->current.shaped_client) && (!b->current.has_shape))
{
XRectangle rects[4];
rects[0].x = 0; rects[0].y = 0;
rects[0].width = b->current.w; rects[0].height = pt;
rects[1].x = 0; rects[1].y = pt;
rects[1].width = pl; rects[1].height = b->current.h - pt - pb;
rects[2].x = b->current.w - pr; rects[2].y = pt;
rects[2].width = pr; rects[2].height = b->current.h - pt - pb;
rects[3].x = 0; rects[3].y = b->current.h - pb;
rects[3].width = b->current.w; rects[3].height = pb;
e_window_resize(shape_win, b->current.w, b->current.h);
e_window_set_shape_window(shape_win, b->win.client, pl, pt - b->current.shaded);
e_window_clip_shape_by_rectangle(shape_win, pl, pt, b->current.w - pl - pr, b->current.h - pt - pb);
e_window_add_shape_rectangles(shape_win, rects, 4);
e_window_set_shape_window(b->win.main, shape_win, 0, 0);
return;
}
if ((!b->current.shaped_client) && (b->current.has_shape))
{
e_window_resize(shape_win, b->current.w, b->current.h);
e_window_set_shape_rectangle(shape_win, pl, pt - b->current.shaded, b->current.w - pl - pr, b->current.h - pt - pb);
/* FIXME: later when i actually generate shape masks for borders */
{
XRectangle rects[4];
rects[0].x = 0; rects[0].y = 0;
rects[0].width = b->current.w; rects[0].height = pt;
rects[1].x = 0; rects[1].y = pt;
rects[1].width = pl; rects[1].height = b->current.h - pt - pb;
rects[2].x = b->current.w - pr; rects[2].y = pt;
rects[2].width = pr; rects[2].height = b->current.h - pt - pb;
rects[3].x = 0; rects[3].y = b->current.h - pb;
rects[3].width = b->current.w; rects[3].height = pb;
e_window_add_shape_rectangles(shape_win, rects, 4);
}
e_window_set_shape_window(b->win.main, shape_win, 0, 0);
return;
}
if ((b->current.shaped_client) && (b->current.has_shape))
{
e_window_resize(shape_win, b->current.w, b->current.h);
e_window_set_shape_window(shape_win, b->win.client, pl, pt - b->current.shaded);
e_window_clip_shape_by_rectangle(shape_win, pl, pt, b->current.w - pl - pr, b->current.h - pt - pb);
/* FIXME: later when i actually generate shape masks for borders */
{
XRectangle rects[4];
rects[0].x = 0; rects[0].y = 0;
rects[0].width = b->current.w; rects[0].height = pt;
rects[1].x = 0; rects[1].y = pt;
rects[1].width = pl; rects[1].height = b->current.h - pt - pb;
rects[2].x = b->current.w - pr; rects[2].y = pt;
rects[2].width = pr; rects[2].height = b->current.h - pt - pb;
rects[3].x = 0; rects[3].y = b->current.h - pb;
rects[3].width = b->current.w; rects[3].height = pb;
e_window_add_shape_rectangles(shape_win, rects, 4);
}
e_window_set_shape_window(b->win.main, shape_win, 0, 0);
return;
}
}
E_Border *
e_border_adopt(Window win, int use_client_pos)
{
@ -1029,6 +1134,7 @@ e_border_adopt(Window win, int use_client_pos)
XEV_FOCUS |
XEV_PROPERTY |
XEV_COLORMAP);
e_window_select_shape_events(win);
/* parent of the client window listens for these */
e_window_set_events(b->win.container, XEV_CHILD_CHANGE | XEV_CHILD_REDIRECT);
/* add to save set & border of 0 */
@ -1036,10 +1142,11 @@ e_border_adopt(Window win, int use_client_pos)
e_window_set_border_width(win, 0);
b->win.client = win;
b->current.requested.visible = 1;
/* get size & location hints */
/* get hints */
e_icccm_get_size_info(win, b);
e_icccm_get_mwm_hints(win, b);
e_icccm_get_layer(win, b);
b->current.shaped_client = e_icccm_is_shaped(win);
/* we have now placed the bugger */
b->placed = 1;
/* desk area */
@ -1593,14 +1700,14 @@ e_border_update(E_Border *b)
location_changed = 1;
if ((b->current.w != b->previous.w) || (b->current.h != b->previous.h))
size_changed = 1;
if ((size_changed) && (b->has_shape))
if ((size_changed) && (b->current.has_shape))
shape_changed = 1;
if (b->bits.new)
{
e_window_gravity_set(b->win.container, StaticGravity);
border_changed = 1;
}
if ((border_changed) && (b->has_shape))
if ((border_changed) && (b->current.has_shape))
shape_changed = 1;
if (b->current.visible != b->previous.visible)
visibility_changed = 1;
@ -1636,6 +1743,10 @@ e_border_update(E_Border *b)
int pl, pr, pt, pb, x, y, w, h;
int smaller;
if ((b->current.shaped_client) || (b->previous.shaped_client) ||
(b->current.shape_changes) || (b->previous.shape_changes) ||
(b->current.has_shape) || (b->previous.has_shape))
b->shape_changed = 1;
smaller = 0;
if ((b->current.w < b->previous.w) || (b->current.h < b->previous.h))
smaller = 1;
@ -1655,8 +1766,8 @@ e_border_update(E_Border *b)
e_window_move_resize(b->win.container,
b->current.w + 1,
b->current.h + 1,
1,
1);
320,
320);
}
else
{
@ -1720,6 +1831,7 @@ e_border_update(E_Border *b)
b->client.w, b->client.h);
e_cb_border_move_resize(b);
}
e_border_reshape(b);
if (visibility_changed)
{
if (b->current.visible)

View File

@ -63,6 +63,7 @@ e_mouse_down(Eevent * ev)
}
}
}
/* handling mouse up events */
static void
e_mouse_up(Eevent * ev)
@ -95,6 +96,7 @@ e_mouse_up(Eevent * ev)
}
}
}
/* handling mouse move events */
static void
e_mouse_move(Eevent * ev)
@ -161,6 +163,7 @@ e_mouse_in(Eevent * ev)
}
}
}
/* handling mouse leave events */
static void
e_mouse_out(Eevent * ev)
@ -304,7 +307,8 @@ e_desktops_scroll(E_Desktop *desk, int dx, int dy)
b = l->data;
/* if sticky */
/* e_window_gravity_set(b->win.main, StaticGravity); */
if (b->client.sticky)
e_window_gravity_set(b->win.main, StaticGravity);
e_window_gravity_set(b->win.main, grav);
}
grav_stick = StaticGravity;

47
src/e.h
View File

@ -79,7 +79,7 @@ printf("%3.3f : %s()\n", __p->total, __p->func); \
#define OBJ_REF(_e_obj) _e_obj->references++
#define OBJ_UNREF(_e_obj) _e_obj->references--;
#define OBJ_UNREF(_e_obj) _e_obj->references--
#define OBJ_IF_FREE(_e_obj) if (_e_obj->references == 0)
#define OBJ_FREE(_e_obj) _e_obj->e_obj_free(_e_obj)
#define OBJ_DO_FREE(_e_obj) \
@ -121,14 +121,16 @@ e_window_gravity_set(_b->win.r, _grav); \
e_window_gravity_set(_b->win.t, _grav); \
e_window_gravity_set(_b->win.b, _grav);
typedef struct _E_Object E_Object;
typedef struct _E_Border E_Border;
typedef struct _E_Grab E_Grab;
typedef struct _E_Action E_Action;
typedef struct _E_Action_Proto E_Action_Proto;
typedef struct _E_Desktop E_Desktop;
typedef struct _E_Rect E_Rect;
typedef struct _E_Object E_Object;
typedef struct _E_Border E_Border;
typedef struct _E_Grab E_Grab;
typedef struct _E_Action E_Action;
typedef struct _E_Action_Proto E_Action_Proto;
typedef struct _E_Desktop E_Desktop;
typedef struct _E_Rect E_Rect;
typedef struct _E_Active_Action_Timer E_Active_Action_Timer;
typedef struct _E_View E_View;
struct _E_Object
{
OBJ_PROPERTIES;
@ -166,6 +168,9 @@ struct _E_Border
int visible;
int selected;
int shaded;
int has_shape;
int shape_changes;
int shaped_client;
} current, previous;
struct {
@ -174,7 +179,6 @@ struct _E_Border
double aspect;
} base, min, max, step;
int layer;
int shaped;
char *title;
char *name;
char *class;
@ -187,7 +191,6 @@ struct _E_Border
int arrange_ignore;
int hidden;
int iconified;
int borderless;
int titlebar;
int border;
int handles;
@ -198,11 +201,9 @@ struct _E_Border
int move, resize;
} mode;
int has_shape;
int shape_changes;
int ignore_unmap;
int shape_changed;
int placed;
Evas_List grabs;
@ -277,6 +278,17 @@ struct _E_Rect
int v1, v2, v3, v4;
};
struct _E_Active_Action_Timer
{
void *object;
char *name;
};
struct _E_View
{
OBJ_PROPERTIES
};
void e_action_add_proto(char *action,
void (*func_start) (void *o, E_Action *a, void *data, int x, int y, int rx, int ry),
void (*func_stop) (void *o, E_Action *a, void *data, int x, int y, int rx, int ry),
@ -286,10 +298,14 @@ void e_action_start(char *action, int act, int button, char *key, Ev_Key_Modifie
void e_action_stop(char *action, int act, int button, char *key, Ev_Key_Modifiers mods, void *o, void *data, int x, int y, int rx, int ry);
void e_action_go(char *action, int act, int button, char *key, Ev_Key_Modifiers mods, void *o, void *data, int x, int y, int rx, int ry, int dx, int dy);
void e_action_stop_by_object(void *o, void *data, int x, int y, int rx, int ry);
void e_actions_del_timer(void *o, char *name);
void e_actions_add_timer(void *o, char *name);
void e_actions_del_timer_object(void *o);
void e_border_apply_border(E_Border *b);
E_Border * e_border_new(void);
E_Border * e_border_adopt(Window win, int use_client_pos);
void e_border_reshape(E_Border *b);
void e_border_free(E_Border *b);
void e_border_remove_mouse_grabs(E_Border *b);
void e_border_attach_mouse_grabs(E_Border *b);
@ -323,6 +339,7 @@ void e_icccm_set_frame_size(Window win, int l, int r, int t, int b);
void e_icccm_set_desk_area(Window win, int ax, int ay);
void e_icccm_set_desk_area_size(Window win, int ax, int ay);
void e_icccm_set_desk(Window win, int d);
int e_icccm_is_shaped(Window win);
void e_icccm_handle_property_change(Atom a, E_Border *b);
void e_icccm_handle_client_message(Ev_Message *e);
void e_icccm_advertise_e_compat(void);

View File

@ -370,6 +370,24 @@ e_icccm_set_desk(Window win, int d)
e_window_property_set(win, a_win_workspace, XA_CARDINAL, 32, props, 1);
}
int
e_icccm_is_shaped(Window win)
{
int w, h, num;
int shaped = 1;
XRectangle *rect;
e_window_get_geometry(win, NULL, NULL, &w, &h);
rect = e_window_get_shape_rectangles(win, &num);
if (!rect) return 1;
if ((num == 1) &&
(rect[0].x == 0) && (rect[0].y == 0) &&
(rect[0].width == w) && (rect[0].height == h))
shaped = 0;
XFree(rect);
return shaped;
}
void
e_icccm_handle_property_change(Atom a, E_Border *b)
{

20
src/view.c Normal file
View File

@ -0,0 +1,20 @@
#include "e.h"
E_View *
e_view_new(void)
{
E_View *v;
v = NEW(E_View, 1);
ZERO(v, E_View, 1);
}
void
e_view_free(E_View *v)
{
}
void
e_view_init(void)
{
}