+#if GTK_CHECK_VERSION(3,0,0)
+struct find_app_menu_bar_ctx {
+ GtkWidget *area, *menubar;
+};
+static void find_app_menu_bar(GtkWidget *widget, gpointer data)
+{
+ struct find_app_menu_bar_ctx *ctx = (struct find_app_menu_bar_ctx *)data;
+ if (widget != ctx->area && GTK_IS_MENU_BAR(widget))
+ ctx->menubar = widget;
+}
+#endif
+
+static void compute_geom_hints(struct gui_data *inst, GdkGeometry *geom)
+{
+ /*
+ * Unused fields in geom.
+ */
+ geom->max_width = geom->max_height = -1;
+ geom->min_aspect = geom->max_aspect = 0;
+
+ /*
+ * Set up the geometry fields we care about, with reference to
+ * just the drawing area. We'll correct for other widgets in a
+ * moment.
+ */
+ geom->min_width = inst->font_width + 2*inst->window_border;
+ geom->min_height = inst->font_height + 2*inst->window_border;
+ geom->base_width = 2*inst->window_border;
+ geom->base_height = 2*inst->window_border;
+ geom->width_inc = inst->font_width;
+ geom->height_inc = inst->font_height;
+
+ /*
+ * If we've got a scrollbar visible, then we must include its
+ * width as part of the base and min width, and also ensure that
+ * our window's minimum height is at least the height required by
+ * the scrollbar.
+ *
+ * In the latter case, we must also take care to arrange that
+ * (geom->min_height - geom->base_height) is an integer multiple of
+ * geom->height_inc, because if it's not, then some window managers
+ * (we know of xfwm4) get confused, with the effect that they
+ * resize our window to a height based on min_height instead of
+ * base_height, which we then round down and the window ends up
+ * too short.
+ */
+ if (inst->sbar_visible) {
+ GtkRequisition req;
+ int min_sb_height;
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_get_preferred_size(inst->sbar, &req, NULL);
+#else
+ gtk_widget_size_request(inst->sbar, &req);
+#endif
+
+ /* Compute rounded-up scrollbar height. */
+ min_sb_height = req.height;
+ min_sb_height += geom->height_inc - 1;
+ min_sb_height -= ((min_sb_height - geom->base_height%geom->height_inc)
+ % geom->height_inc);
+
+ geom->min_width += req.width;
+ geom->base_width += req.width;
+ if (geom->min_height < min_sb_height)
+ geom->min_height = min_sb_height;
+ }
+
+#if GTK_CHECK_VERSION(3,0,0)
+ /*
+ * And if we're running a gtkapp.c based program and
+ * GtkApplicationWindow has given us a menu bar inside the window,
+ * then we must take that into account as well.
+ *
+ * In its unbounded wisdom, GtkApplicationWindow doesn't actually
+ * give us a direct function call to _find_ the menu bar widget.
+ * Fortunately, we can find it by enumerating the children of the
+ * top-level window and looking for one we didn't put there
+ * ourselves.
+ */
+ {
+ struct find_app_menu_bar_ctx actx, *ctx = &actx;
+ ctx->area = inst->area;
+ ctx->menubar = NULL;
+ gtk_container_foreach(GTK_CONTAINER(inst->window),
+ find_app_menu_bar, ctx);
+
+ if (ctx->menubar) {
+ GtkRequisition req;
+ int min_menu_width;
+ gtk_widget_get_preferred_size(ctx->menubar, NULL, &req);
+
+ /*
+ * This time, the height adjustment is easy (the menu bar
+ * sits above everything), but we have to take care with
+ * the _width_ to ensure we keep min_width and base_width
+ * congruent modulo width_inc.
+ */
+ geom->min_height += req.height;
+ geom->base_height += req.height;
+
+ min_menu_width = req.width;
+ min_menu_width += geom->width_inc - 1;
+ min_menu_width -=
+ ((min_menu_width - geom->base_width%geom->width_inc)
+ % geom->width_inc);
+ if (geom->min_width < min_menu_width)
+ geom->min_width = min_menu_width;
+ }
+ }
+#endif
+}
+