discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=48a718108913f0ae0f8a06ee9a0057bea87cdbe8

commit 48a718108913f0ae0f8a06ee9a0057bea87cdbe8
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Fri Jul 21 16:20:03 2017 -0400

    add a configurable default policy (default: extend) for screen hotplugging
    
    make an effort to "just work" instead of the classic enlightenment ux of 
being
    as annoying as possible
    
    ref T5707
---
 src/bin/e_comp_x_randr.c                     |   1 +
 src/bin/e_randr2.c                           | 144 ++++++++++++++++++++++-----
 src/bin/e_randr2.h                           |  11 +-
 src/modules/conf_randr/e_int_config_randr2.c |  75 ++++++++++++++
 4 files changed, 205 insertions(+), 26 deletions(-)

diff --git a/src/bin/e_comp_x_randr.c b/src/bin/e_comp_x_randr.c
index 3e793c717..d0745b866 100644
--- a/src/bin/e_comp_x_randr.c
+++ b/src/bin/e_comp_x_randr.c
@@ -752,6 +752,7 @@ e_comp_x_randr_create(void)
                     }
                }
              free(modes);
+             e_randr2_screen_modes_sort(s);
           }
         cs = NULL;
         priority = 0;
diff --git a/src/bin/e_randr2.c b/src/bin/e_randr2.c
index 1dae6a0f3..f1ee1ceca 100644
--- a/src/bin/e_randr2.c
+++ b/src/bin/e_randr2.c
@@ -1,6 +1,6 @@
 #include "e.h"
 
-#define E_RANDR_CONFIG_VERSION 1
+#define E_RANDR_CONFIG_VERSION 2
 
 /////////////////////////////////////////////////////////////////////////
 static Eina_Bool               _screen_closed(E_Randr2_Screen *s);
@@ -13,7 +13,7 @@ static void                    _info_free(E_Randr2 *r);
 static E_Config_Randr2        *_config_load(void);
 static void                    _config_free(E_Config_Randr2 *cfg);
 static Eina_Bool               _config_save(E_Randr2 *r, E_Config_Randr2 *cfg);
-static void                    _config_update(E_Randr2 *r, E_Config_Randr2 
*cfg);
+static Eina_Bool               _config_update(E_Randr2 *r, E_Config_Randr2 
*cfg, Eina_Bool );
 static void                    _config_apply(E_Randr2 *r, E_Config_Randr2 
*cfg);
 static int                     _config_screen_match_count(E_Randr2 *r, 
E_Config_Randr2 *cfg);
 static char                   *_screens_fingerprint(E_Randr2 *r);
@@ -44,6 +44,8 @@ E_API int              E_EVENT_RANDR_CHANGE = 0;
 EINTERN Eina_Bool
 e_randr2_init(void)
 {
+   int count;
+
    if (!E_EVENT_RANDR_CHANGE) E_EVENT_RANDR_CHANGE = ecore_event_type_new();
    if ((!e_comp->screen) || (!e_comp->screen->available) || 
(!e_comp->screen->available())) return EINA_FALSE;
    // create data descriptors for config storage
@@ -76,6 +78,7 @@ e_randr2_init(void)
    E_CONFIG_VAL(D, T, restore, UCHAR);
    E_CONFIG_VAL(D, T, ignore_hotplug_events, UCHAR);
    E_CONFIG_VAL(D, T, ignore_acpi_events, UCHAR);
+   E_CONFIG_VAL(D, T, default_policy, UINT);
 
    // set up events from the driver
    if (e_comp->screen->init)
@@ -88,14 +91,20 @@ e_randr2_init(void)
    e_randr2_cfg = _config_load();
    // only apply if restore is set AND at least one configured screen
    // matches one we have
-   if ((e_randr2_cfg->restore) &&
-       (_config_screen_match_count(e_randr2, e_randr2_cfg) > 0))
+
+   count = _config_screen_match_count(e_randr2, e_randr2_cfg);
+   if (e_randr2_cfg->restore && count)
      {
+        if (count != (int)eina_list_count(e_randr2->screens))
+          {
+             if (_config_update(e_randr2, e_randr2_cfg, 1))
+               e_randr2_config_save();
+          }
         _do_apply();
      }
    else
      {
-        _config_update(e_randr2, e_randr2_cfg);
+        _config_update(e_randr2, e_randr2_cfg, 0);
         e_randr2_config_save();
      }
    ecore_event_add(E_EVENT_RANDR_CHANGE, NULL, NULL, NULL);
@@ -314,6 +323,13 @@ _info_free(E_Randr2 *r)
    free(r);
 }
 
