<div dir="ltr"><div>For reference, here is a video of the  "weston-stacking" client with vanilla Weston, latest master branch, and this series of patches applied :<br><br><a href="https://www.youtube.com/watch?v=IZj72kWLY2w">https://www.youtube.com/watch?v=IZj72kWLY2w</a><br><br></div>(if a parent window creates a new child window, and we use the "n" button from the parent again, then xdg_surface_present() will be called on the child window surface. desktop-shell will issue a small GUI notification -which the user can ignore. If the user clicks, the corresponding surface will be raised to moved to the current workspace)<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-09 18:25 GMT+02:00 Manuel Bachmann <span dir="ltr"><<a href="mailto:manuel.bachmann@open.eurogiciel.org" target="_blank">manuel.bachmann@open.eurogiciel.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Due to the absence of a clever close handler, closing one<br>
window among multiple ones used to quit the application.<br>
We now keep track of our children windows, and close only<br>
these ones.<br>
<br>
If the user tries to create a new window and we already<br>
have a child, present() the child instead. The user will<br>
then be able to raise and find the child by interacting<br>
with the notification.<br>
<br>
Signed-off-by: Manuel Bachmann <<a href="mailto:manuel.bachmann@open.eurogiciel.org">manuel.bachmann@open.eurogiciel.org</a>><br>
---<br>
 clients/stacking.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++--------<br>
 1 file changed, 70 insertions(+), 11 deletions(-)<br>
<br>
diff --git a/clients/stacking.c b/clients/stacking.c<br>
index ea6101d..c9e38d3 100644<br>
--- a/clients/stacking.c<br>
+++ b/clients/stacking.c<br>
@@ -33,9 +33,15 @@<br>
<br>
 #include "window.h"<br>
<br>
+struct stacked_window {<br>
+       struct window *window;<br>
+       struct stacked_window *child_window;<br>
+       struct stacking *stacking;<br>
+};<br>
+<br>
 struct stacking {<br>
        struct display *display;<br>
-       struct window *root_window;<br>
+       struct stacked_window *root_window;<br>
 };<br>
<br>
 static void<br>
@@ -55,17 +61,33 @@ static void<br>
 fullscreen_handler(struct window *window, void *data);<br>
 static void<br>
 redraw_handler(struct widget *widget, void *data);<br>
