Support floating keyboard 51/138451/6
authorInHong Han <inhong1.han@samsung.com>
Thu, 29 Jun 2017 05:48:36 +0000 (14:48 +0900)
committerJihoon Kim <jihoon48.kim@samsung.com>
Sat, 29 Jul 2017 02:50:52 +0000 (02:50 +0000)
Change-Id: I32409b63f3e101a54d158e2c19341471cbedccaf

src/e_mod_input_panel.c

index 9727dcf..3e8a65d 100644 (file)
@@ -7,6 +7,13 @@
 
 typedef struct _E_Input_Panel E_Input_Panel;
 typedef struct _E_Input_Panel_Surface E_Input_Panel_Surface;
+typedef struct _E_Input_Panel_Floating_Info E_Input_Panel_Floating_Info;
+
+typedef enum
+{
+   E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE,
+   E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL,
+} E_Input_Panel_Coordinate_Type;
 
 struct _E_Input_Panel
 {
@@ -38,15 +45,25 @@ struct _E_Input_Panel_Surface
    Eina_Bool need_show;
 };
 
-typedef struct _E_Floating_Position {
-   int portrait_x;
-   int portrait_y;
-   int landscape_x;
-   int landscape_y;
-} E_Floating_Position;
+struct _E_Input_Panel_Floating_Info
+{
+   Eina_Bool moving_req;
+   Eina_Bool init_portrait_position;
+   Eina_Bool init_landscape_position;
+   int before_canvas_x;
+   int before_canvas_y;
+
+   struct
+   {
+      int portrait_x;
+      int portrait_y;
+      int landscape_x;
+      int landscape_y;
+   } start_position;
+};
 
 E_Input_Panel *g_input_panel = NULL;
-E_Floating_Position g_floating_position = {-1, -1, -1, -1};
+E_Input_Panel_Floating_Info *g_floating_info = NULL;
 Eina_List *handlers = NULL;
 static Eina_Bool panel_show_need_rerun = EINA_FALSE;
 
@@ -180,15 +197,40 @@ static void
         return;
      }
 
-   if (ips->ec)
-     ips->ec->vkbd.floating = !!state;
+   if (!ips->ec) return;
+
+   if (ips->ec->vkbd.floating == state) return;
+
+   ips->ec->vkbd.floating = !!state;
+
+   if (ips->ec->vkbd.floating)
+     e_policy_conformant_part_del(ips->ec);
+   else
+     e_policy_conformant_part_add(ips->ec);
+}
+
+static void
+_e_input_panel_surface_cb_floating_drag_enabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t enabled)
+{
+   E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
+
+   if (!ips)
+     {
+        WTI_WARNING(resource,
+                    WL_DISPLAY_ERROR_INVALID_OBJECT,
+                    "No Input Panel Surface For Surface");
+        return;
+     }
+
+   g_floating_info->moving_req = !!enabled;
 }
 
 static const struct wl_input_panel_surface_interface _e_input_panel_surface_implementation = {
      _e_input_panel_surface_cb_toplevel_set,
      _e_input_panel_surface_cb_overlay_panel_set,
      _e_input_panel_surface_cb_ready_set,
-     _e_input_panel_surface_cb_floating_panel_set
+     _e_input_panel_surface_cb_floating_panel_set,
+     _e_input_panel_surface_cb_floating_drag_enabled_set
 };
 
 static void
@@ -238,12 +280,148 @@ _e_input_panel_surface_resource_destroy(struct wl_resource *resource)
 }
 
 static void