+static void
+_config_upgrade(E_Config_Randr2 *cfg)
+{
+   if (cfg->version < 2)
+     cfg->default_policy = E_RANDR2_POLICY_EXTEND;
+}
+
 static E_Config_Randr2 *
 _config_load(void)
 {
@@ -324,15 +340,9 @@ _config_load(void)
    if (cfg)
      {
         if (cfg->version < E_RANDR_CONFIG_VERSION)
-          {
-             _config_free(cfg);
-             cfg = NULL;
-          }
-        else
-          {
-             printf("RRR: loaded existing config\n");
-             return cfg;
-          }
+          _config_upgrade(cfg);
+        printf("RRR: loaded existing config\n");
+        return cfg;
      }
 
    // need new config
@@ -342,6 +352,7 @@ _config_load(void)
    cfg->restore = 1;
    cfg->ignore_hotplug_events = 0;
    cfg->ignore_acpi_events = 0;
+   cfg->default_policy = E_RANDR2_POLICY_EXTEND;
    printf("RRR: fresh config\n");
    return cfg;
 }
@@ -371,12 +382,20 @@ _config_save(E_Randr2 *r, E_Config_Randr2 *cfg)
    return e_config_domain_save("e_randr2", _e_randr2_cfg_edd, cfg);
 }
 
