X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=src%2Fchimara-glk.c;h=57846cb25c9b40f30da265a94bb6978e93e9253a;hb=aa0f8e10254824b85a93d67030a9f014e2cbf4f1;hp=1a449b5ea88b3e4eee6554963d9c76e59e99f710;hpb=cfe519635eddc394e8690a62ca9e47a00384588e;p=projects%2Fchimara%2Fchimara.git diff --git a/src/chimara-glk.c b/src/chimara-glk.c index 1a449b5..57846cb 100644 --- a/src/chimara-glk.c +++ b/src/chimara-glk.c @@ -1,5 +1,6 @@ /* licensing and copyright information here */ +#include #include #include #include @@ -164,6 +165,59 @@ chimara_glk_finalize(GObject *object) G_OBJECT_CLASS(chimara_glk_parent_class)->finalize(object); } +/* Internal function: Recursively get the Glk window tree's size request */ +static void +request_recurse(winid_t win, GtkRequisition *requisition) +{ + if(win->type == wintype_Pair) + { + /* Get children's size requests */ + GtkRequisition child1, child2; + request_recurse(win->window_node->children->data, &child1); + request_recurse(win->window_node->children->next->data, &child2); + + /* If the split is fixed, get the size of the fixed child */ + if((win->split_method & winmethod_DivisionMask) == winmethod_Fixed) + { + switch(win->split_method & winmethod_DirMask) + { + case winmethod_Left: + child1.width = win->constraint_size * win->key_window->unit_width; + break; + case winmethod_Right: + child2.width = win->constraint_size * win->key_window->unit_width; + break; + case winmethod_Above: + child1.height = win->constraint_size * win->key_window->unit_height; + break; + case winmethod_Below: + child2.height = win->constraint_size * win->key_window->unit_height; + break; + } + } + + /* Add the children's requests */ + switch(win->split_method & winmethod_DirMask) + { + case winmethod_Left: + case winmethod_Right: + requisition->width = child1.width + child2.width; + requisition->height = MAX(child1.height, child2.height); + break; + case winmethod_Above: + case winmethod_Below: + requisition->width = MAX(child1.width, child2.width); + requisition->height = child1.height + child2.height; + break; + } + } + + /* For non-pair windows, just use the size that GTK requests */ + else + gtk_widget_size_request(win->frame, requisition); +} + +/* Overrides gtk_widget_size_request */ static void chimara_glk_size_request(GtkWidget *widget, GtkRequisition *requisition) { @@ -174,16 +228,114 @@ chimara_glk_size_request(GtkWidget *widget, GtkRequisition *requisition) ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(widget); /* For now, just pass the size request on to the root Glk window */ - if(priv->root_window) { - GtkWidget *child = ((winid_t)(priv->root_window->data))->frame; - if(GTK_WIDGET_VISIBLE(child)) - gtk_widget_size_request(child, requisition); - } else { - requisition->width = CHIMARA_GLK_MIN_WIDTH; - requisition->height = CHIMARA_GLK_MIN_HEIGHT; + if(priv->root_window) + { + request_recurse(priv->root_window->data, requisition); + requisition->width += 2 * GTK_CONTAINER(widget)->border_width; + requisition->height += 2 * GTK_CONTAINER(widget)->border_width; + } + else + { + requisition->width = CHIMARA_GLK_MIN_WIDTH + 2 * GTK_CONTAINER(widget)->border_width; + requisition->height = CHIMARA_GLK_MIN_HEIGHT + 2 * GTK_CONTAINER(widget)->border_width; } } +/* Recursively give the Glk windows their allocated space */ +static void +allocate_recurse(winid_t win, GtkAllocation *allocation) +{ + if(win->type == wintype_Pair) + { + GtkAllocation child1, child2; + child1.x = allocation->x; + child1.y = allocation->y; + + if((win->split_method & winmethod_DivisionMask) == winmethod_Fixed) + { + switch(win->split_method & winmethod_DirMask) + { + case winmethod_Left: + child1.width = win->constraint_size * win->key_window->unit_width; + if(child1.width > allocation->width) + child1.width = allocation->width; + break; + case winmethod_Right: + child2.width = win->constraint_size * win->key_window->unit_width; + if(child2.width > allocation->width) + child2.width = allocation->width; + break; + case winmethod_Above: + child1.height = win->constraint_size * win->key_window->unit_height; + if(child1.height > allocation->height) + child1.height = allocation->height; + break; + case winmethod_Below: + child2.height = win->constraint_size * win->key_window->unit_height; + if(child2.height > allocation->height) + child2.height = allocation->height; + break; + } + } + else /* proportional */ + { + switch(win->split_method & winmethod_DirMask) + { + case winmethod_Left: + child1.width = (glui32)ceil((win->constraint_size / 100.0) * allocation->width); + break; + case winmethod_Right: + child2.width = (glui32)ceil((win->constraint_size / 100.0) * allocation->width); + break; + case winmethod_Above: + child1.height = (glui32)ceil((win->constraint_size / 100.0) * allocation->height); + break; + case winmethod_Below: + child2.height = (glui32)ceil((win->constraint_size / 100.0) * allocation->height); + break; + } + } + + /* Fill in the rest of the size requisitions according to the child specified above */ + switch(win->split_method & winmethod_DirMask) + { + case winmethod_Left: + child2.width = allocation->width - child1.width; + child2.x = child1.x + child1.width; + child2.y = child1.y; + child1.height = child2.height = allocation->height; + break; + case winmethod_Right: + child1.width = allocation->width - child2.width; + child2.x = child1.x + child1.width; + child2.y = child1.y; + child1.height = child2.height = allocation->height; + break; + case winmethod_Above: + child2.height = allocation->height - child1.height; + child2.x = child1.x; + child2.y = child1.y + child1.height; + child1.width = child2.width = allocation->width; + break; + case winmethod_Below: + child1.height = allocation->height - child2.height; + child2.x = child1.x; + child2.y = child1.y + child1.height; + child1.width = child2.width = allocation->width; + break; + } + + /* Recurse */ + allocate_recurse(win->window_node->children->data, &child1); + allocate_recurse(win->window_node->children->next->data, &child2); + } + + /* For non-pair windows, just give them the size */ + else + gtk_widget_size_allocate(win->frame, allocation); +} + +/* Overrides gtk_widget_size_allocate */ static void chimara_glk_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { @@ -196,25 +348,43 @@ chimara_glk_size_allocate(GtkWidget *widget, GtkAllocation *allocation) widget->allocation = *allocation; if(priv->root_window) { - GtkWidget *child = ((winid_t)(priv->root_window->data))->frame; - if(GTK_WIDGET_VISIBLE(child)) - gtk_widget_size_allocate(child, allocation); - } + GtkAllocation child; + child.x = allocation->x + GTK_CONTAINER(widget)->border_width; + child.y = allocation->y + GTK_CONTAINER(widget)->border_width; + child.width = allocation->width - 2 * GTK_CONTAINER(widget)->border_width; + child.height = allocation->height - 2 * GTK_CONTAINER(widget)->border_width; + allocate_recurse(priv->root_window->data, &child); + } } +/* Recursively invoke callback() on the GtkWidget of each non-pair window in the tree */ static void -chimara_glk_forall(GtkContainer *container, gboolean include_internals, - GtkCallback callback, gpointer callback_data) +forall_recurse(winid_t win, GtkCallback callback, gpointer callback_data) +{ + if(win->type == wintype_Pair) + { + forall_recurse(win->window_node->children->data, callback, callback_data); + forall_recurse(win->window_node->children->next->data, callback, callback_data); + } + else + (*callback)(win->frame, callback_data); +} + +/* Overrides gtk_container_forall */ +static void +chimara_glk_forall(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) { g_return_if_fail(container); g_return_if_fail(CHIMARA_IS_GLK(container)); ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(container); - if(priv->root_window) { - GtkWidget *child = ((winid_t)(priv->root_window->data))->frame; - (*callback)(child, callback_data); - } + /* All the children are "internal" */ + if(!include_internals) + return; + + if(priv->root_window) + forall_recurse(priv->root_window->data, callback, callback_data); } static void