[elm_win] added the window manager rotation feature and a sample
authorGwanglim Lee <gl77.lee@samsung.com>
Tue, 19 Mar 2013 17:57:31 +0000 (02:57 +0900)
committerSungho Kwak <sungho1.kwak@samsung.com>
Thu, 21 Mar 2013 08:14:46 +0000 (17:14 +0900)
Change-Id: Ia282f3286bd63aa5a2d27bd4b89948f0fbf80c11

src/bin/Makefile.am
src/bin/test.c
src/bin/test_win_wm_rotation.c [new file with mode: 0644]
src/lib/elm_win.c
src/lib/elm_win.h

index 0488927..9b7cb16 100644 (file)
@@ -123,6 +123,7 @@ test_win_inline.c \
 test_win_socket.c \
 test_win_plug.c \
 test_win_state.c \
+test_win_wm_rotation.c \
 test.h
 
 if HAVE_EIO
index 36a0003..b83438d 100644 (file)
@@ -172,6 +172,7 @@ void test_store(void *data, Evas_Object *obj, void *event_info);
 void test_win_inline(void *data, Evas_Object *obj, void *event_info);
 void test_win_socket(void *data, Evas_Object *obj, void *event_info);
 void test_win_plug(void *data, Evas_Object *obj, void *event_info);
+void test_win_wm_rotation(void *data, Evas_Object *obj, void *event_info);
 void test_grid(void *data, Evas_Object *obj, void *event_info);
 void test_glview_simple(void *data, Evas_Object *obj, void *event_info);
 void test_glview(void *data, Evas_Object *obj, void *event_info);
@@ -467,6 +468,7 @@ add_tests:
    ADD_TEST(NULL, "Window / Background", "Window Inline", test_win_inline);
    ADD_TEST(NULL, "Window / Background", "Window Socket", test_win_socket);
    ADD_TEST(NULL, "Window / Background", "Window Plug", test_win_plug);
+   ADD_TEST(NULL, "Window / Background", "Window WM Rotation", test_win_wm_rotation);
 
    //------------------------------//
    ADD_TEST(NULL, "Images", "Icon", test_icon);
