fully support _GTK_FRAME_EXTENTS

gtk apps set an atom which provides information about the area
where non-window content (eg. shadows) may be drawn; this area
must not be used in placement calculations.

the easiest method for implementing this functionality was to add
a case to the compositor geometry interceptors which effectively
flip the client struct geometry values such that the E_Client->client
is outside of the more commonly used E_Client->x/y/w/h

fix T2744
This commit is contained in:
Mike Blumenkrantz 2015-09-24 15:29:37 -04:00
parent 0692c736d0
commit 53e0c56f5e
4 changed files with 79 additions and 5 deletions

View File

@ -760,9 +760,15 @@ static void
_e_comp_intercept_move(void *data, Evas_Object *obj, int x, int y)
{
E_Comp_Object *cw = data;
int ix, iy;
int ix, iy, fx, fy;
if ((cw->x == x) && (cw->y == y))
/* if frame_object does not exist, client_inset indicates CSD.
* this means that ec->client matches cw->x/y, the opposite
* of SSD.
*/
fx = (!cw->frame_object) * cw->client_inset.l;
fy = (!cw->frame_object) * cw->client_inset.t;
if ((cw->x == x + fx) && (cw->y == y + fy))
{
if ((cw->ec->x != x) || (cw->ec->y != y))
{
@ -821,6 +827,9 @@ _e_comp_intercept_move(void *data, Evas_Object *obj, int x, int y)
cw->ec->client.x = ix;
cw->ec->client.y = iy;
}
/* flip SSD->CSD */
if (!cw->frame_object)
x = ix, y = iy;
evas_object_move(obj, x, y);
}
}
@ -831,7 +840,13 @@ _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
E_Comp_Object *cw = data;
int pw, ph, fw, fh, iw, ih, prev_w, prev_h;
if ((cw->w == w) && (cw->h == h))
/* if frame_object does not exist, client_inset indicates CSD.
* this means that ec->client matches cw->w/h, the opposite
* of SSD.
*/
fw = (!cw->frame_object) * (-cw->client_inset.l - cw->client_inset.r);
fh = (!cw->frame_object) * (-cw->client_inset.t - cw->client_inset.b);
if ((cw->w == w + fw) && (cw->h == h + fh))
{
if (cw->ec->shading || cw->ec->shaded) return;
if (((cw->ec->w != w) || (cw->ec->h != h)) ||
@ -913,7 +928,11 @@ _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
{
//INF("CALLBACK: REQ(%dx%d) != CUR(%dx%d)", w - fw, h - fh, pw, ph);
evas_object_smart_callback_call(obj, "client_resize", NULL);
e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
/* flip for CSD */
if (cw->frame_object || cw->ec->input_only)
e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
else
w = pw, h = ph;
if ((cw->w == w) && (cw->h == h))
{
/* going to be a noop resize which won't trigger smart resize */
@ -924,6 +943,9 @@ _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
}
else
{
/* flip for CSD */
if ((!cw->frame_object) && (!cw->ec->input_only))
w = pw, h = ph;
/* "just do it" for overrides */
//INF("INTERCEPT %dx%d", w, h);
evas_object_resize(obj, w, h);
@ -2086,7 +2108,11 @@ _e_comp_smart_resize(Evas_Object *obj, int w, int h)
if ((!cw->ec->shading) && (!cw->ec->shaded))
{
int ww, hh, pw, ph;
e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
if (cw->frame_object)
e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
else
ww = w, hh = h;
/* verify pixmap:object size */
if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
{
@ -2741,6 +2767,22 @@ e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *
if (b) *b = cw->client_inset.b;
}
/* set geometry for CSD */
E_API void
e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
{
API_ENTRY;
cw->client_inset.l = l;
cw->client_inset.r = r;
cw->client_inset.t = t;
cw->client_inset.b = b;
cw->client_inset.calc = 1;
eina_stringshare_replace(&cw->frame_theme, "borderless");
if (!cw->ec->new_client) return;
cw->ec->w += l + r;
cw->ec->h += t + b;
}
E_API void
e_comp_object_frame_icon_geometry_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
{

View File

@ -54,6 +54,7 @@ E_API void e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on);
E_API void e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y);
E_API void e_comp_object_util_fullscreen(Evas_Object *obj);
E_API void e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b);
E_API void e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b);
E_API void e_comp_object_frame_icon_geometry_get(Evas_Object *obj, int *x, int *y, int *w, int *h);
E_API Eina_Bool e_comp_object_frame_title_set(Evas_Object *obj, const char *name);
E_API Eina_Bool e_comp_object_frame_exists(Evas_Object *obj);

View File

@ -398,6 +398,8 @@ _e_comp_x_client_new_helper(E_Client *ec)
/* loop to check for window profile list atom */
else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
ec->e.fetch.profile = 1;
else if (atoms[i] == ATM_GTK_FRAME_EXTENTS)
ec->comp_data->fetch_gtk_frame_extents = 1;
}
if (video_position && video_parent)
{
@ -2028,6 +2030,11 @@ _e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Cl
free(p);
}
}
else if (ev->message_type == ATM_GTK_FRAME_EXTENTS)
{
ec->comp_data->fetch_gtk_frame_extents = 1;
EC_CHANGED(ec);
}
return ECORE_CALLBACK_PASS_ON;
}
@ -4199,6 +4206,29 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
ec->e.state.profile.wait_for_done = 1;
eina_stringshare_replace(&ec->e.state.profile.set, NULL);
}
if (ec->comp_data->fetch_gtk_frame_extents)
{
unsigned char *data;
int count;
if (ecore_x_window_prop_property_get(win,
ATM_GTK_FRAME_EXTENTS,
ECORE_X_ATOM_CARDINAL, 32,
&data, &count))
{
unsigned int *extents = (unsigned int*)data;
/* _GTK_FRAME_EXTENTS describes a region l/r/t/b pixels
* from the "window" object in which shadows will be drawn.
* this area should not be accounted for in sizing or
* placement calculations.
*/
e_comp_object_frame_geometry_set(ec->frame,
-extents[0], -extents[1], -extents[2], -extents[3]);
free(data);
}
ec->comp_data->fetch_gtk_frame_extents = 0;
}
ec->changes.prop = 0;
if (rem_change) e_remember_update(ec);
if ((!ec->comp_data->reparented) && (!ec->internal)) ec->changes.border = 0;

View File

@ -106,6 +106,7 @@ struct _E_Comp_X_Client_Data
Eina_Bool evas_init : 1;
Eina_Bool unredirected_single : 1;
unsigned int parent_activate_count; //number of times a win has activated itself when parent was focused
Eina_Bool fetch_gtk_frame_extents : 1;
};
EINTERN Eina_Bool e_comp_x_init(void);