resize e_comp_object to the viewport size of a client
authorBoram Park <boram1288.park@samsung.com>
Thu, 7 Jan 2016 10:40:36 +0000 (19:40 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Thu, 21 Jan 2016 07:20:12 +0000 (16:20 +0900)
Change-Id: I22818b165368b8c9ee94a4d10038ff9bf98e2f9d

src/bin/e_comp_object.c
src/bin/e_comp_wl.c
src/bin/e_comp_wl.h

index 13f42bf..12a8eea 100644 (file)
@@ -1076,6 +1076,9 @@ _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
 {
    E_Comp_Object *cw = data;
    int pw = 0, ph = 0, fw, fh, iw, ih, prev_w, prev_h, x, y;
+#ifdef HAVE_WAYLAND_ONLY
+   E_Comp_Wl_Client_Data *cd;
+#endif
 
    if ((!e_util_strcmp("wl_pointer-cursor", cw->ec->icccm.window_role)) ||
        (!e_util_strcmp("input_panel_surface", cw->ec->icccm.window_role)))
@@ -1184,6 +1187,21 @@ _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
         EC_CHANGED(cw->ec);
         return;
      }
+
+#ifdef HAVE_WAYLAND_ONLY
+   cd = (E_Comp_Wl_Client_Data *)cw->ec->comp_data;
+   if (cd && cd->sub.data && (cd->width_from_viewport < cd->width_from_buffer))
+     {
+        /* resize to the viewport size of a client.
+         * When the buffer size is bigger than the viewport size, the object is
+         * clipped by evas rendering mechanism even if we scale down the object
+         * with evas_map.
+         */
+        pw = cd->width_from_viewport;
+        ph = cd->height_from_viewport;
+     }
+#endif
+
    prev_w = cw->w, prev_h = cw->h;
    e_comp_object_frame_wh_adjust(obj, 0, 0, &fw, &fh);
    /* check shading and clamp to pixmap size for regular clients */
@@ -3749,6 +3767,9 @@ e_comp_object_dirty(Evas_Object *obj)
    Evas_Object *o;
    int w, h;
    Eina_Bool dirty, visible;
+#ifdef HAVE_WAYLAND_ONLY
+   E_Comp_Wl_Client_Data *cd;
+#endif
 
    API_ENTRY;
    /* only actually dirty if pixmap is available */
@@ -3783,6 +3804,16 @@ e_comp_object_dirty(Evas_Object *obj)
    it = eina_tiler_iterator_new(cw->updates);
    EINA_ITERATOR_FOREACH(it, rect)
      {
+#ifdef HAVE_WAYLAND_ONLY
+        cd = (E_Comp_Wl_Client_Data *)cw->ec->comp_data;
+        if (cd && cd->sub.data && (cd->width_from_viewport < cd->width_from_buffer))
+          {
+             Eina_Rectangle tr;
+             /* change to the buffer cordinate if subsurface */
+             e_comp_wl_surface_to_buffer_rect(cw->ec, rect, &tr);
+             rect = &tr;
+          }
+#endif
         RENDER_DEBUG("UPDATE ADD [%p]: %d %d %dx%d", cw->ec, rect->x, rect->y, rect->w, rect->h);
         evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
@@ -3817,6 +3848,9 @@ e_comp_object_render(Evas_Object *obj)
    int stride, pw, ph;
    unsigned int *pix, *srcpix;
    Eina_Bool ret = EINA_FALSE;
+#ifdef HAVE_WAYLAND_ONLY
+   E_Comp_Wl_Client_Data *cd;
+#endif
 
    API_ENTRY EINA_FALSE;
 
@@ -3886,6 +3920,16 @@ e_comp_object_render(Evas_Object *obj)
    srcpix = e_pixmap_image_data_get(cw->ec->pixmap);
    EINA_ITERATOR_FOREACH(it, r)
      {
+#ifdef HAVE_WAYLAND_ONLY
+        cd = (E_Comp_Wl_Client_Data *)cw->ec->comp_data;
+        if (cd && cd->sub.data && (cd->width_from_viewport < cd->width_from_buffer))
+          {
+             Eina_Rectangle tr;
+             /* change to the buffer cordinate if subsurface */
+             e_comp_wl_surface_to_buffer_rect(cw->ec, r, &tr);
+             r = &tr;
+          }
+#endif
         E_RECTS_CLIP_TO_RECT(r->x, r->y, r->w, r->h, 0, 0, pw, ph);
         ret = e_pixmap_image_draw(cw->ec->pixmap, r);
         if (!ret)
index 3e98974..31bf9df 100644 (file)
@@ -471,6 +471,93 @@ _e_comp_wl_map_transform(int width, int height, uint32_t transform, int32_t scal
 }
 
 static void
+_e_comp_wl_map_transform_rect(int width, int height,
+                              uint32_t transform, int32_t scale,
+                              Eina_Rectangle *srect, Eina_Rectangle *drect)
+{
+   int x1, x2, y1, y2;
+
+   x1 = srect->x;
+   y1 = srect->y;
+   x2 = srect->x + srect->w;
+   y2 = srect->y + srect->h;
+
+   _e_comp_wl_map_transform(width, height, transform, scale, x1, y1, &x1, &y1);
+   _e_comp_wl_map_transform(width, height, transform, scale, x2, y2, &x2, &y2);
+
+   drect->x = MIN(x1, x2);
+   drect->y = MIN(y1, y2);
+   drect->w = MAX(x1, x2) - drect->x;
+   drect->h = MAX(y1, y2) - drect->y;
+}
+
+static void
+_e_comp_wl_map_scaler_surface_to_buffer(E_Client *ec, int sx, int sy, int *bx, int *by)
+{
+   E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
+   double src_width, src_height;
+   double src_x, src_y;
+
+   if (vp->buffer.src_width == wl_fixed_from_int(-1))
+     {
+        if (vp->surface.width == -1)
+          {
+             *bx = sx;
+             *by = sy;
+             return;
+          }
+
+        src_x = 0.0;
+        src_y = 0.0;
+        src_width = ec->comp_data->width_from_buffer;
+        src_height = ec->comp_data->height_from_buffer;
+     }
+   else
+     {
+        src_x = wl_fixed_to_double(vp->buffer.src_x);
+        src_y = wl_fixed_to_double(vp->buffer.src_y);
+        src_width = wl_fixed_to_double(vp->buffer.src_width);
+        src_height = wl_fixed_to_double(vp->buffer.src_height);
+     }
+
+   *bx = sx * src_width / ec->comp_data->width_from_viewport + src_x;
+   *by = sy * src_height / ec->comp_data->height_from_viewport + src_y;
+}
+
+EAPI void
+e_comp_wl_surface_to_buffer_rect(E_Client *ec, Eina_Rectangle *srect, Eina_Rectangle *drect)
+{
+   E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
+   int xf1, yf1, xf2, yf2;
+
+   if (!ec->comp_data->sub.data)
+     {
+        *drect = *srect;
+        return;
+     }
+
+   /* first transform box coordinates if the scaler is set */
+
+   xf1 = srect->x;
+   yf1 = srect->y;
+   xf2 = srect->x + srect->w;
+   yf2 = srect->y + srect->h;
+
+   _e_comp_wl_map_scaler_surface_to_buffer(ec, xf1, yf1, &xf1, &yf1);
+   _e_comp_wl_map_scaler_surface_to_buffer(ec, xf2, yf2, &xf2, &yf2);
+
+   srect->x = MIN(xf1, xf2);
+   srect->y = MIN(yf1, yf2);
+   srect->w = MAX(xf1, xf2) - srect->x;
+   srect->h = MAX(yf1, yf2) - srect->y;
+
+   _e_comp_wl_map_transform_rect(ec->comp_data->width_from_buffer,
+                                 ec->comp_data->height_from_buffer,
+                                 vp->buffer.transform, vp->buffer.scale,
+                                 srect, drect);
+}
+
+static void
 _e_comp_wl_map_apply(E_Client *ec)
 {
    E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
@@ -1922,6 +2009,15 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
         if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.configure))
           ec->comp_data->shell.configure(ec->comp_data->shell.surface,
                                          x, y, ec->w, ec->h);
+        else if (ec->comp_data->sub.data &&
+                 (ec->comp_data->width_from_viewport < ec->comp_data->width_from_buffer))
+          /* resize to the viewport size of a client.
+           * When the buffer size is bigger than the viewport size, the object is
+           * clipped by evas rendering mechanism even if we scale down the object
+           * with evas_map.
+           */
+          e_client_util_move_resize_without_frame(ec, x, y, ec->comp_data->width_from_viewport,
+                                                  ec->comp_data->height_from_viewport);
         else
           {
              if (ec->netwm.sync.wait)
index 39b26c3..d83018a 100644 (file)
@@ -461,6 +461,7 @@ EINTERN Eina_Bool e_comp_wl_surface_commit(E_Client *ec);
 EINTERN Eina_Bool e_comp_wl_subsurface_commit(E_Client *ec);
 E_API void e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer);
 E_API E_Comp_Wl_Buffer *e_comp_wl_buffer_get(struct wl_resource *resource, E_Client *ec);
+E_API void e_comp_wl_surface_to_buffer_rect(E_Client *ec, Eina_Rectangle *srect, Eina_Rectangle *drect);
 
 E_API struct wl_signal e_comp_wl_surface_create_signal_get(void);
 E_API double e_comp_wl_idle_time_get(void);