e - randr - laptop lids - handle plug/unplug and well as lid open/close
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Mon, 9 Feb 2015 08:43:17 +0000 (17:43 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Mon, 9 Feb 2015 09:22:02 +0000 (18:22 +0900)
this fixes some issues in the new randr2 code that made it not work
right with plug/unplug and lid close/open. now it does work right and
plugging/unplugging displays is seamless (if your driver does not give
plug/unplug events bind a key to update screen config acvtion and e
will figure it out when you hit the key).

src/bin/e_comp.c
src/bin/e_comp_canvas.c
src/bin/e_comp_x.c
src/bin/e_randr2.c
src/bin/e_randr2.h
src/bin/e_sys.c
src/modules/conf_randr/e_int_config_randr2.c

index 7c25c871ef79552971de2f925dca7c9063383648..ff4fff0d4e0eb8bf1386c2c1c321f0703dd4c255 100644 (file)
@@ -851,6 +851,7 @@ _e_comp_screensaver_on(void *data EINA_UNUSED, int type EINA_UNUSED, void *event
    Eina_List *l;
    E_Zone *zone;
 
+   printf("_e_comp_screensaver_on\n");
    ecore_frametime = ecore_animator_frametime_get();
    if (e_comp->saver) return ECORE_CALLBACK_RENEW;
    e_comp_override_add(e_comp);
@@ -874,6 +875,7 @@ _e_comp_screensaver_off(void *data EINA_UNUSED, int type EINA_UNUSED, void *even
    E_Zone *zone;
    E_Client *ec;
 
+   printf("_e_comp_screensaver_off\n");
    ecore_animator_frametime_set(ecore_frametime);
    if (!e_comp->saver) return ECORE_CALLBACK_RENEW;
    e_comp_override_del(e_comp);
index 5425ddc5c400e364b5c199642ac20d60638521e7..5e494ac9dba534332f0a905c9f0f2607463735c6 100644 (file)
@@ -346,17 +346,24 @@ e_comp_canvas_update(void)
      {
         zones = e_comp->zones;
         e_comp->zones = NULL;
+        printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
         EINA_LIST_FOREACH(screens, l, scr)
           {
              zone = NULL;
 
+             printf("@ match screens %p[%i] = %i %i %ix%i -- %i\n", 
+                    scr, scr->escreen, scr->x, scr->y, scr->w, scr->h, scr->escreen);
              EINA_LIST_FOREACH(zones, ll, zone)
                {
                   if (zone->id == scr->escreen) break;
                   zone = NULL;
                }
+             printf("@ matches existing zone %p\n", zone);
              if (zone)
                {
+                  printf("   move resize %i %i %ix%i -> %i %i %ix%i\n",
+                         zone->x, zone->y, zone->w, zone->h,
+                         scr->x, scr->y, scr->w, scr->h);
                   changed |= e_zone_move_resize(zone, scr->x, scr->y, scr->w, scr->h);
                   if (changed)
                     printf("@@@ FOUND ZONE %i %i [%p]\n", zone->num, zone->id, zone);
@@ -380,6 +387,7 @@ e_comp_canvas_update(void)
           {
              E_Zone *spare_zone;
 
+             printf("@zones have been deleted....\n");
              changed = EINA_TRUE;
              spare_zone = eina_list_data_get(e_comp->zones);
 
@@ -387,6 +395,7 @@ e_comp_canvas_update(void)
                {
                   E_Client *ec;
 
+                  printf("reassign all clients from deleted zone %p\n", zone);
                   E_CLIENT_FOREACH(e_comp, ec)
                     {
                        if (ec->zone == zone)
index 36ff29afb4a10f0aed7628c2c8a15d39d65115e4..1621942d9b7e81d584676e5266636074f3ba7b0a 100644 (file)
@@ -4585,15 +4585,21 @@ _e_comp_x_xinerama_setup(int rw, int rh)
              screen->w = s->config.geom.w;
              screen->h = s->config.geom.h;
              all_screens = eina_list_append(all_screens, screen);
+             printf("xinerama screen %i %i %ix%i\n", screen->x, screen->y, screen->w, screen->h);
              INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i",
                  i, i, screen->w, screen->h, screen->x, screen->y);
              i++;
           }
      }
-   // XXX: what if we have zero screens? all unplugged? need to flag this
-   // keep all screens as-is for now and mark comp to hide everything
-   // and wait for a screen to come back
-   if (i == 0)
+   // if we have NO screens at all (above - i will be 0) AND we have no
+   // existing screens set up in xinerama - then just say root window size
+   // is the entire screen. this should handle the case where you unplug ALL
+   // screens from an existing setup (unplug external monitors and/or close
+   // laptop lid), in which case as long as at least one screen is configured
+   // in xinerama, it will be left-as is until next time we re-eval screen
+   // setup and have at least one screen
+   printf("xinerama setup............... %i %p\n", i, e_xinerama_screens_all_get());
+   if ((i == 0) && (!e_xinerama_screens_all_get()))
      {
         screen = E_NEW(E_Screen, 1);
         screen->escreen = screen->screen = 0;
index db568d179ca2a54ccf4f689488253d6dadb29bfe..5eea039227dc36e3b434de2f14ce40e010390b44 100644 (file)
@@ -186,8 +186,13 @@ static Evas_Object *_fade_obj = NULL;
 static Eina_Bool
 _screen_closed(E_Randr2_Screen *s)
 {
+   printf("RRR: check lid for %s...\n", s->info.name);
    if (!_lid_is_closed) return EINA_FALSE;
-   if (s->info.is_lid) return EINA_TRUE;
+   if (s->info.is_lid)
+     {
+        printf("RRR:   is closed lid\n");
+        return EINA_TRUE;
+     }
    return EINA_FALSE;
 }
 
@@ -510,6 +515,8 @@ _screens_fingerprint(E_Randr2 *r)
              eina_strbuf_append(buf, ":");
              eina_strbuf_append(buf, s->id);
              eina_strbuf_append(buf, ":");
+             if (s->info.lid_closed) eina_strbuf_append(buf, ":LC:");
+             else eina_strbuf_append(buf, ":LO:");
           }
      }
    str = eina_strbuf_string_steal(buf);
@@ -529,7 +536,9 @@ _screens_differ(E_Randr2 *r1, E_Randr2 *r2)
    s1 = _screens_fingerprint(r1);
    s2 = _screens_fingerprint(r2);
    if ((!s1) && (!s2)) return EINA_FALSE;
+   printf("RRR: check fingerprint...\n");
    if ((s1) && (s2) && (strcmp(s1, s2))) changed = EINA_TRUE;
+   printf("RRR: ... fingerprint says %i\n", changed);
    free(s1);
    free(s2);
    // check screen config
@@ -549,9 +558,11 @@ _screens_differ(E_Randr2 *r1, E_Randr2 *r2)
                  (s->config.mode.w != ss->config.mode.w) ||
                  (s->config.mode.h != ss->config.mode.h) ||
                  (s->config.enabled != ss->config.enabled) ||
-                 (s->config.rotation != ss->config.rotation))
+                 (s->config.rotation != ss->config.rotation) ||
+                 (s->info.lid_closed != ss->info.lid_closed))
           changed = EINA_TRUE;
      }
+   printf("RRR: changed = %i\n", changed);
    return changed;
 }
 
@@ -559,6 +570,7 @@ static Eina_Bool
 _cb_screen_change_delay(void *data EINA_UNUSED)
 {
    _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))
      {
@@ -572,6 +584,7 @@ _cb_screen_change_delay(void *data EINA_UNUSED)
              if (_screens_differ(e_randr2, rtemp)) change = EINA_TRUE;
              _info_free(rtemp);
           }
