From 58371937aa342265a9780e7d007fcf274635079f Mon Sep 17 00:00:00 2001 From: fliep Date: Wed, 13 May 2009 21:40:04 +0000 Subject: [PATCH] Correctly handles what happens when a window that is the key window of another window is closed. --- src/chimara-glk.c | 34 ++++++++++++++++++++++++++-------- src/window.c | 28 +++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/chimara-glk.c b/src/chimara-glk.c index b762924..3e2dabe 100644 --- a/src/chimara-glk.c +++ b/src/chimara-glk.c @@ -189,16 +189,24 @@ request_recurse(winid_t win, GtkRequisition *requisition, guint spacing) switch(win->split_method & winmethod_DirMask) { case winmethod_Left: - child1.width = win->constraint_size * win->key_window->unit_width; + child1.width = win->key_window? + win->constraint_size * win->key_window->unit_width + : 0; break; case winmethod_Right: - child2.width = win->constraint_size * win->key_window->unit_width; + child2.width = win->key_window? + win->constraint_size * win->key_window->unit_width + : 0; break; case winmethod_Above: - child1.height = win->constraint_size * win->key_window->unit_height; + child1.height = win->key_window? + win->constraint_size * win->key_window->unit_height + : 0; break; case winmethod_Below: - child2.height = win->constraint_size * win->key_window->unit_height; + child2.height = win->key_window? + win->constraint_size * win->key_window->unit_height + : 0; break; } } @@ -260,19 +268,29 @@ allocate_recurse(winid_t win, GtkAllocation *allocation, guint spacing) if((win->split_method & winmethod_DivisionMask) == winmethod_Fixed) { + /* If the key window has been closed, then default to 0; otherwise + use the key window to determine the size */ switch(win->split_method & winmethod_DirMask) { case winmethod_Left: - child1.width = CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - spacing); + child1.width = win->key_window? + CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - spacing) + : 0; break; case winmethod_Right: - child2.width = CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - spacing); + child2.width = win->key_window? + CLAMP(win->constraint_size * win->key_window->unit_width, 0, allocation->width - spacing) + : 0; break; case winmethod_Above: - child1.height = CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - spacing); + child1.height = win->key_window? + CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - spacing) + : 0; break; case winmethod_Below: - child2.height = CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - spacing); + child2.height = win->key_window? + CLAMP(win->constraint_size * win->key_window->unit_height, 0, allocation->height - spacing) + : 0; break; } } diff --git a/src/window.c b/src/window.c index 45054e0..bac8e18 100644 --- a/src/window.c +++ b/src/window.c @@ -514,12 +514,15 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, gdk_threads_leave(); - /* For text grid windows, wait until GTK draws the window (see note in glk_window_get_size() ), calculate the size and fill the buffer with blanks. */ + /* For blank or pair windows, this is almost a no-op. For text grid and + text buffer windows, this will wait for GTK to draw the window. Otherwise, + opening a window and getting its size immediately will give you the wrong + size. */ + glk_window_get_size(win, NULL, NULL); + + /* For text grid windows, fill the buffer with blanks. */ if(wintype == wintype_TextGrid) { - /* Force the window to be drawn and cache its size */ - glk_window_get_size(win, NULL, NULL); - /* Create the cursor position mark */ gdk_threads_enter(); GtkTextIter begin; @@ -535,6 +538,17 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, return win; } +/* 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 @@ -629,7 +643,11 @@ glk_window_close(winid_t win, stream_result_t *result) { VALID_WINDOW(win, return); - /* First close all the window streams and destroy the widgets of this window + /* If any pair windows have this window or its children as a key window, + set their key window to NULL */ + g_node_traverse(glk_data->root_window, G_IN_ORDER, G_TRAVERSE_NON_LEAVES, -1, remove_key_windows, win); + + /* Close all the window streams and destroy the widgets of this window and below, before trashing the window tree */ destroy_windows_below(win, result); -- 2.30.2