From 696550a5f286687deb3f50d5966d67eb9cd11fb7 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 7 Feb 2021 19:59:21 +0000 Subject: [PATCH] Flip direction of window pos/size queries. Similarly to other recent changes, the frontend now proactively keeps Terminal up to date with the current position and size of the terminal window, so that escape-sequence queries can be answered immediately from the Terminal's own internal data structures without needing a call back to the frontend. Mostly this has let me remove explicit window-system API calls that retrieve the window position and size, in favour of having the front ends listen for WM_MOVE / WM_SIZE / ConfigureNotify events and track the position and size that way. One exception is that the window pixel size is still requested by Seat via a callback, to put in the wire-encoded termios settings. That won't be happening very much, so I'm leaving it this way round for the moment. --- fuzzterm.c | 4 --- putty.h | 11 ++------- terminal.c | 26 +++++++++++++++----- terminal.h | 2 ++ unix/gtkwin.c | 63 ++++++++++++++++++------------------------------ windows/window.c | 54 +++++++++++++++++------------------------ 6 files changed, 70 insertions(+), 90 deletions(-) diff --git a/fuzzterm.c b/fuzzterm.c index 83858f7c..c5c29ef4 100644 --- a/fuzzterm.c +++ b/fuzzterm.c @@ -94,8 +94,6 @@ static void fuzz_set_zorder(TermWin *tw, bool top) {} static void fuzz_palette_set(TermWin *tw, unsigned start, unsigned ncolours, const rgb *colours) {} static void fuzz_palette_get_overrides(TermWin *tw) {} -static void fuzz_get_pos(TermWin *tw, int *x, int *y) { *x = *y = 0; } -static void fuzz_get_pixels(TermWin *tw, int *x, int *y) { *x = *y = 0; } static const TermWinVtable fuzz_termwin_vt = { .setup_draw_ctx = fuzz_setup_draw_ctx, @@ -120,8 +118,6 @@ static const TermWinVtable fuzz_termwin_vt = { .set_zorder = fuzz_set_zorder, .palette_set = fuzz_palette_set, .palette_get_overrides = fuzz_palette_get_overrides, - .get_pos = fuzz_get_pos, - .get_pixels = fuzz_get_pixels, }; void ldisc_send(Ldisc *ldisc, const void *buf, int len, bool interactive) {} diff --git a/putty.h b/putty.h index 55751943..54a072e4 100644 --- a/putty.h +++ b/putty.h @@ -1282,9 +1282,6 @@ struct TermWinVtable { * colours stored in Conf. The front end should set any it cares * about by calling term_palette_override. */ void (*palette_get_overrides)(TermWin *); - - void (*get_pos)(TermWin *, int *x, int *y); - void (*get_pixels)(TermWin *, int *x, int *y); }; static inline bool win_setup_draw_ctx(TermWin *win) @@ -1327,8 +1324,6 @@ static inline void win_set_icon_title(TermWin *win, const char *icontitle) { win->vt->set_icon_title(win, icontitle); } static inline void win_set_minimised(TermWin *win, bool minimised) { win->vt->set_minimised(win, minimised); } -static inline bool win_is_minimised(TermWin *win) -{ return win->vt->is_minimised(win); } static inline void win_set_maximised(TermWin *win, bool maximised) { win->vt->set_maximised(win, maximised); } static inline void win_move(TermWin *win, int x, int y) @@ -1340,10 +1335,6 @@ static inline void win_palette_set( { win->vt->palette_set(win, start, ncolours, colours); } static inline void win_palette_get_overrides(TermWin *win) { win->vt->palette_get_overrides(win); } -static inline void win_get_pos(TermWin *win, int *x, int *y) -{ win->vt->get_pos(win, x, y); } -static inline void win_get_pixels(TermWin *win, int *x, int *y) -{ win->vt->get_pixels(win, x, y); } /* * Global functions not specific to a connection instance. @@ -1773,6 +1764,8 @@ void term_get_cursor_position(Terminal *term, int *x, int *y); void term_setup_window_titles(Terminal *term, const char *title_hostname); void term_notify_minimised(Terminal *term, bool minimised); void term_notify_palette_overrides_changed(Terminal *term); +void term_notify_window_pos(Terminal *term, int x, int y); +void term_notify_window_size_pixels(Terminal *term, int x, int y); void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb); typedef enum SmallKeypadKey { diff --git a/terminal.c b/terminal.c index 3b37b497..caebe13d 100644 --- a/terminal.c +++ b/terminal.c @@ -1918,6 +1918,8 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win) term->window_title = dupstr(""); term->icon_title = dupstr(""); term->minimised = false; + term->winpos_x = term->winpos_y = 0; + term->winpixsize_x = term->winpixsize_y = 0; palette_reset(term, false); @@ -4498,7 +4500,7 @@ static void term_out(Terminal *term) compatibility(OTHER); switch (term->esc_args[0]) { - int x, y, len; + int len; char buf[80]; const char *p; case 1: @@ -4557,17 +4559,17 @@ static void term_out(Terminal *term) break; case 13: if (term->ldisc) { - win_get_pos(term->win, &x, &y); len = sprintf(buf, "\033[3;%u;%ut", - (unsigned)x, - (unsigned)y); + term->winpos_x, + term->winpos_y); ldisc_send(term->ldisc, buf, len, false); } break; case 14: if (term->ldisc) { - win_get_pixels(term->win, &x, &y); - len = sprintf(buf, "\033[4;%d;%dt", y, x); + len = sprintf(buf, "\033[4;%u;%ut", + term->winpixsize_y, + term->winpixsize_x); ldisc_send(term->ldisc, buf, len, false); } break; @@ -7466,3 +7468,15 @@ void term_notify_palette_overrides_changed(Terminal *term) { palette_reset(term, true); } + +void term_notify_window_pos(Terminal *term, int x, int y) +{ + term->winpos_x = x; + term->winpos_y = y; +} + +void term_notify_window_size_pixels(Terminal *term, int x, int y) +{ + term->winpixsize_x = x; + term->winpixsize_y = y; +} diff --git a/terminal.h b/terminal.h index ed8a0da6..e64738e5 100644 --- a/terminal.h +++ b/terminal.h @@ -360,6 +360,8 @@ struct terminal_tag { /* The composite palette that we make out of the above */ rgb palette[OSC4_NCOLOURS]; + + unsigned winpos_x, winpos_y, winpixsize_x, winpixsize_y; }; static inline bool in_utf(Terminal *term) diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 012aad2f..06617645 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -350,7 +350,16 @@ static bool gtk_seat_is_utf8(Seat *seat) static bool gtk_seat_get_window_pixel_size(Seat *seat, int *w, int *h) { GtkFrontend *inst = container_of(seat, GtkFrontend, seat); - win_get_pixels(&inst->termwin, w, h); + /* + * I assume that when the GTK version of this call is available + * we should use it. Not sure how it differs from the GDK one, + * though. + */ +#if GTK_CHECK_VERSION(2,0,0) + gtk_window_get_size(GTK_WINDOW(inst->window), w, h); +#else + gdk_window_get_size(gtk_widget_get_window(inst->window), w, h); +#endif return true; } @@ -561,42 +570,6 @@ static void gtkwin_set_maximised(TermWin *tw, bool maximised) #endif } -/* - * Report the window's position, for terminal reports. - */ -static void gtkwin_get_pos(TermWin *tw, int *x, int *y) -{ - GtkFrontend *inst = container_of(tw, GtkFrontend, termwin); - /* - * I assume that when the GTK version of this call is available - * we should use it. Not sure how it differs from the GDK one, - * though. - */ -#if GTK_CHECK_VERSION(2,0,0) - gtk_window_get_position(GTK_WINDOW(inst->window), x, y); -#else - gdk_window_get_position(gtk_widget_get_window(inst->window), x, y); -#endif -} - -/* - * Report the window's pixel size, for terminal reports. - */ -static void gtkwin_get_pixels(TermWin *tw, int *x, int *y) -{ - GtkFrontend *inst = container_of(tw, GtkFrontend, termwin); - /* - * I assume that when the GTK version of this call is available - * we should use it. Not sure how it differs from the GDK one, - * though. - */ -#if GTK_CHECK_VERSION(2,0,0) - gtk_window_get_size(GTK_WINDOW(inst->window), x, y); -#else - gdk_window_get_size(gtk_widget_get_window(inst->window), x, y); -#endif -} - /* * Find out whether a dialog box already exists for this window in a * particular DialogSlot. If it does, uniconify it (if we can) and @@ -842,6 +815,18 @@ static void area_check_scale(GtkFrontend *inst) } #endif +static gboolean window_configured( + GtkWidget *widget, GdkEventConfigure *event, gpointer data) +{ + GtkFrontend *inst = (GtkFrontend *)data; + if (inst->term) { + term_notify_window_pos(inst->term, event->x, event->y); + term_notify_window_size_pixels( + inst->term, event->width, event->height); + } + return false; +} + #if GTK_CHECK_VERSION(3,10,0) static gboolean area_configured( GtkWidget *widget, GdkEventConfigure *event, gpointer data) @@ -5053,8 +5038,6 @@ static const TermWinVtable gtk_termwin_vt = { .set_zorder = gtkwin_set_zorder, .palette_set = gtkwin_palette_set, .palette_get_overrides = gtkwin_palette_get_overrides, - .get_pos = gtkwin_get_pos, - .get_pixels = gtkwin_get_pixels, }; void new_session_window(Conf *conf, const char *geometry_string) @@ -5263,6 +5246,8 @@ void new_session_window(Conf *conf, const char *geometry_string) G_CALLBACK(area_realised), inst); g_signal_connect(G_OBJECT(inst->area), "size_allocate", G_CALLBACK(area_size_allocate), inst); + g_signal_connect(G_OBJECT(inst->window), "configure_event", + G_CALLBACK(window_configured), inst); #if GTK_CHECK_VERSION(3,10,0) g_signal_connect(G_OBJECT(inst->area), "configure_event", G_CALLBACK(area_configured), inst); diff --git a/windows/window.c b/windows/window.c index 95473b1b..415b0485 100644 --- a/windows/window.c +++ b/windows/window.c @@ -242,8 +242,6 @@ static void wintw_move(TermWin *, int x, int y); static void wintw_set_zorder(TermWin *, bool top); static void wintw_palette_set(TermWin *, unsigned, unsigned, const rgb *); static void wintw_palette_get_overrides(TermWin *); -static void wintw_get_pos(TermWin *, int *x, int *y); -static void wintw_get_pixels(TermWin *, int *x, int *y); static const TermWinVtable windows_termwin_vt = { .setup_draw_ctx = wintw_setup_draw_ctx, @@ -268,8 +266,6 @@ static const TermWinVtable windows_termwin_vt = { .set_zorder = wintw_set_zorder, .palette_set = wintw_palette_set, .palette_get_overrides = wintw_palette_get_overrides, - .get_pos = wintw_get_pos, - .get_pixels = wintw_get_pixels, }; static TermWin wintw[1]; @@ -295,12 +291,6 @@ static char *win_seat_get_ttymode(Seat *seat, const char *mode) return term_get_ttymode(term, mode); } -static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y) -{ - win_get_pixels(wintw, x, y); - return true; -} - static StripCtrlChars *win_seat_stripctrl_new( Seat *seat, BinarySink *bs_out, SeatInteractionContext sic) { @@ -318,6 +308,7 @@ static void win_seat_update_specials_menu(Seat *seat); static void win_seat_set_busy_status(Seat *seat, BusyStatus status); static bool win_seat_set_trust_status(Seat *seat, bool trusted); static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y); +static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y); static const SeatVtable win_seat_vt = { .output = win_seat_output, @@ -2870,6 +2861,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, fullscr_on_max = true; break; case WM_MOVE: + term_notify_window_pos(term, LOWORD(lParam), HIWORD(lParam)); sys_cursor_update(); break; case WM_SIZE: @@ -2884,6 +2876,17 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, LOWORD(lParam), HIWORD(lParam)); #endif term_notify_minimised(term, wParam == SIZE_MINIMIZED); + { + /* + * WM_SIZE's lParam tells us the size of the client area. + * But historic PuTTY practice is that we want to tell the + * terminal the size of the overall window. + */ + RECT r; + GetWindowRect(hwnd, &r); + term_notify_window_size_pixels( + term, r.right - r.left, r.bottom - r.top); + } if (wParam == SIZE_MINIMIZED) SetWindowText(hwnd, conf_get_bool(conf, CONF_win_name_always) ? @@ -5513,28 +5516,6 @@ static void wintw_set_maximised(TermWin *tw, bool maximised) } } -/* - * Report the window's position, for terminal reports. - */ -static void wintw_get_pos(TermWin *tw, int *x, int *y) -{ - RECT r; - GetWindowRect(wgs.term_hwnd, &r); - *x = r.left; - *y = r.top; -} - -/* - * Report the window's pixel size, for terminal reports. - */ -static void wintw_get_pixels(TermWin *tw, int *x, int *y) -{ - RECT r; - GetWindowRect(wgs.term_hwnd, &r); - *x = r.right - r.left; - *y = r.bottom - r.top; -} - /* * See if we're in full-screen mode. */ @@ -5693,3 +5674,12 @@ static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y) term_get_cursor_position(term, x, y); return true; } + +static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y) +{ + RECT r; + GetWindowRect(wgs.term_hwnd, &r); + *x = r.right - r.left; + *y = r.bottom - r.top; + return true; +}