+        printf("RRR: change = %i\n", change);
         // we plugged or unplugged some monitor - re-apply config so
         // known screens can be coonfigured
         if (change) e_randr2_config_apply();
@@ -600,10 +613,13 @@ _cb_acpi(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
    E_Event_Acpi *ev = event;
    Eina_Bool lid_closed;
 
+   printf("RRR: acpi event\n");
    if (ev->type != E_ACPI_TYPE_LID) return EINA_TRUE;
    lid_closed = (ev->status == E_ACPI_LID_CLOSED);
    if (lid_closed == _lid_is_closed) return EINA_TRUE;
+   printf("RRR: lid event for lid %i\n", lid_closed);
    _lid_is_closed = lid_closed;
+   event_screen = EINA_TRUE;
    _screen_change_delay();
    return EINA_TRUE;
 }
@@ -650,12 +666,13 @@ _screen_config_do(E_Randr2_Screen *s)
 {
    E_Randr2_Screen *s2 = NULL;
 
-   _config_do_recurse++;
-   if (_config_do_recurse > 20)
+   printf("RRR: screen do '%s'\n", s->info.name);
+   if (_config_do_recurse > 10)
      {
         ERR("screen config loop!");
         return;
      }
+   _config_do_recurse++;
    // if screen has a dependency...
    if ((s->config.relative.mode != E_RANDR2_RELATIVE_UNKNOWN) &&
        (s->config.relative.mode != E_RANDR2_RELATIVE_NONE) &&
@@ -737,6 +754,7 @@ _screen_config_do(E_Randr2_Screen *s)
              s->config.geom.y = s2->config.geom.y + s2->config.geom.h;
           }
      }