+_e_input_panel_init_floating_position(E_Client *ec)
+{
+   int zx, zy, zw, zh;
+
+   if (!ec || !g_floating_info) return;
+
+   e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
+
+   switch (ec->e.state.rot.ang.curr)
+     {
+        case 90:
+        case 270:
+           g_floating_info->start_position.landscape_x = (zh - ec->client.h) / 2;
+           g_floating_info->start_position.landscape_y = (zw - ec->client.w) / 2;
+           g_floating_info->init_landscape_position = EINA_TRUE;
+           break;
+        case 0:
+        case 180:
+        default:
+           g_floating_info->start_position.portrait_x = (zw - ec->client.w) / 2;
+           g_floating_info->start_position.portrait_y = (zh - ec->client.h) / 2;
+           g_floating_info->init_portrait_position = EINA_TRUE;
+           break;
+     }
+}
+
+static void
+_e_input_panel_stay_within_screen(E_Client *ec, int x, int y, int *new_x, int *new_y)
+{
+   int zx, zy, zw, zh;
+
+   if (!ec || !g_floating_info) return;
+
+   e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
+
+   switch (ec->e.state.rot.ang.curr)
+     {
+        case 90:
+        case 270:
+           if (x < 0)
+             *new_x = 0;
+           else if (x > zh - ec->client.h)
+             *new_x = zh - ec->client.h;
+           else
+             *new_x = x;
+
+           if (y < 0)
+             *new_y = 0;
+           else if (y > zw - ec->client.w)
+             *new_y = zw - ec->client.w;
+           else
+             *new_y = y;
+           break;
+        case 0:
+        case 180:
+        default:
+           if (x < 0)
+             *new_x = 0;
+           else if (x > zw - ec->client.w)
+             *new_x = zw - ec->client.w;
+           else
+             *new_x = x;
+
+           if (y < 0)
+             *new_y = 0;
+           else if (y > zh - ec->client.h)
+             *new_y = zh - ec->client.h;
+           else
+             *new_y = y;
+           break;
+     }
+}
+
+static void
+_e_input_panel_convert_floating_position(E_Client *ec, int x, int y, int *new_x, int *new_y, E_Input_Panel_Coordinate_Type cur_type)
+{
+   int zx, zy, zw, zh;
+   int cur_angle;
+
+   if (!ec || !g_floating_info) return;
+
+   cur_angle = ec->e.state.rot.ang.curr;
+   if ((!g_floating_info->init_portrait_position && (cur_angle == 0 || cur_angle == 180)) ||
+    (!g_floating_info->init_landscape_position && (cur_angle == 90 || cur_angle == 270)))
+     _e_input_panel_init_floating_position(ec);
+
+   e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
+
+   switch (cur_angle)
+     {
+        case 90:
+           if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
+             {
+                *new_x = zh - y - ec->client.h;
+                *new_y = x;
+             }
+           else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
+             {
+                *new_x = y;
+                *new_y = zh - x - ec->client.h;
+             }
+           break;
+        case 180:
+           if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
+             {
+                *new_x = zh - y - ec->client.h;
+                *new_y = zw - x - ec->client.w;
+             }
+           else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
+             {
+                *new_x = zw - x - ec->client.w;
+                *new_y = zh - y - ec->client.h;
+             }
+           break;
+        case 270:
+           if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
+             {
+                *new_x = y;
+                *new_y = zw - x - ec->client.w;
+             }
+           else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
+             {
+                *new_x = zw - y - ec->client.w;
+                *new_y = x;
+             }
+           break;
+        case 0:
+        default:
+           *new_x = x;
+           *new_y = y;
+           break;
+     }
+}
+
+static void
 _e_input_panel_position_set(E_Client *ec, int w, int h)
 {
    int nx, ny;
    int zx, zy, zw, zh;
+   Eina_Bool is_portrait;
 
-   if (!ec) return;
+   if (!ec || !g_floating_info) return;
 
    e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
 
@@ -253,24 +431,41 @@ _e_input_panel_position_set(E_Client *ec, int w, int h)
         case 90:
            nx = zx + zw - w;
            ny = zy + (zh - h) / 2;
+           is_portrait = EINA_FALSE;
            break;
         case 180:
            nx = zx + (zw - w) / 2;
            ny = zy;
+           is_portrait = EINA_TRUE;
            break;
         case 270:
            nx = zx;
            ny = zy + (zh - h) / 2;
+           is_portrait = EINA_FALSE;
            break;
         case 0:
         default:
            nx = zx + (zw - w) / 2;
            ny = zy + zh - h;
+           is_portrait = EINA_TRUE;
            break;
      }
 
-   if (!ec->vkbd.floating)
-     e_client_util_move_without_frame(ec, nx, ny);
+   if (ec->vkbd.floating)
+     {
+        int sx, sy;
+        if ((is_portrait && !g_floating_info->init_portrait_position) || (!is_portrait && !g_floating_info->init_landscape_position))
+          _e_input_panel_init_floating_position(ec);
+
+        if (is_portrait)
+          _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.portrait_x, g_floating_info->start_position.portrait_y, &sx, &sy);
+        else
+          _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.landscape_x, g_floating_info->start_position.landscape_y, &sx, &sy);
+
+        _e_input_panel_convert_floating_position(ec, sx, sy, &nx, &ny, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
+     }
+
+   e_client_util_move_without_frame(ec, nx, ny);
 }
 
 static void