-static void
-_config_update(E_Randr2 *r, E_Config_Randr2 *cfg)
+static Eina_Bool
+_config_ask_dialog()
+{
+   e_configure_registry_call("screen/screen_setup", NULL, NULL);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_config_update(E_Randr2 *r, E_Config_Randr2 *cfg, Eina_Bool update_only)
 {
    Eina_List *l;
    E_Randr2_Screen *s;
    E_Config_Randr2_Screen *cs;
+   Eina_Bool ret = EINA_FALSE;
 
    printf("--------------------------------------------------\n");
    EINA_LIST_FOREACH(r->screens, l, s)
@@ -384,6 +403,7 @@ _config_update(E_Randr2 *r, E_Config_Randr2 *cfg)
         printf("RRR: out id=%s:  connected=%i\n", s->id, s->info.connected);
         if ((!s->id) || (!s->info.connected) || (_screen_closed(s))) continue;
         cs = e_randr2_config_screen_find(s, cfg);
+        if (cs && update_only) continue;
         if (!cs)
           {
              cs = calloc(1, sizeof(E_Config_Randr2_Screen));
@@ -395,16 +415,60 @@ _config_update(E_Randr2 *r, E_Config_Randr2 *cfg)
           }
         if (cs)
           {
-             if (s->config.relative.to)
-               cs->rel_to = eina_stringshare_add(s->config.relative.to);
-             cs->rel_align = s->config.relative.align;
-             cs->mode_refresh = s->config.mode.refresh;
-             cs->mode_w = s->config.mode.w;
-             cs->mode_h = s->config.mode.h;
+             if (update_only)
+               {
+                  switch (cfg->default_policy)
+                    {
+                     case E_RANDR2_POLICY_EXTEND:
+                       if (s->config.relative.mode < E_RANDR2_RELATIVE_TO_LEFT)
+                         cs->rel_mode = E_RANDR2_RELATIVE_TO_RIGHT;
+                       else
+                         cs->rel_mode = s->config.relative.mode;
+                       break;
+                     case E_RANDR2_POLICY_CLONE:
+                       cs->rel_mode = E_RANDR2_RELATIVE_CLONE;
+                       break;
+                     case E_RANDR2_POLICY_ASK:
+                       ecore_timer_loop_add(2, _config_ask_dialog, NULL);
+                     case E_RANDR2_POLICY_NONE:
+                       cs->rel_mode = E_RANDR2_RELATIVE_NONE;
+                       break;
+                    }
+               }
+             else
+               cs->rel_mode = s->config.relative.mode;
+             if (update_only &&
+               ((cfg->default_policy == E_RANDR2_POLICY_CLONE) ||
+                (cfg->default_policy == E_RANDR2_POLICY_EXTEND)))
+               {
+                  E_Randr2_Mode *m = eina_list_data_get(s->info.modes);
+
+                  cs->enabled = !!m;
+                  cs->mode_refresh = m->refresh;
+                  cs->mode_w = m->w;
+                  cs->mode_h = m->h;
+                  if (s->config.relative.to)
+                    cs->rel_to = eina_stringshare_add(s->config.relative.to);
+                  else
+                    {
+                       /* find right-most screen */
+                       E_Zone *zone = eina_list_last_data_get(e_comp->zones);
+                       eina_stringshare_replace(&cs->rel_to, zone->randr2_id);
+                    }
+                  cs->rel_align = 0;
+               }
+             else
+               {
+                  cs->enabled = s->config.enabled;
+                  cs->mode_refresh = s->config.mode.refresh;
+                  cs->mode_w = s->config.mode.w;
+                  cs->mode_h = s->config.mode.h;
+                  if (s->config.relative.to)
+                    cs->rel_to = eina_stringshare_add(s->config.relative.to);
+                  cs->rel_align = s->config.relative.align;
+               }
              cs->rotation = s->config.rotation;
              cs->priority = s->config.priority;
-             cs->rel_mode = s->config.relative.mode;
-             cs->enabled = s->config.enabled;
              if (cs->profile)
                {
                   printf("RRR: store config profile '%s'\n", cs->profile);
@@ -418,9 +482,11 @@ _config_update(E_Randr2 *r, E_Config_Randr2 *cfg)
                }
              printf("RRR: store scale mul %1.5f\n", cs->scale_multiplier);
              s->config.scale_multiplier = cs->scale_multiplier;
+             ret = EINA_TRUE;
           }
      }
    printf("--------------------------------------------------\n");
+   return ret;
 }
 
 static void