diff --git a/src/bin/test_win_wm_rotation.c b/src/bin/test_win_wm_rotation.c
new file mode 100644 (file)
index 0000000..d518384
--- /dev/null
@@ -0,0 +1,217 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+#ifndef ELM_LIB_QUICKLAUNCH
+
+typedef struct _App_Data App_Data;
+
+struct _App_Data
+{
+   Eina_Bool    wm_rot_supported;
+   Eina_List   *chs;
+   int          available_rots[4];
+   unsigned int count;
+   Evas_Object *lb;
+   Evas_Object *rdg;
+};
+
+static void
+_bt_available_rots_set(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = (Evas_Object *)(data);
+   App_Data *ad = evas_object_data_get(win, "ad");
+   Evas_Object *o;
+   Eina_List *l;
+   const char *str;
+   unsigned int i = 0;
+
+   if (!ad->wm_rot_supported) return;
+
+   EINA_LIST_FOREACH(ad->chs, l, o)
+     {
+        if (!elm_check_state_get(o)) continue;
+        str = elm_object_text_get(o);
+        if (!str) continue;
+        ad->available_rots[i] = atoi(str);
+        i++;
+     }
+
+   ad->count = i;
+
+   elm_win_wm_rotation_available_rotations_set
+     (win, ad->available_rots, ad->count);
+}
+
+static void
+_bt_preferred_rot_set(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win = (Evas_Object *)(data);
+   App_Data *ad = evas_object_data_get(win, "ad");
+
+   if (!ad->wm_rot_supported) return;
+
+   Evas_Object *rd = elm_radio_selected_object_get(ad->rdg);
+   if (rd)
+     {
+        const char *str = elm_object_text_get(rd);
+        int rot = 0;
+
+        if (!strcmp(str, "Unset"))
+          rot = -1;
+        else
+          rot = atoi(str);
+
+        elm_win_wm_rotation_preferred_rotation_set(win, rot);
+     }
+}
+
+static void
+_win_wm_rotation_changed_cb(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
+{
+   Evas_Object *win = (Evas_Object *)(data);
+   App_Data *ad = evas_object_data_get(win, "ad");
+   int rot = elm_win_rotation_get(win);
+   char buf[32];
+
+   if (!ad->wm_rot_supported) return;
+
+   eina_convert_itoa(rot, buf);
+   elm_object_text_set(ad->lb, eina_stringshare_add(buf));
+}
+
+static void
+_win_del_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   App_Data *ad = evas_object_data_get(obj, "ad");
+   Evas_Object *o;
+
+   if (ad->wm_rot_supported)
+     {
+        EINA_LIST_FREE(ad->chs, o)
+          evas_object_data_del(o, "rotation");
+     }
+
+   free(ad);
+}
+
+void
+test_win_wm_rotation(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   App_Data *ad;
+   Evas_Object *win, *bx, *bx2, *lb, *ch, *bt, *en, *rd, *rdg = NULL;
+   int i;
+   char buf[32];
+
+   if (!(ad = calloc(1, sizeof(App_Data)))) return;
+
+   win = elm_win_util_standard_add("wmrotation", "WMRotation");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_data_set(win, "ad", ad);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+
+   lb = elm_label_add(win);
+   elm_object_text_set(lb, "<b>Window manager rotation test</b>");
+   evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+
+   ad->wm_rot_supported = elm_win_wm_rotation_supported_get(win);
+   if (ad->wm_rot_supported)
+     {
+        int rots[] = { 0, 90, 270 };
+        elm_win_wm_rotation_available_rotations_set(win, rots, (sizeof(rots) / sizeof(int)));
+        elm_win_wm_rotation_preferred_rotation_set(win, 90);
+
+        bx2 = elm_box_add(win);
+        evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+        evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, 0.0);
+        elm_box_align_set(bx2, 0.0, 0.5);
+        elm_box_horizontal_set(bx2, EINA_TRUE);
+        elm_box_pack_end(bx, bx2);
+        evas_object_show(bx2);
+
+        for (i = 0; i < 4; i++)
+          {
+             ch = elm_check_add(win);
+             eina_convert_itoa((i * 90), buf);
+             elm_object_text_set(ch, eina_stringshare_add(buf));
+             evas_object_size_hint_weight_set(ch, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             elm_box_pack_end(bx2, ch);
+             evas_object_show(ch);
+
+             if (i != 2) elm_check_state_set(ch, 1);
+
+             ad->chs = eina_list_append(ad->chs, ch);
+          }
+
+        bt = elm_button_add(win);
+        elm_object_text_set(bt, "Available rotations");
+        evas_object_smart_callback_add(bt, "clicked", _bt_available_rots_set, win);
+        elm_box_pack_end(bx, bt);
+        evas_object_show(bt);
+
+        bx2 = elm_box_add(win);
+        evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, 0.0);
+        evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, 0.0);
+        elm_box_align_set(bx2, 0.0, 0.5);
+        elm_box_horizontal_set(bx2, EINA_TRUE);
+        elm_box_pack_end(bx, bx2);
+        evas_object_show(bx2);
+
+        for (i = 0; i < 5; i++)
+          {
+             rd = elm_radio_add(win);
+             if (!rdg) rdg = rd;
+             elm_radio_state_value_set(rd, i);
+             elm_radio_group_add(rd, rdg);
+
+             if (i == 0)
+               elm_object_text_set(rd, "Unset");
+             else
+               {
+                  eina_convert_itoa(((i - 1) * 90), buf);
+                  elm_object_text_set(rd, eina_stringshare_add(buf));
+               }
+
+             evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             elm_box_pack_end(bx2, rd);
+             evas_object_show(rd);
+          }
+
+        elm_radio_value_set(rdg, 2);
+        ad->rdg = rdg;
+
+        bt = elm_button_add(win);
+        elm_object_text_set(bt, "Preferred rotation");
+        evas_object_smart_callback_add(bt, "clicked", _bt_preferred_rot_set, win);
+        elm_box_pack_end(bx, bt);
+        evas_object_show(bt);
+
+        evas_object_smart_callback_add(win, "wm,rotation,changed", _win_wm_rotation_changed_cb, win);
+     }
+
+   en = elm_entry_add(win);
+   elm_entry_single_line_set(en, EINA_TRUE);
+   evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, en);
+   evas_object_show(en);
+
+   lb = elm_label_add(win);
+   elm_object_text_set(lb, "N/A");
+   evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_box_pack_end(bx, lb);
+   evas_object_show(lb);
+   ad->lb = lb;
+
+   evas_object_smart_callback_add(win, "delete,request", _win_del_cb, NULL);
+
+   evas_object_resize(win, 480, 400);
+   evas_object_show(bx);
+   evas_object_show(win);
+}
+#endif
index f4a35da..1d4ae1d 100755 (executable)
@@ -128,6 +128,14 @@ struct _Elm_Win_Smart_Data
       Ecore_Timer *timer;
       Eina_List   *names;
    } profile;