+   _config_do_recurse--;
 }
 
 static void
@@ -1159,6 +1177,8 @@ _info_get(void)
         else if (conn == ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT)
           s->info.connector = E_RANDR2_CONNECTOR_DISPLAY_PORT;
         s->info.is_lid = _is_lid_name(s->info.name);
+        s->info.lid_closed = s->info.is_lid && _lid_is_closed;
+        printf("RRR: .... lid_closed = %i (%i && %i)\n", s->info.lid_closed, s->info.is_lid, _lid_is_closed);
         if (ecore_x_randr_output_connection_status_get(root, outputs[i]) ==
             ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
           s->info.connected = EINA_TRUE;
@@ -1413,7 +1433,7 @@ _screen_config_apply(void)
    Ecore_X_Randr_Crtc *crtcs = NULL;
    Ecore_X_Randr_Output *outputs = NULL, out, *outconf;
    E_Randr2_Screen **screenconf;
-   int crtcs_num = 0, outputs_num = 0, i;
+   int crtcs_num = 0, outputs_num = 0, i, numout;
    Ecore_X_Randr_Crtc_Info *info;
    int top_priority = 0;
 
@@ -1492,6 +1512,13 @@ _screen_config_apply(void)
                     }
                }
           }
+        numout = 0;
+        for (i = 0; i < crtcs_num; i++)
+          {
+             if (outconf[i]) numout++;
+          }
+        if (numout)
+          {
         // set up a crtc to drive each output (or not)
         for (i = 0; i < crtcs_num; i++)
           {
@@ -1544,20 +1571,34 @@ _screen_config_apply(void)
                      ECORE_X_RANDR_ORIENTATION_ROT_0);
                }
           }
+          }
+        else
+          {
+             printf("RRR: EERRRRRROOOORRRRRRR no outputs to configure!\n");
+          }
      }
    free(outputs);
    free(crtcs);
 
+   printf("RRR: set vsize: %ix%i\n", nw, nh);
    ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1);
      {
         int ww = 0, hh = 0, ww2 = 0, hh2 = 0;
         ecore_x_randr_screen_current_size_get(root, &ww, &hh, &ww2, &hh2);
         printf("RRR: cur size: %ix%i\n", ww, hh);
+//        ecore_x_randr_screen_reset(root);
+//        ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1);
+//        ecore_x_sync();
+//        ecore_x_randr_screen_current_size_get(root, &ww, &hh, &ww2, &hh2);
+//        printf("RRR: cur size: %ix%i\n", ww, hh);
      }
    ecore_x_randr_screen_size_range_get(root, NULL, NULL, NULL, NULL);
    ecore_x_ungrab();
    ecore_x_sync();
 
    // ignore the next batch of randr events - we caused them ourselves