+static void<br>
+close_handler(void *data);<br>
<br>
 /* Iff parent_window is set, the new window will be transient. */<br>
 static struct window *<br>
 new_window(struct stacking *stacking, struct window *parent_window)<br>
 {<br>
+       struct stacked_window *current_window;<br>
        struct window *new_window;<br>
        struct widget *new_widget;<br>
<br>
        new_window = window_create(stacking->display);<br>
        window_set_parent(new_window, parent_window);<br>
<br>
+       /* iterate through stackings, and stop once we find<br>
+        * the last window */<br>
+       current_window = stacking->root_window;<br>
+       while (current_window->child_window) {<br>
+               current_window = current_window->child_window;<br>
+       }<br>
+       /* we create the new child */<br>
+       current_window->child_window = xzalloc(sizeof *current_window);<br>
+       current_window = current_window->child_window;<br>
+       current_window->stacking = stacking;<br>
+       current_window->window = new_window;<br>
+       current_window->child_window = NULL;<br>
+<br>
        new_widget = window_frame_create(new_window, new_window);<br>
<br>
        window_set_title(new_window, "Stacking Test");<br>
@@ -74,7 +96,8 @@ new_window(struct stacking *stacking, struct window *parent_window)<br>
        window_set_fullscreen_handler(new_window, fullscreen_handler);<br>
        widget_set_button_handler(new_widget, button_handler);<br>
        widget_set_redraw_handler(new_widget, redraw_handler);<br>
-       window_set_user_data(new_window, stacking);<br>
+       window_set_close_handler(new_window, close_handler);<br>
+       window_set_user_data(new_window, current_window);<br>
<br>
        window_schedule_resize(new_window, 300, 300);<br>
<br>
@@ -108,12 +131,12 @@ button_handler(struct widget *widget,<br>
                uint32_t button,<br>
                enum wl_pointer_button_state state, void *data)<br>
 {<br>
-       struct stacking *stacking = data;<br>
+       struct stacked_window *current_window = data;<br>
<br>
        switch (button) {<br>
        case BTN_RIGHT:<br>
                if (state == WL_POINTER_BUTTON_STATE_PRESSED)<br>
-                       show_popup(stacking, input, time,<br>
+                       show_popup(current_window->stacking, input, time,<br>
                                   widget_get_user_data(widget));<br>
                break;<br>
<br>
@@ -129,7 +152,7 @@ key_handler(struct window *window,<br>
             uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,<br>
             void *data)<br>
 {<br>
-       struct stacking *stacking = data;<br>
+       struct stacked_window *current_window = data;<br>
<br>
        if (state != WL_KEYBOARD_KEY_STATE_PRESSED)<br>
                return;<br>
@@ -144,12 +167,16 @@ key_handler(struct window *window,<br>
                break;<br>
<br>
        case XKB_KEY_n:<br>
-               /* New top-level window. */<br>
-               new_window(stacking, NULL);<br>
+               /* If this window has no child, create a new top-level one.<br>
+                * Otherwise, present the existing child to the user. */<br>
+               if (!current_window->child_window)<br>
+                       new_window(current_window->stacking, NULL);<br>
+               else<br>
+                       window_present(current_window->child_window->window);<br>
                break;<br>
<br>
        case XKB_KEY_p:<br>
-               show_popup(stacking, input, time, window);<br>
+               show_popup(current_window->stacking, input, time, window);<br>
                break;<br>
<br>
        case XKB_KEY_q:<br>
@@ -158,7 +185,7 @@ key_handler(struct window *window,<br>
<br>
        case XKB_KEY_t:<br>
                /* New transient window. */<br>
-               new_window(stacking, window);<br>
+               new_window(current_window->stacking, window);<br>
                break;<br>
<br>
        default:<br>
@@ -281,6 +308,34 @@ redraw_handler(struct widget *widget, void *data)<br>
        cairo_destroy(cr);<br>
 }<br>
<br>
+static void<br>
+close_handler(void *data)<br>
+{<br>
+       struct stacked_window *current_window = data;<br>
+       struct stacked_window *parent_window;<br>
+<br>
+       /* we first re-iterate from the root window to the current<br>
+        * one to find the direct parent, and unreference it */<br>
+       parent_window = current_window->stacking->root_window;<br>
+       while (parent_window) {<br>
+               if (parent_window->child_window == current_window) {<br>
+                       parent_window->child_window = NULL;<br>
+                       break;<br>
+               }<br>
+               parent_window = parent_window->child_window;<br>
+       }<br>
+<br>
+       /* we can now unreference and free all the children */<br>
+       while (current_window) {<br>
+               window_destroy(current_window->window);<br>
+               free(current_window);<br>
+<br>
+               parent_window = current_window;<br>
+               current_window = current_window->child_window;<br>
+               parent_window->child_window = NULL;<br>
+       }<br>
+}<br>
+<br>
 int<br>
 main(int argc, char *argv[])<br>
 {<br>
@@ -288,6 +343,10 @@ main(int argc, char *argv[])<br>
<br>
        memset(&stacking, 0, sizeof stacking);<br>
<br>
+       stacking.root_window = xzalloc(sizeof stacking.root_window);<br>
+       stacking.root_window->stacking = &stacking;<br>
+       stacking.root_window->child_window = NULL;<br>
+<br>
 #ifdef HAVE_PANGO<br>
        g_type_init();<br>
 #endif<br>
@@ -300,11 +359,11 @@ main(int argc, char *argv[])<br>
<br>
        display_set_user_data(stacking.display, &stacking);<br>
<br>
-       stacking.root_window = new_window(&stacking, NULL);<br>
+       stacking.root_window->window = new_window(&stacking, NULL);<br>
<br>
        display_run(stacking.display);<br>
<br>
-       window_destroy(stacking.root_window);<br>
+       window_destroy(stacking.root_window->window);<br>
        display_destroy(stacking.display);<br>
<br>
        return 0;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature"><div dir="ltr"><font>Regards,<br>
<br>
<i><b>Manuel BACHMANN</b><br>
Tizen Project<br>
VANNES-FR</i><br>
</font></div></div>
</div>