1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05:00

Rework window geometry to avoid using geometry_widget.

Partly this is because the geometry_widget functionality is going away
in a later version of GTK3, so sooner or later we'll need not to be
using it anyway. But also, it turns out that GTK 3's geometry
calculations have the unfortunate effect of setting the window's base
and min heights to values that are not congruent mod height_increment
(because the former is the value we gave, but the latter is based on
the minimum height of the scrollbar), which confuses at least one
window manager (xfwm4) and causes the window to be created one row too
small.

So I've redone all the geometry computations my own way, based on the
knowledge that the only widgets visible in the top-level window are
the drawing area and the scrollbar and I know how both of those
behave, and taking care to keep base_height and min_height congruent
to avoid that xfwm4 bug.
This commit is contained in:
Simon Tatham
2016-03-29 13:42:54 +01:00
parent df93419ae5
commit ad87950539

View File

@ -56,6 +56,7 @@ struct clipboard_data_instance;
struct gui_data {
GtkWidget *window, *area, *sbar;
gboolean sbar_visible;
GtkBox *hbox;
GtkAdjustment *sbar_adjust;
GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,
@ -2846,6 +2847,15 @@ void scrollbar_moved(GtkAdjustment *adj, gpointer data)
term_scroll(inst->term, 1, (int)gtk_adjustment_get_value(adj));
}
static void show_scrollbar(struct gui_data *inst, gboolean visible)
{
inst->sbar_visible = visible;
if (visible)
gtk_widget_show(inst->sbar);
else
gtk_widget_hide(inst->sbar);
}
void sys_cursor(void *frontend, int x, int y)
{
/*
@ -3599,17 +3609,65 @@ char *setup_fonts_ucs(struct gui_data *inst)
void set_geom_hints(struct gui_data *inst)
{
GdkGeometry geom;
gint flags;
/*
* 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 the scrollbar in a
* moment.
*/
flags = GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC;
geom.min_width = inst->font_width + 2*inst->window_border;
geom.min_height = inst->font_height + 2*inst->window_border;
geom.max_width = geom.max_height = -1;
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;
geom.min_aspect = geom.max_aspect = 0;
gtk_window_set_geometry_hints(GTK_WINDOW(inst->window), inst->area, &geom,
GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE |
GDK_HINT_RESIZE_INC);
/*
* 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;
}
gtk_window_set_geometry_hints(GTK_WINDOW(inst->window),
NULL, &geom, flags);
}
void clear_scrollback_menuitem(GtkMenuItem *item, gpointer data)
@ -3732,16 +3790,16 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
}
}
need_size = FALSE;
/*
* If the scrollbar needs to be shown, hidden, or moved
* from one end to the other of the window, do so now.
*/
if (conf_get_int(oldconf, CONF_scrollbar) !=
conf_get_int(newconf, CONF_scrollbar)) {
if (conf_get_int(newconf, CONF_scrollbar))
gtk_widget_show(inst->sbar);
else
gtk_widget_hide(inst->sbar);
show_scrollbar(inst, conf_get_int(newconf, CONF_scrollbar));
need_size = TRUE;
}
if (conf_get_int(oldconf, CONF_scrollbar_on_left) !=
conf_get_int(newconf, CONF_scrollbar_on_left)) {
@ -3762,7 +3820,6 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
* Redo the whole tangled fonts and Unicode mess if
* necessary.
*/
need_size = FALSE;
if (strcmp(conf_get_fontspec(oldconf, CONF_font)->name,
conf_get_fontspec(newconf, CONF_font)->name) ||
strcmp(conf_get_fontspec(oldconf, CONF_boldfont)->name,
@ -4139,23 +4196,6 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string)
init_clipboard(inst);
set_geom_hints(inst);
#if GTK_CHECK_VERSION(3,0,0)
gtk_window_set_default_geometry(GTK_WINDOW(inst->window),
inst->width, inst->height);
#else
{
int w = inst->font_width * inst->width + 2*inst->window_border;
int h = inst->font_height * inst->height + 2*inst->window_border;
#if GTK_CHECK_VERSION(2,0,0)
gtk_widget_set_size_request(inst->area, w, h);
#else
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), w, h);
#endif
}
#endif
inst->sbar_adjust = GTK_ADJUSTMENT(gtk_adjustment_new(0,0,0,0,0,0));
inst->sbar = gtk_vscrollbar_new(inst->sbar_adjust);
inst->hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
@ -4173,12 +4213,26 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string)
gtk_container_add(GTK_CONTAINER(inst->window), GTK_WIDGET(inst->hbox));
gtk_widget_show(inst->area);
if (conf_get_int(inst->conf, CONF_scrollbar))
gtk_widget_show(inst->sbar);
else
gtk_widget_hide(inst->sbar);
show_scrollbar(inst, conf_get_int(inst->conf, CONF_scrollbar));
gtk_widget_show(GTK_WIDGET(inst->hbox));
set_geom_hints(inst);
#if GTK_CHECK_VERSION(3,0,0)
gtk_window_set_default_geometry(GTK_WINDOW(inst->window),
inst->width, inst->height);
#else
{
int w = inst->font_width * inst->width + 2*inst->window_border;
int h = inst->font_height * inst->height + 2*inst->window_border;
#if GTK_CHECK_VERSION(2,0,0)
gtk_widget_set_size_request(inst->area, w, h);
#else
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), w, h);
#endif
}
#endif
#if GTK_CHECK_VERSION(2,0,0)
if (inst->geometry) {
gtk_window_parse_geometry(GTK_WINDOW(inst->window), inst->geometry);