fully support _GTK_FRAME_EXTENTS
authorMike Blumenkrantz <zmike@osg.samsung.com>
Thu, 24 Sep 2015 19:29:37 +0000 (15:29 -0400)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Thu, 24 Sep 2015 20:33:56 +0000 (16:33 -0400)
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

src/bin/e_comp_object.c
src/bin/e_comp_object.h
src/bin/e_comp_x.c
src/bin/e_comp_x.h

index 55c6dc4..c42ec47 100644 (file)
@@ -868,9 +868,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))
           {
@@ -929,6 +935,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);
      }
 }
@@ -939,7 +948,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)) ||
@@ -1022,7 +1037,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 */
@@ -1033,6 +1052,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);
@@ -2231,7 +2253,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))
           {
@@ -2847,6 +2873,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)
 {
index aca2ba4..b13a63a 100644 (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);
index 6434485..fb8a77b 100644 (file)
@@ -422,6 +422,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)
           {
@@ -2125,6 +2127,11 @@ _e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Cl
           }
      }
 #endif
+   else if (ev->message_type == ATM_GTK_FRAME_EXTENTS)
+     {
+        _e_comp_x_client_data_get(ec)->fetch_gtk_frame_extents = 1;
+        EC_CHANGED(ec);
+     }
    else
      DBG("missed client message '%s' for %u", ecore_x_atom_name_get(ev->message_type), ev->win);
    return ECORE_CALLBACK_PASS_ON;
@@ -4288,6 +4295,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 (cd->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);
+          }
+        cd->fetch_gtk_frame_extents = 0;
+     }
    ec->changes.prop = 0;
    if (rem_change) e_remember_update(ec);
    if ((!cd->reparented) && (!ec->internal)) ec->changes.border = 0;
index af1a01c..28da7b5 100644 (file)
@@ -105,6 +105,7 @@ struct _E_Comp_X_Client_Data
    Eina_Bool frame_update : 1;
    Eina_Bool evas_init : 1;
    Eina_Bool unredirected_single : 1;
+   Eina_Bool fetch_gtk_frame_extents : 1;
 };
 
 E_API Eina_Bool e_comp_x_init(void);