ecore-evas-wl: Add support for Window Manager rotations
authorChris Michael <cp.michael@samsung.com>
Fri, 9 Jun 2017 15:06:05 +0000 (11:06 -0400)
committerChris Michael <cp.michael@samsung.com>
Fri, 9 Jun 2017 16:30:42 +0000 (12:30 -0400)
This patch adds support to Ecore_Evas_Wayland for Window Manager
Rotations so that window managers which do support rotations are able
to rotate an EFL wayland application.

@feature

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h

index 30ddb30..362aef9 100644 (file)
@@ -28,9 +28,10 @@ struct _EE_Wl_Device
 
 /* local variables */
 static int _ecore_evas_wl_init_count = 0;
-static Ecore_Event_Handler *_ecore_evas_wl_event_hdls[13];
+static Ecore_Event_Handler *_ecore_evas_wl_event_hdls[14];
 
 static void _ecore_evas_wayland_resize(Ecore_Evas *ee, int location);
+static void _ecore_evas_wl_common_rotation_set(Ecore_Evas *ee, int rotation, int resize);
 
 /* local functions */
 static void
@@ -39,6 +40,17 @@ _ecore_evas_wl_common_state_update(Ecore_Evas *ee)
    if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
 }
 
+static void
+_ecore_evas_wl_common_wm_rotation_protocol_set(Ecore_Evas *ee)
+{
+   Ecore_Evas_Engine_Wl_Data *wdata;
+
+   wdata = ee->engine.data;
+
+   ee->prop.wm_rot.supported =
+     ecore_wl2_window_wm_rotation_supported_get(wdata->win);
+}
+
 static Eina_Bool
 _ecore_evas_wl_common_cb_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
@@ -344,6 +356,69 @@ _ecore_evas_wl_common_resize(Ecore_Evas *ee, int w, int h)
      }
 }
 
