mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-04-11 16:18:06 -05:00
Try to ensure term_size() after win_resize_request().
When the terminal asks its TermWin for a resize, the resize operation happens asynchronously (or can do), and sooner or later, the terminal will see a term_size() telling it the resize has actually taken effect. If the resize _doesn't_ take effect for any reason - e.g. because the window is maximised, or because the X11 window manager is a tiling one which will refuse requests to change the window size anyway - then the terminal never got any explicit notification of refusal to resize. Now it should, in as many cases as I can arrange. One obvious case of this is the early exit I recently added to gtkwin_request_resize() when the window is known to be in a maximised or tiled state preventing a resize: in that situation, when our own code knows we're not even attempting the resize, we also queue a toplevel callback to tell the terminal so. The more interesting case is when the request is refused for a reason GTK _didn't_ know in advance, e.g. because the user is running an X11 tiling window manager such as i3, which generally refuses windows' resize requests. In X11, if a window manager refuses an attempt to change the window's size via ConfigureWindow, ICCCM says it should respond by sending a synthetic ConfigureNotify event restating the same size. Such no-op configure events do reach the "configure_event" handler in a GTK program, but they weren't previously getting as far as term_size(), because the call to term_size() was triggered from the GTK "size_allocate" event on the GtkDrawingArea inside the window (via drawing_area_setup()), so GTK would detect that nothing had changed. Now we queue a last-ditch toplevel callback which ensures that if the configure event doesn't also cause a size_allocate and a call to drawing_area_setup(), then we cause one of our own once the dust has settled. And drawing_area_setup(), in turn, now unconditionally calls term_size() even if the size is the same as it was last time, instead of taking an early exit. (It still does take an early exit to avoid unnecessary faffing with Cairo surfaces etc, but _after_ term_size()). This won't be 100% reliable, because it's the window manager's responsibility to send those synthetic ConfigureNotify events, and a window manager is a fallible process which could get into a stuck state. But it covers all the cases I know of that _can_ be sensibly covered - so now, when terminal.c asks the front end to resize the window, it ought to find out in a timely manner whether or not that has happened, in _almost_ all cases.
This commit is contained in:
parent
be0cea7130
commit
19b12ee56c
@ -89,6 +89,7 @@ struct GtkFrontend {
|
||||
gboolean sbar_visible;
|
||||
gboolean drawing_area_got_size, drawing_area_realised;
|
||||
gboolean drawing_area_setup_needed;
|
||||
bool drawing_area_setup_called;
|
||||
GtkBox *hbox;
|
||||
GtkAdjustment *sbar_adjust;
|
||||
GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,
|
||||
@ -700,7 +701,6 @@ static void draw_backing_rect(GtkFrontend *inst);
|
||||
static void drawing_area_setup(GtkFrontend *inst, int width, int height)
|
||||
{
|
||||
int w, h, new_scale;
|
||||
bool need_size = false;
|
||||
|
||||
/*
|
||||
* See if the terminal size has changed.
|
||||
@ -716,11 +716,7 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height)
|
||||
conf_set_int(inst->conf, CONF_width, inst->width);
|
||||
conf_set_int(inst->conf, CONF_height, inst->height);
|
||||
/*
|
||||
* We'll need to tell terminal.c about the resize below.
|
||||
*/
|
||||
need_size = true;
|
||||
/*
|
||||
* And we must refresh the window's backing image.
|
||||
* We must refresh the window's backing image.
|
||||
*/
|
||||
inst->drawing_area_setup_needed = true;
|
||||
}
|
||||
@ -742,10 +738,23 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height)
|
||||
inst->drawing_area_setup_needed = true;
|
||||
|
||||
/*
|
||||
* This event might be spurious; some GTK setups have been known
|
||||
* to call it when nothing at all has changed. Check if we have
|
||||
* any reason to proceed.
|
||||
* GTK will sometimes send us configure events when nothing about
|
||||
* the window size has actually changed. In some situations this
|
||||
* can happen quite often, so it's a worthwhile optimisation to
|
||||
* detect that situation and avoid the expensive reinitialisation
|
||||
* of the backing surface / image, and so on.
|
||||
*
|
||||
* However, we must still communicate to the terminal that we
|
||||
* received a resize event, because sometimes a trivial resize
|
||||
* event (to the same size we already were) is a signal from the
|
||||
* window system that a _nontrivial_ resize we recently asked for
|
||||
* has failed to happen.
|
||||
*/
|
||||
|
||||
inst->drawing_area_setup_called = true;
|
||||
if (inst->term)
|
||||
term_size(inst->term, h, w, conf_get_int(inst->conf, CONF_savelines));
|
||||
|
||||
if (!inst->drawing_area_setup_needed)
|
||||
return;
|
||||
|
||||
@ -776,10 +785,6 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height)
|
||||
|
||||
draw_backing_rect(inst);
|
||||
|
||||
if (need_size && inst->term) {
|
||||
term_size(inst->term, h, w, conf_get_int(inst->conf, CONF_savelines));
|
||||
}
|
||||
|
||||
if (inst->term)
|
||||
term_invalidate(inst->term);
|
||||
|
||||
@ -806,6 +811,14 @@ static void drawing_area_setup_simple(GtkFrontend *inst)
|
||||
drawing_area_setup(inst, alloc.width, alloc.height);
|
||||
}
|
||||
|
||||
static void drawing_area_setup_cb(void *vctx)
|
||||
{
|
||||
GtkFrontend *inst = (GtkFrontend *)vctx;
|
||||
|
||||
if (!inst->drawing_area_setup_called)
|
||||
drawing_area_setup_simple(inst);
|
||||
}
|
||||
|
||||
static void area_realised(GtkWidget *widget, GtkFrontend *inst)
|
||||
{
|
||||
inst->drawing_area_realised = true;
|
||||
@ -844,6 +857,10 @@ static gboolean window_configured(
|
||||
term_notify_window_pos(inst->term, event->x, event->y);
|
||||
term_notify_window_size_pixels(
|
||||
inst->term, event->width, event->height);
|
||||
if (inst->drawing_area_realised && inst->drawing_area_got_size) {
|
||||
inst->drawing_area_setup_called = false;
|
||||
queue_toplevel_callback(drawing_area_setup_cb, inst);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2450,6 +2467,14 @@ static void compute_whole_window_size(GtkFrontend *inst,
|
||||
int *wpix, int *hpix);
|
||||
#endif
|
||||
|
||||
static void gtkwin_deny_term_resize(void *vctx)
|
||||
{
|
||||
GtkFrontend *inst = (GtkFrontend *)vctx;
|
||||
if (inst->term)
|
||||
term_size(inst->term, inst->term->rows, inst->term->cols,
|
||||
inst->term->savelines);
|
||||
}
|
||||
|
||||
static void gtkwin_request_resize(TermWin *tw, int w, int h)
|
||||
{
|
||||
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
|
||||
@ -2494,6 +2519,7 @@ static void gtkwin_request_resize(TermWin *tw, int w, int h)
|
||||
GDK_WINDOW_STATE_LEFT_TILED |
|
||||
#endif
|
||||
0)) {
|
||||
queue_toplevel_callback(gtkwin_deny_term_resize, inst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user