<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>