@@ -591,19 +657,28 @@ _screens_differ(E_Randr2 *r1, E_Randr2 *r2)
 static Eina_Bool
 _cb_screen_change_delay(void *data EINA_UNUSED)
 {
+   Eina_Bool change = EINA_FALSE;
    _screen_delay_timer = NULL;
    printf("RRR: ... %i %i\n", event_screen, event_ignore);
    // if we had a screen plug/unplug etc. event and we shouldnt ignore it...
    if ((event_screen) && (!event_ignore))
      {
         E_Randr2 *rtemp;
-        Eina_Bool change = EINA_FALSE;
 
         printf("RRR: reconfigure screens due to event...\n");
         rtemp = e_comp->screen->create();
         if (rtemp)
           {
              if (_screens_differ(e_randr2, rtemp)) change = EINA_TRUE;
+             if (e_randr2_cfg->default_policy != E_RANDR2_POLICY_NONE)
+               {
+                  if (_config_update(rtemp, e_randr2_cfg, 1))
+                    {
+                       e_randr2_config_save();
+                       if (e_randr2_cfg->default_policy != E_RANDR2_POLICY_ASK)
+                         change = EINA_TRUE;
+                    }
+               }
              _info_free(rtemp);
           }
         printf("RRR: change = %i\n", change);
@@ -1268,3 +1343,22 @@ e_randr2_screen_dpi_get(E_Randr2_Screen *s)
    dpi2 = (25.4 * (double)(s->config.mode.h)) / (double)(s->info.size.h);
    return (dpi1 + dpi2) / 2.0;
 }
+
+static int
+_modelist_sort(const void *a, const void *b)
+{
+   const E_Randr2_Mode *ma = a, *mb = b;
+
+   /* largest resolutions first */
+   if ((ma->w * ma->h) > (mb->w * mb->h)) return -1;
+   /* highest refresh first */
+   if (ma->refresh > mb->refresh) return -1;
+   return 1;
+}
+
+EAPI void
+e_randr2_screen_modes_sort(E_Randr2_Screen *s)
+{
+   EINA_SAFETY_ON_NULL_RETURN(s);
+   s->info.modes = eina_list_sort(s->info.modes, 0, _modelist_sort);
+}
diff --git a/src/bin/e_randr2.h b/src/bin/e_randr2.h
index e964bb7eb..02614f2b3 100644
--- a/src/bin/e_randr2.h
+++ b/src/bin/e_randr2.h
@@ -11,6 +11,14 @@ typedef struct _E_Config_Randr2_Screen 
E_Config_Randr2_Screen;
 #ifndef E_RANDR2_H
 #define E_RAND2R_H
 
+typedef enum
+{
+   E_RANDR2_POLICY_NONE,
+   E_RANDR2_POLICY_EXTEND,
+   E_RANDR2_POLICY_CLONE,
+   E_RANDR2_POLICY_ASK,
+} E_Randr2_Policy;
+
 typedef enum _E_Randr2_Relative
 {
    E_RANDR2_RELATIVE_UNKNOWN,
@@ -92,6 +100,7 @@ struct _E_Config_Randr2
    unsigned char  restore;
    unsigned char  ignore_hotplug_events;
    unsigned char  ignore_acpi_events;
+   E_Randr2_Policy default_policy;
 };
 
 struct _E_Config_Randr2_Screen
@@ -128,6 +137,6 @@ E_API E_Config_Randr2_Screen 
*e_randr2_config_screen_find(E_Randr2_Screen *s, E_
 E_API void                    e_randr2_screens_setup(int rw, int rh);
 E_API E_Randr2_Screen        *e_randr2_screen_id_find(const char *id);
 E_API double                  e_randr2_screen_dpi_get(E_Randr2_Screen *s);
-
+E_API void                     e_randr2_screen_modes_sort(E_Randr2_Screen *s);
 #endif
 #endif
diff --git a/src/modules/conf_randr/e_int_config_randr2.c 
b/src/modules/conf_randr/e_int_config_randr2.c
index 42c98ccac..f724ecd4f 100644
--- a/src/modules/conf_randr/e_int_config_randr2.c
+++ b/src/modules/conf_randr/e_int_config_randr2.c
@@ -27,10 +27,12 @@ struct _E_Config_Dialog_Data
    Evas_Object *profile_list_obj;
    Evas_Object *scale_custom_obj;
    Evas_Object *scale_value_obj;
+   Evas_Object *policy_obj;
    int restore;
    int hotplug;
    int acpi;
    int screen;
+   E_Randr2_Policy policy;
 };
 
 typedef struct
@@ -101,6 +103,7 @@ _create_data(E_Config_Dialog *cfd EINA_UNUSED)
    cfdata->restore = e_randr2_cfg->restore;
    cfdata->hotplug = !e_randr2_cfg->ignore_hotplug_events;
    cfdata->acpi = !e_randr2_cfg->ignore_acpi_events;
+   cfdata->policy = e_randr2_cfg->default_policy;
    return cfdata;
 }
 
@@ -742,6 +745,66 @@ _cb_enabled_changed(void *data, Evas_Object *obj, void 
*event EINA_UNUSED)
    e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE);
 }
 