-   event_ignore = EINA_TRUE;
+   // XXX: a problem. thew first time we configure the screen we may not
+   // get any events back to clear the ignore flag below, so only apply
+   // here if the randr config now doesnt match what we want to set up.
+//   event_ignore = EINA_TRUE;
 }
index 70fd40f0ca8c86b6b6646a731cb48e6e7a7748c0..ab7aa0b4425a031576c73be3369a2151f61b39b2 100644 (file)
@@ -59,6 +59,7 @@ struct _E_Randr2_Screen
       char                 *edid; // full edid data
       E_Randr2_Connector    connector; // the connector type
       Eina_Bool             is_lid : 1; // is an internal screen
+      Eina_Bool             lid_closed : 1; // is lid closed when screen qury'd
       Eina_Bool             connected : 1; // some screen is plugged in or not
       Eina_Bool             backlight : 1; // does it have backlight controls?
       Eina_Bool             can_rot_0 : 1; // can it do this rotation?
index 41c0633d2f5eeb8c524c49dda2a2296b1860906f..69400febc70c0a511f002c7a8519f387220d34ed 100644 (file)
@@ -114,6 +114,7 @@ _e_sys_comp_emit_cb_wait(E_Sys_Action a, const char *sig, const char *rep, Eina_
 
    if (nocomp_push) e_comp_override_add(e_comp);
    else e_comp_override_timed_pop(e_comp);
+   printf("_e_sys_comp_emit_cb_wait - [%x] %s %s\n", a, sig, rep);
    EINA_LIST_FOREACH(e_comp->zones, l, zone)
      {
         e_zone_fade_handle(zone, nocomp_push, 0.5);
index 2f8c4ccac9a1b11fc8a86fc136e8224900c3ea92..f823fdb67646f945122b909cbc7f180e92afe652 100644 (file)
@@ -378,6 +378,7 @@ _cb_rel_to_set(void *data, Evas_Object *obj, void *event)
                   E_Randr2_Screen *s = _screen_config_id_find(cs2->id);
                   if (s)
                     {
+                       printf("SEt to %p [%s]\n", cs, cs->id);
                        printf("find s = %p\n", s);
                        printf("s id = %s\n", s->id);
                        elm_object_text_set(obj, s->info.name);
@@ -710,9 +711,11 @@ _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
    E_Config_Randr2_Screen *cs, *cs2;
 
    e_randr2_cfg->restore = cfdata->restore;
+   printf("APPLY....................\n");
    EINA_LIST_FOREACH(cfdata->screens, l, cs2)
      {
         if (!cs2->id) continue;
+        printf("APPLY .... %p\n", cs2);
         cs = _screen_config_randr_id_find(cs2->id);
         if (!cs)
           {
@@ -722,6 +725,7 @@ _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
           }
         if (cs->rel_to) eina_stringshare_del(cs->rel_to);
         cs->rel_to = NULL;
+        printf("APPLY %s .... rel to %s\n", cs->id, cs2->rel_to);
         if (cs2->rel_to) cs->rel_to = eina_stringshare_add(cs2->rel_to);
         cs->rel_align = cs2->rel_align;
         cs->mode_refresh = cs2->mode_refresh;
@@ -731,6 +735,7 @@ _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
         cs->rotation = cs2->rotation;
         cs->priority = cs2->priority;
         cs->rel_mode = cs2->rel_mode;
+        printf("APPLY %s .... rel mode %i\n", cs->id, cs->rel_mode);
         cs->enabled = cs2->enabled;
      }
    e_randr2_config_save();