@@ -464,6 +659,74 @@ _e_ips_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *e
 }
 
 static void
+_e_ips_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Client *ec;
+
+   ec = data;
+   if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
+     return;
+
+   g_floating_info->moving_req = EINA_FALSE;
+}
+
+static void
+_e_ips_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   E_Client *ec;
+   Evas_Event_Mouse_Move *ev = event_info;
+
+   ec = data;
+   if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
+     return;
+
+   g_floating_info->before_canvas_x = ev->cur.canvas.x;
+   g_floating_info->before_canvas_y = ev->cur.canvas.y;
+}
+
+static void
+_e_ips_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
+{
+   E_Client *ec;
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Coord x, y, w, h;
+   int b_x = 0, b_y = 0, n_x = 0, n_y = 0;
+   int d_x, d_y;
+
+   ec = data;
+   if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
+     return;
+
+   if (!g_floating_info->moving_req)
+     return;
+
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+
+   d_x = x + (ev->cur.canvas.x - g_floating_info->before_canvas_x);
+   d_y = y + (ev->cur.canvas.y - g_floating_info->before_canvas_y);
+
+   _e_input_panel_convert_floating_position(ec, d_x, d_y, &b_x, &b_y, E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE);
+   _e_input_panel_stay_within_screen(ec, b_x, b_y, &n_x, &n_y);
+
+   g_floating_info->before_canvas_x = ev->cur.canvas.x;
+   g_floating_info->before_canvas_y = ev->cur.canvas.y;
+
+   if (ec->e.state.rot.ang.curr == 90 || ec->e.state.rot.ang.curr == 270)
+     {
+        g_floating_info->start_position.landscape_x = n_x;
+        g_floating_info->start_position.landscape_y = n_y;
+     }
+   else
+     {
+        g_floating_info->start_position.portrait_x = n_x;
+        g_floating_info->start_position.portrait_y = n_y;
+     }
+
+   _e_input_panel_convert_floating_position(ec, n_x, n_y, &d_x, &d_y, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
+   evas_object_move(obj, d_x, d_y);
+}
+
+static void
 _e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
 {
    E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
@@ -538,6 +801,9 @@ _e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *reso
    evas_object_raise(ec->frame);
 
    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE, _e_ips_cb_evas_resize, ec);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_UP, _e_ips_cb_mouse_up, ec);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_DOWN, _e_ips_cb_mouse_down, ec);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_MOVE, _e_ips_cb_mouse_move, ec);
 
    cdata->surface = surface_resource;
    cdata->shell.configure_send = NULL;
@@ -774,6 +1040,7 @@ e_input_panel_init(void)
      }
 
    g_input_panel->idle_enter = ecore_idle_enterer_add(_e_input_panel_idle_enter, NULL);
+   g_floating_info = E_NEW(E_Input_Panel_Floating_Info, 1);
 
    return EINA_TRUE;
 }
@@ -797,6 +1064,9 @@ e_input_panel_shutdown(void)
 
          E_FREE_FUNC(g_input_panel->idle_enter, ecore_idle_enterer_del);
       }
+
+    if (g_floating_info)
+      E_FREE(g_floating_info);
 }
 
 static void
@@ -943,21 +1213,22 @@ e_input_panel_show_need_rerun_set(Eina_Bool need_rerun)
 void
 e_input_panel_floating_position_set(E_Client *ec, int x, int y)
 {
-   if (!ec) return;
+   if (!ec || !g_floating_info) return;
 
    switch (ec->e.state.rot.ang.curr)
      {
-        case 0:
-        case 180:
-           g_floating_position.portrait_x = x;
-           g_floating_position.portrait_y = y;
-           break;
         case 90:
         case 270:
-           g_floating_position.landscape_x = x;
-           g_floating_position.landscape_y = y;
+           g_floating_info->start_position.landscape_x = x;
+           g_floating_info->start_position.landscape_y = y;
+           g_floating_info->init_landscape_position = EINA_TRUE;
            break;
+        case 0:
+        case 180:
         default:
+           g_floating_info->start_position.portrait_x = x;
+           g_floating_info->start_position.portrait_y = y;
+           g_floating_info->init_portrait_position = EINA_TRUE;
            break;
      }
-}
\ No newline at end of file
+}