+   struct
+   {
+      int          preferred_rot; // specified by app
+      int         *rots;          // available rotations
+      unsigned int count;         // number of elements in available rotations
+      Eina_Bool    wm_supported : 1;
+      Eina_Bool    use : 1;
+   } wm_rot;
 
    Evas_Object *icon;
    const char  *title;
@@ -172,6 +180,7 @@ static const char SIG_IOERR[] = "ioerr";
 static const char SIG_INDICATOR_PROP_CHANGED[] = "indicator,prop,changed";
 static const char SIG_ROTATION_CHANGED[] = "rotation,changed";
 static const char SIG_PROFILE_CHANGED[] = "profile,changed";
+static const char SIG_WM_ROTATION_CHANGED[] = "wm,rotation,changed";
 
 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
    {SIG_DELETE_REQUEST, ""},
@@ -191,6 +200,7 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
    {SIG_INDICATOR_PROP_CHANGED, ""},
    {SIG_ROTATION_CHANGED, ""},
    {SIG_PROFILE_CHANGED, ""},
+   {SIG_WM_ROTATION_CHANGED, ""},
    {NULL, NULL}
 };
 
@@ -207,6 +217,8 @@ static Eina_Bool _elm_win_auto_throttled = EINA_FALSE;
 
 static Ecore_Job *_elm_win_state_eval_job = NULL;
 
+static void _elm_win_resize_objects_eval(Evas_Object *obj);
+
 static void
 _elm_win_obj_intercept_show(void *data, Evas_Object *obj)
 {
@@ -946,6 +958,7 @@ _elm_win_state_change(Ecore_Evas *ee)
    Eina_Bool ch_fullscreen = EINA_FALSE;
    Eina_Bool ch_maximized = EINA_FALSE;
    Eina_Bool ch_profile = EINA_FALSE;
+   Eina_Bool ch_wm_rotation = EINA_FALSE;
    const char *profile;
 
    EINA_SAFETY_ON_NULL_RETURN(sd);
@@ -995,6 +1008,14 @@ _elm_win_state_change(Ecore_Evas *ee)
              ch_profile = EINA_TRUE;
           }
      }
+   if (sd->wm_rot.use)
+     {
+        if (sd->rot != ecore_evas_rotation_get(sd->ee))
+          {
+             sd->rot = ecore_evas_rotation_get(sd->ee);
+             ch_wm_rotation = EINA_TRUE;
+          }
+     }
 
    _elm_win_state_eval_queue();
 
@@ -1032,6 +1053,15 @@ _elm_win_state_change(Ecore_Evas *ee)
      {
         _elm_win_profile_update(ee);
      }
+   if (ch_wm_rotation)
+     {
+        evas_object_size_hint_min_set(obj, -1, -1);
+        evas_object_size_hint_max_set(obj, -1, -1);
+        _elm_win_resize_objects_eval(obj);
+        elm_widget_orientation_set(obj, sd->rot);
+
+        evas_object_smart_callback_call(obj, SIG_WM_ROTATION_CHANGED, NULL);
+     }
 }
 
 static Eina_Bool
@@ -1549,6 +1579,9 @@ _elm_win_smart_del(Evas_Object *obj)
    if (sd->profile.name) eina_stringshare_del(sd->profile.name);
    if (sd->profile.timer) ecore_timer_del(sd->profile.timer);
 
+   if (sd->wm_rot.rots) free(sd->wm_rot.rots);
+   sd->wm_rot.rots = NULL;
+
    /* Don't let callback in the air that point to sd */
    ecore_evas_callback_delete_request_set(sd->ee, NULL);
    ecore_evas_callback_resize_set(sd->ee, NULL);
@@ -2920,6 +2953,9 @@ elm_win_add(Evas_Object *parent,
         // do nothing
      }
 
+   sd->wm_rot.wm_supported = ecore_evas_wm_rotation_supported_get(sd->ee);
+   sd->wm_rot.preferred_rot = -1; // it means that elm_win doesn't use preferred rotation.
+
    return obj;
 }
 
@@ -3723,6 +3759,114 @@ elm_win_rotation_get(const Evas_Object *obj)
    return sd->rot;
 }
 
