+/* Internal function: if node's key window is closing_win or one of its
+ children, set node's key window to NULL. */
+static gboolean
+remove_key_windows(GNode *node, winid_t closing_win)
+{
+ winid_t win = (winid_t)node->data;
+ if(win->key_window && (win->key_window == closing_win || g_node_is_ancestor(closing_win->window_node, win->key_window->window_node)))
+ win->key_window = NULL;
+ return FALSE; /* Don't stop the traversal */
+}
+
+/* Internal function: destroy this window's GTK widgets, window streams,
+ and those of all its children */
+static void
+destroy_windows_below(winid_t win, stream_result_t *result)
+{
+ switch(win->type)
+ {
+ case wintype_Blank:
+ gdk_threads_enter();
+ gtk_widget_unparent(win->widget);
+ gdk_threads_leave();
+ break;
+
+ case wintype_TextGrid:
+ case wintype_TextBuffer:
+ gdk_threads_enter();
+ gtk_widget_unparent(win->frame);
+ gdk_threads_leave();
+ /* TODO: Cancel all input requests */
+ break;
+
+ case wintype_Pair:
+ destroy_windows_below(win->window_node->children->data, NULL);
+ destroy_windows_below(win->window_node->children->next->data, NULL);
+ break;
+
+ default:
+ ILLEGAL_PARAM("Unknown window type: %u", win->type);
+ return;
+ }
+ stream_close_common(win->window_stream, result);
+}
+
+/* Internal function: free the winid_t structure of this window and those of all its children */
+static void
+free_winids_below(winid_t win)
+{
+ if(win->type == wintype_Pair) {
+ free_winids_below(win->window_node->children->data);
+ free_winids_below(win->window_node->children->next->data);
+ }
+ win->magic = MAGIC_FREE;
+ g_free(win);
+}
+