+static void
+_policy_text_update(E_Config_Dialog_Data *cfdata)
+{
+   char pbuf[128];
+   const char *policy[] =
+   {
+      _("Ignore"),
+      _("Extend"),
+      _("Clone"),
+      _("Ask")
+   };
+
+   snprintf(pbuf, sizeof(pbuf), _("Hotplug Policy (%s)"), 
policy[cfdata->policy]);
+   elm_object_text_set(cfdata->policy_obj, pbuf);
+}
+
+static void
+_cb_policy_ignore(void *data, Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
+{
+   E_Config_Dialog_Data *cfdata = data;
+
+   if (cfdata->policy == E_RANDR2_POLICY_NONE) return;
+   cfdata->policy = E_RANDR2_POLICY_NONE;
+   _policy_text_update(cfdata);
+   e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE);
+}
+
+static void
+_cb_policy_ask(void *data, Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
+{
+   E_Config_Dialog_Data *cfdata = data;
+
+   if (cfdata->policy == E_RANDR2_POLICY_ASK) return;
+   cfdata->policy = E_RANDR2_POLICY_ASK;
+   _policy_text_update(cfdata);
+   e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE);
+}
+
+static void
+_cb_policy_extend(void *data, Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
+{
+   E_Config_Dialog_Data *cfdata = data;
+
+   if (cfdata->policy == E_RANDR2_POLICY_EXTEND) return;
+   cfdata->policy = E_RANDR2_POLICY_EXTEND;
+   _policy_text_update(cfdata);
+   e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE);
+}
+
+static void
+_cb_policy_clone(void *data, Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
+{
+   E_Config_Dialog_Data *cfdata = data;
+
+   if (cfdata->policy == E_RANDR2_POLICY_CLONE) return;
+   cfdata->policy = E_RANDR2_POLICY_CLONE;
+   _policy_text_update(cfdata);
+   e_config_dialog_changed_set(cfdata->cfd, EINA_TRUE);
+}
+
 static Evas_Object *
 _basic_create(E_Config_Dialog *cfd, Evas *evas EINA_UNUSED, 
E_Config_Dialog_Data *cfdata)
 {
@@ -1045,6 +1108,17 @@ _basic_create(E_Config_Dialog *cfd, Evas *evas 
EINA_UNUSED, E_Config_Dialog_Data
    evas_object_show(o);
    evas_object_smart_callback_add(o, "changed", _cb_acpi_changed, cfdata);
 
+   cfdata->policy_obj = o = elm_hoversel_add(win);
+   evas_object_size_hint_weight_set(o, 0.0, 0.0);
+   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
+   _policy_text_update(cfdata);
+   elm_hoversel_item_add(o, _("Clone"), NULL, ELM_ICON_NONE, _cb_policy_clone, 
cfdata);
+   elm_hoversel_item_add(o, _("Extend"), NULL, ELM_ICON_NONE, 
_cb_policy_extend, cfdata);
+   elm_hoversel_item_add(o, _("Ask"), NULL, ELM_ICON_NONE, _cb_policy_ask, 
cfdata);
+   elm_hoversel_item_add(o, _("Ignore"), NULL, ELM_ICON_NONE, 
_cb_policy_ignore, cfdata);
+   elm_box_pack_end(bx2, o);
+   evas_object_show(o);
+
    evas_smart_objects_calculate(evas_object_evas_get(win));
 
    e_util_win_auto_resize_fill(win);
@@ -1062,6 +1136,7 @@ _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, 
E_Config_Dialog_Data *cfdata)
    e_randr2_cfg->restore = cfdata->restore;
    e_randr2_cfg->ignore_hotplug_events = !cfdata->hotplug;
    e_randr2_cfg->ignore_acpi_events = !cfdata->acpi;
+   e_randr2_cfg->default_policy = cfdata->policy;
 
    printf("APPLY....................\n");
    EINA_LIST_FOREACH(cfdata->screens, l, cs2)

-- 


Reply via email to