Page MenuHomePhabricator

Hide, then show existing elm win hides but doesn't show again
Closed, ResolvedPublic

Description

Try this test:

#include <Elementary.h>

static Evas_Object *win, *bg, *im;

static void
win_del(void *data, Evas_Object *obj, void *event_info)
{
   elm_exit();
}

int
main(int argc, char **argv)
{
   int w, h;

   elm_init(argc, argv);

   win = elm_win_add(NULL, "tst", ELM_WIN_BASIC);
   elm_win_title_set(win, "TST");
   evas_object_smart_callback_add(win, "delete,request", win_del, NULL);

   bg = elm_bg_add(win);
   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(win, bg);
   evas_object_show(bg);

   im = evas_object_image_filled_add(evas_object_evas_get(win));
   evas_object_image_smooth_scale_set(im, EINA_FALSE);
   evas_object_image_file_set(im, argv[1], NULL);
   evas_object_image_size_get(im, &w, &h);
   if ((w <= 0) || (h <= 0)) exit(0);
   evas_object_move(im, 50, 50);
   evas_object_resize(im, 200, 200);
   evas_object_show(im);

   im = evas_object_image_filled_add(evas_object_evas_get(win));
   evas_object_image_file_set(im, argv[1], NULL);
   evas_object_image_size_get(im, &w, &h);
   if ((w <= 0) || (h <= 0)) exit(0);
   evas_object_move(im, 50, 350);
   evas_object_resize(im, 200, 200);
   evas_object_show(im);

   evas_object_resize(win, 300, 600);
   evas_object_show(win);

   elm_run();

   elm_shutdown();
   return 0;
}

Hit "disconnect" and watch window disappear and never reappear again. FYI Tested in TWM (the above code) and it works fine. EFL seems OK there, but not under Enlightenment. :)

raster created this task.Apr 3 2017, 8:05 PM
raster updated the task description. (Show Details)Apr 3 2017, 8:05 PM
zmike added a comment.Apr 4 2017, 7:48 AM

There is no "disconnect" ?

raster added a comment.EditedApr 4 2017, 9:40 PM

oh crap. i pasted the wrong code. argh!

#include <Elementary.h>

static Evas_Object *win, *win2, *bt, *bt2, *bg2;

static void
_disconnect_clicked(void *data, Evas_Object *obj, void *event_info)
{
   evas_object_hide(win2);
   evas_object_show(win2);
}

static void
_ok_clicked(void *data, Evas_Object *obj, void *event_info)
{
   elm_exit();
}

int
main(int argc, char **argv)
{
   int w, h;

   elm_init(argc, argv);

   win = elm_win_util_standard_add("main", "Main");
   elm_win_title_set(win, "TST");
   elm_win_autodel_set(win, EINA_TRUE);
   evas_object_size_hint_weight_set(win, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(win,  EVAS_HINT_FILL, EVAS_HINT_FILL);

   bt = elm_button_add(win);
   elm_object_text_set(bt, "OK");
   evas_object_smart_callback_add(bt, "clicked", _ok_clicked, NULL);
   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(win, bt);
   evas_object_show(bt);

   evas_object_resize(win, 300, 300);
   evas_object_show(win);

   win2 = elm_win_add(win, "dialog", ELM_WIN_BASIC);
   elm_win_title_set(win2, "Dialog");
   elm_win_autodel_set(win2, EINA_TRUE);
   evas_object_size_hint_weight_set(win2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(win2,  EVAS_HINT_FILL, EVAS_HINT_FILL);

   bg2 = elm_bg_add(win2);
   evas_object_size_hint_weight_set(bg2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(win2, bg2);
   evas_object_show(bg2);

   bt2 = elm_button_add(win2);
   elm_object_text_set(bt2, "Disconnect");
   evas_object_smart_callback_add(bt2, "clicked", _disconnect_clicked, NULL);
   evas_object_size_hint_align_set(bt2, EVAS_HINT_FILL, EVAS_HINT_FILL);
   evas_object_size_hint_weight_set(bt2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(win2, bt2);
   evas_object_show(bt2);

   evas_object_resize(win2, 200, 200);
   evas_object_show(win2);

   elm_run();

   elm_shutdown();
   return 0;
}

There!

zmike added a comment.Apr 5 2017, 10:46 AM

This is an insane corner case bug which, afaik, is not actually covered by spec. It's such a corner case that blackbox (my usual goto) handles the behavior somewhat inconsistently and with different behavior than twm. Not planning to make any changes today since thinking not so good with jetlag, but here's a rundown:

  • (C) Map window
  • (S) Reparent window (managed)
  • (C) Unmap window
  • (C) Map window
  • (S) Reparent window (unmanaged)
  • WM receives MapRequest where the parent window is the WM's (dead) reparent window instead of the root window

twm will manage+map any window at any time without ever checking the parent window, but blackbox (and enlightenment) check and will not do this if the parent is not root; right now enlightenment is actually slightly broken in that it will fallthrough and map these windows which pegs the cpu and breaks the compositor in subtle ways.

twm works here because it totally ignores any existing parent window and just creates another manager window to reparent. this is broken in some cases, so I don't think "twm works" is the right reference.

blackbox is inconsistent: it will sometimes show the window without creating a manager window to reparent (window shows with no frame and cannot be moved) and will sometimes show the window with a frame as expected--this is due to the race condition.

I think that, in fact, this is an efl bug since it guarantees a server-side race condition, but I'm too tired to

raster added a comment.Apr 5 2017, 5:02 PM

Hmmmm. I am not sure the spec has to cover this. At least in X11 it's an unmap then a map. the new map should be treated like any new client. Yup. It's a corner case indeed. My test was twm and fvwm2... which worked.

indeed i get why they are different. actually enlightenment's "i'll wait and defer my work until idle enter time when i eval stuff: also interacts here.

i know this is a corner case. i actually am not sure what we should do about it... is it a bug? is it just a "race condition built into x11 you cant really get rid of, so deal with it?" ... ?

so how would this be an efl bug? any client can do an xlib XUnmapWindow() and XMapWindow() one after the other. it's valid x11 protocol requests... :/

jpeg removed a subscriber: jpeg.Apr 5 2017, 11:38 PM
zmike added a comment.Apr 6 2017, 5:54 AM

It's an efl bug because we make it super easy for developers to trigger this behavior by making show/hide ops on the window canvas object translate into synchronous show/hide calls on the display server's window. If this were deferred then it would be more difficult, though that would have its own issues unless every protocol-level call was batched+dispatched (and that's a huge amount of work).

I have an idea for an incredibly specific hack to resolve this corner case, but I'm not happy that it's the only thing I could come up with ...