diff --git a/data/orig/border.xcf b/data/orig/border.xcf new file mode 100644 index 000000000..4ad87b3c9 Binary files /dev/null and b/data/orig/border.xcf differ diff --git a/src/Makefile.am b/src/Makefile.am index 598bdb3ef..c53cc1b65 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) diff --git a/src/actions.c b/src/actions.c index c62d7d072..a800d0fc9 100644 --- a/src/actions.c +++ b/src/actions.c @@ -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 diff --git a/src/border.c b/src/border.c index 90b11a594..494d41506 100644 --- a/src/border.c +++ b/src/border.c @@ -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) diff --git a/src/desktops.c b/src/desktops.c index 3c6a0784c..ad59c2982 100644 --- a/src/desktops.c +++ b/src/desktops.c @@ -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; diff --git a/src/e.h b/src/e.h index efbb10eb9..c012a6817 100644 --- a/src/e.h +++ b/src/e.h @@ -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); diff --git a/src/icccm.c b/src/icccm.c index 95dd183d9..a38194dca 100644 --- a/src/icccm.c +++ b/src/icccm.c @@ -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) { diff --git a/src/view.c b/src/view.c new file mode 100644 index 000000000..c6bab4015 --- /dev/null +++ b/src/view.c @@ -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) +{ +}