+EAPI Eina_Bool
+elm_win_wm_rotation_supported_get(const Evas_Object *obj)
+{
+   ELM_WIN_CHECK(obj) EINA_FALSE;
+   ELM_WIN_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
+   return sd->wm_rot.wm_supported;
+}
+
+/* This will unset a preferred rotation, if given preferred rotation is '-1'.
+ */
+EAPI void
+elm_win_wm_rotation_preferred_rotation_set(Evas_Object *obj,
+                                           const int rotation)
+{
+   int rot;
+
+   ELM_WIN_CHECK(obj);
+   ELM_WIN_DATA_GET_OR_RETURN(obj, sd);
+
+   if (!sd->wm_rot.use)
+     sd->wm_rot.use = EINA_TRUE;
+
+   // '-1' means that elm_win doesn't use preferred rotation.
+   if (rotation == -1)
+     rot = -1;
+   else
+     rot = _win_rotation_degree_check(rotation);
+
+   if (sd->wm_rot.preferred_rot == rot) return;
+   sd->wm_rot.preferred_rot = rot;
+
+   ecore_evas_wm_rotation_preferred_rotation_set(sd->ee, rot);
+}
+
+EAPI int
+elm_win_wm_rotation_preferred_rotation_get(const Evas_Object *obj)
+{
+   ELM_WIN_CHECK(obj) -1;
+   ELM_WIN_DATA_GET_OR_RETURN_VAL(obj, sd, -1);
+   if (!sd->wm_rot.use) return -1;
+   return sd->wm_rot.preferred_rot;
+}
+
+EAPI void
+elm_win_wm_rotation_available_rotations_set(Evas_Object *obj,
+                                            const int   *rotations,
+                                            unsigned int count)
+{
+   unsigned int i;
+   int r;
+
+   ELM_WIN_CHECK(obj);
+   ELM_WIN_DATA_GET_OR_RETURN(obj, sd);
+
+   if (!sd->wm_rot.use)
+     sd->wm_rot.use = EINA_TRUE;
+
+   if (sd->wm_rot.rots) free(sd->wm_rot.rots);
+
+   sd->wm_rot.rots = NULL;
+   sd->wm_rot.count = 0;
+
+   if (count > 0)
+     {
+        sd->wm_rot.rots = calloc(count, sizeof(int));
+        if (!sd->wm_rot.rots) return;
+        for (i = 0; i < count; i++)
+          {
+             r = _win_rotation_degree_check(rotations[i]);
+             sd->wm_rot.rots[i] = r;
+          }
+     }
+
+   sd->wm_rot.count = count;
+
+   ecore_evas_wm_rotation_available_rotations_set(sd->ee,
+                                                  sd->wm_rot.rots,
+                                                  sd->wm_rot.count);
+}
+
+EAPI Eina_Bool
+elm_win_wm_rotation_available_rotations_get(const Evas_Object *obj,
+                                            int              **rotations,
+                                            unsigned int      *count)
+{
+   ELM_WIN_CHECK(obj) EINA_FALSE;
+   ELM_WIN_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
+   if (!sd->wm_rot.use) return EINA_FALSE;
+
+   if (sd->wm_rot.count > 0)
+     {
+        if ((rotations) && (*rotations))
+          {
+             *rotations = calloc(sd->wm_rot.count, sizeof(int));
+             if (*rotations)
+               {
+                  memcpy(*rotations,
+                         sd->wm_rot.rots,
+                         sizeof(int) * sd->wm_rot.count);
+               }
+          }
+     }
+
+   if (count) *count = sd->wm_rot.count;
+
+   return EINA_TRUE;
+}
+
 EAPI void
 elm_win_sticky_set(Evas_Object *obj,
                    Eina_Bool sticky)
index 45ab03e..299e122 100644 (file)
@@ -82,6 +82,7 @@
  * @li "unfullscreen": window has stopped being fullscreen
  * @li "maximized": window has been maximized
  * @li "unmaximized": window has stopped being maximized
+ * @li "wm,rotation,changed": rotation of window has been changed by window manager
  * @li "ioerr": there has been a low-level I/O error with the display system
  *
  * Examples:
@@ -1562,6 +1563,12 @@ EAPI void                  elm_win_floating_mode_set(Evas_Object *obj, Eina_Bool
  */
 EAPI Eina_Bool             elm_win_floating_mode_get(const Evas_Object *obj);
 
+EAPI Eina_Bool             elm_win_wm_rotation_supported_get(const Evas_Object *obj);
+EAPI void                  elm_win_wm_rotation_preferred_rotation_set(Evas_Object *obj, const int rotation);
+EAPI int                   elm_win_wm_rotation_preferred_rotation_get(const Evas_Object *obj);
+EAPI void                  elm_win_wm_rotation_available_rotations_set(Evas_Object *obj, const int *rotations, unsigned int count);
+EAPI Eina_Bool             elm_win_wm_rotation_available_rotations_get(const Evas_Object *obj, int **rotations, unsigned int *count);
+
 /**
  * @}
  */