Correctly handles what happens when a window that is the key window of another
authorfliep <fliep@ddfedd41-794f-dd11-ae45-00112f111e67>
Wed, 13 May 2009 21:40:04 +0000 (21:40 +0000)
committerfliep <fliep@ddfedd41-794f-dd11-ae45-00112f111e67>
Wed, 13 May 2009 21:40:04 +0000 (21:40 +0000)
window is closed.

src/chimara-glk.c
src/window.c

index b7629240b7cc4422b7e8b774003399c2cd2d48be..3e2dabecf20e1abed3494a729b73753902dd8cfd 100644 (file)
@@ -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;
                        }
                }
index 45054e0765fba3d537b4cb6f7643ea0a5829e341..bac8e18ce2c753dd2fc6b5db9d5ea2dadf7a4195 100644 (file)
@@ -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);