+static void
+_ecore_evas_wl_common_wm_rot_manual_rotation_done_job(void *data)
+{
+   Ecore_Evas *ee = (Ecore_Evas *)data;
+   Ecore_Evas_Engine_Wl_Data *wdata;
+
+   wdata = ee->engine.data;
+
+   wdata->wm_rot.manual_mode_job = NULL;
+   ee->prop.wm_rot.manual_mode.wait_for_done = EINA_FALSE;
+
+   ecore_wl2_window_rotation_change_done_send
+     (wdata->win, ee->rotation, ee->w, ee->h);
+
+   wdata->wm_rot.done = EINA_FALSE;
+}
+
+static void
+_ecore_evas_wl_common_wm_rot_manual_rotation_done(Ecore_Evas *ee)
+{
+   if ((ee->prop.wm_rot.supported) &&
+       (ee->prop.wm_rot.app_set) &&
+       (ee->prop.wm_rot.manual_mode.set))
+     {
+        if (ee->prop.wm_rot.manual_mode.wait_for_done)
+          {
+             Ecore_Evas_Engine_Wl_Data *wdata;
+
+             wdata = ee->engine.data;
+
+             if (ee->prop.wm_rot.manual_mode.timer)
+               ecore_timer_del(ee->prop.wm_rot.manual_mode.timer);
+             ee->prop.wm_rot.manual_mode.timer = NULL;
+
+             if (wdata->wm_rot.manual_mode_job)
+               ecore_job_del(wdata->wm_rot.manual_mode_job);
+
+             wdata->wm_rot.manual_mode_job = ecore_job_add
+               (_ecore_evas_wl_common_wm_rot_manual_rotation_done_job, ee);
+          }
+     }
+}
+
+static Eina_Bool
+_ecore_evas_wl_common_wm_rot_manual_rotation_done_timeout(void *data)
+{
+   Ecore_Evas *ee = data;
+
+   ee->prop.wm_rot.manual_mode.timer = NULL;
+   _ecore_evas_wl_common_wm_rot_manual_rotation_done(ee);
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_ecore_evas_wl_common_wm_rot_manual_rotation_done_timeout_update(Ecore_Evas *ee)
+{
+   if (ee->prop.wm_rot.manual_mode.timer)
+     ecore_timer_del(ee->prop.wm_rot.manual_mode.timer);
+
+   ee->prop.wm_rot.manual_mode.timer = ecore_timer_add
+     (4.0f, _ecore_evas_wl_common_wm_rot_manual_rotation_done_timeout, ee);
+}
+
 static Eina_Bool
 _ecore_evas_wl_common_cb_window_configure(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
@@ -411,6 +486,38 @@ _ecore_evas_wl_common_cb_window_configure(void *data EINA_UNUSED, int type EINA_
    if (ee->prop.fullscreen || (ee->req.w != nw) || (ee->req.h != nh))
      _ecore_evas_wl_common_resize(ee, nw, nh);
 
+   if (ee->prop.wm_rot.supported)
+     {
+        if (wdata->wm_rot.prepare)
+          {
+             if ((ee->prop.wm_rot.w == nw) &&
+                 (ee->prop.wm_rot.h == nh))
+               {
+                  ee->prop.wm_rot.win_resize = EINA_FALSE;
+                  wdata->wm_rot.configure_coming = EINA_FALSE;
+               }
+          }
+        else if (wdata->wm_rot.request)
+          {
+             if ((wdata->wm_rot.configure_coming) &&
+                 (ee->prop.wm_rot.w == nw) &&
+                 (ee->prop.wm_rot.h == nh))
+               {
+                  wdata->wm_rot.configure_coming = EINA_FALSE;
+
+                  if (ee->prop.wm_rot.manual_mode.set)
+                    {
+                       ee->prop.wm_rot.manual_mode.wait_for_done = EINA_TRUE;
+                       _ecore_evas_wl_common_wm_rot_manual_rotation_done_timeout_update(ee);
+                    }
+
+                  _ecore_evas_wl_common_rotation_set(ee,
+                                                     ee->prop.wm_rot.angle,
+                                                     EINA_TRUE);
+               }
+          }
+     }
+
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -439,6 +546,22 @@ _ecore_evas_wl_common_cb_window_configure_complete(void *data EINA_UNUSED, int t
    return ECORE_CALLBACK_PASS_ON;
 }
 
+static Eina_Bool
+_ecore_evas_wl_common_cb_window_rotate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   Ecore_Evas *ee;
+   Ecore_Wl2_Event_Window_Rotation *ev;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   ev = event;
+   ee = ecore_event_window_match(ev->win);
+   if (!ee) return ECORE_CALLBACK_PASS_ON;
+   if (ev->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+   _ecore_evas_wl_common_rotation_set(ee, ev->rotation, ev->resize);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
 static void
 _mouse_move_dispatch(Ecore_Evas *ee)
 {
@@ -957,6 +1080,9 @@ _ecore_evas_wl_common_init(void)
      ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_CONFIGURE_COMPLETE,
                              _ecore_evas_wl_common_cb_window_configure_complete,
                              NULL);
+   _ecore_evas_wl_event_hdls[13] =
+     ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_ROTATE,
+                             _ecore_evas_wl_common_cb_window_rotate, NULL);
 
    ecore_event_evas_init();
 
@@ -1109,6 +1235,67 @@ _ecore_evas_wl_common_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_C
 }
 
 static void
+_ecore_evas_wl_common_wm_rot_preferred_rotation_set(Ecore_Evas *ee, int rot)
+{
+   if (ee->prop.wm_rot.supported)
+     {
+        Ecore_Evas_Engine_Wl_Data *wdata;
+
+        wdata = ee->engine.data;
+        if (!ee->prop.wm_rot.app_set)
+          {
+             ecore_wl2_window_rotation_app_set(wdata->win, EINA_TRUE);
+             ee->prop.wm_rot.app_set = EINA_TRUE;
+          }
+
+        ecore_wl2_window_preferred_rotation_set(wdata->win, rot);
+        ee->prop.wm_rot.preferred_rot = rot;
+     }
+}
+
+static void
+_ecore_evas_wl_common_wm_rot_available_rotations_set(Ecore_Evas *ee, const int *rots, unsigned int count)
+{
+   if (ee->prop.wm_rot.supported)
+     {
+        Ecore_Evas_Engine_Wl_Data *wdata;
+
+        wdata = ee->engine.data;
+        if (!ee->prop.wm_rot.app_set)
+          {
+             ecore_wl2_window_rotation_app_set(wdata->win, EINA_TRUE);
+             ee->prop.wm_rot.app_set = EINA_TRUE;
+          }
+
+        if (ee->prop.wm_rot.available_rots)
+          {
+             free(ee->prop.wm_rot.available_rots);
+             ee->prop.wm_rot.available_rots = NULL;
+          }
+
+        ee->prop.wm_rot.count = 0;
+
+        if (count > 0)
+          {
+             ee->prop.wm_rot.available_rots = calloc(count, sizeof(int));
+             if (!ee->prop.wm_rot.available_rots) return;
+
+             memcpy(ee->prop.wm_rot.available_rots, rots, sizeof(int) * count);
+          }
+
+        ee->prop.wm_rot.count = count;
+
+        ecore_wl2_window_available_rotations_set(wdata->win, rots, count);
+     }
+}
+
+static void
+_ecore_evas_wl_common_wm_rot_manual_rotation_done_set(Ecore_Evas *ee, Eina_Bool set)
+{
+   ee->prop.wm_rot.manual_mode.set = set;
+}
+
+static void
 _ecore_evas_wl_common_pointer_device_xy_get(const Ecore_Evas *ee, const Efl_Input_Device *pointer, Evas_Coord *x, Evas_Coord *y)
 {
    Ecore_Evas_Engine_Wl_Data *wdata;
@@ -1433,6 +1620,8 @@ _ecore_evas_wayland_alpha_do(Ecore_Evas *ee, int alpha)
 
    if (wdata->win) ecore_wl2_window_alpha_set(wdata->win, ee->alpha);
 
+   _ecore_evas_wl_common_wm_rotation_protocol_set(ee);
+
    evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh);
 
    if ((einfo = (Evas_Engine_Info_Wayland *)evas_engine_info_get(ee->evas)))
@@ -1960,10 +2149,10 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
    _ecore_evas_wl_common_pointer_xy_get,
    NULL, // pointer_warp
 
-   NULL, // wm_rot_preferred_rotation_set
-   NULL, // wm_rot_available_rotations_set
-   NULL, // wm_rot_manual_rotation_done_set
-   NULL, // wm_rot_manual_rotation_done
+   _ecore_evas_wl_common_wm_rot_preferred_rotation_set,
+   _ecore_evas_wl_common_wm_rot_available_rotations_set,
+   _ecore_evas_wl_common_wm_rot_manual_rotation_done_set,
+   _ecore_evas_wl_common_wm_rot_manual_rotation_done,
 
    NULL, // aux_hints_set
 
@@ -2126,6 +2315,8 @@ _ecore_evas_wl_common_new_internal(const char *disp_name, unsigned int parent, i
         goto eng_err;
      }
 
+   _ecore_evas_wl_common_wm_rotation_protocol_set(ee);
+
    _ecore_evas_register(ee);
    ecore_evas_input_event_register(ee);
 
index aed693b..e6e3f3e 100644 (file)
@@ -46,6 +46,17 @@ struct _Ecore_Evas_Engine_Wl_Data
    int y_rel;
    uint32_t timestamp;
    Eina_List *devices_list;
+
+   struct
+     {
+        Eina_Bool supported : 1;
+        Eina_Bool prepare : 1;
+        Eina_Bool request : 1;
+        Eina_Bool done : 1;
+        Eina_Bool configure_coming : 1;
+        Ecore_Job *manual_mode_job;
+     } wm_rot;
+
    Eina_Bool dragging : 1;
    Eina_Bool sync_done : 1;
    Eina_Bool defer_show : 1;