mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
The terminal window can now indicate that PuTTY is busy in various ways, by
changing its mouse pointer. Currently this is only used in the (slightly- arbitrarily-defined) "heavy" bits of SSH-2 key exchange. We override pointer hiding while PuTTY is busy, but preserve pointer-hiding state. Not yet implemented on the Mac. Also switch to frobbing window-class cursor in Windows rather than relying on SetCursor(). [originally from svn r5303]
This commit is contained in:
parent
9d9c0fcffc
commit
c9116974ac
@ -1499,6 +1499,14 @@ void set_title(void *frontend, char *title)
|
||||
SetWTitle(s->window, mactitle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by backend to indicate busy-ness
|
||||
*/
|
||||
void set_busy_status(void *frontend, int status)
|
||||
{
|
||||
/* FIXME do something */
|
||||
}
|
||||
|
||||
/*
|
||||
* set or clear the "raw mouse message" mode
|
||||
*/
|
||||
|
10
putty.h
10
putty.h
@ -647,6 +647,16 @@ int is_iconic(void *frontend);
|
||||
void get_window_pos(void *frontend, int *x, int *y);
|
||||
void get_window_pixels(void *frontend, int *x, int *y);
|
||||
char *get_window_title(void *frontend, int icon);
|
||||
/* Hint from backend to frontend about time-consuming operations.
|
||||
* Initial state is assumed to be BUSY_NOT. */
|
||||
enum {
|
||||
BUSY_NOT, /* Not busy, all user interaction OK */
|
||||
BUSY_WAITING, /* Waiting for something; local event loops still running
|
||||
so some local interaction (e.g. menus) OK, but network
|
||||
stuff is suspended */
|
||||
BUSY_CPU /* Locally busy (e.g. crypto); user interaction suspended */
|
||||
};
|
||||
void set_busy_status(void *frontend, int status);
|
||||
|
||||
void cleanup_exit(int);
|
||||
|
||||
|
7
ssh.c
7
ssh.c
@ -5142,16 +5142,19 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
|
||||
/*
|
||||
* Now generate and send e for Diffie-Hellman.
|
||||
*/
|
||||
set_busy_status(ssh->frontend, BUSY_CPU); /* this can take a while */
|
||||
s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2);
|
||||
s->pktout = ssh2_pkt_init(s->kex_init_value);
|
||||
ssh2_pkt_addmp(s->pktout, s->e);
|
||||
ssh2_pkt_send_noqueue(ssh, s->pktout);
|
||||
|
||||
set_busy_status(ssh->frontend, BUSY_WAITING); /* wait for server */
|
||||
crWaitUntil(pktin);
|
||||
if (pktin->type != s->kex_reply_value) {
|
||||
bombout(("expected key exchange reply packet from server"));
|
||||
crStop(0);
|
||||
}
|
||||
set_busy_status(ssh->frontend, BUSY_CPU); /* cogitate */
|
||||
ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
|
||||
s->f = ssh2_pkt_getmp(pktin);
|
||||
if (!s->f) {
|
||||
@ -5162,6 +5165,10 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
|
||||
|
||||
s->K = dh_find_K(ssh->kex_ctx, s->f);
|
||||
|
||||
/* We assume everything from now on will be quick, and it might
|
||||
* involve user interaction. */
|
||||
set_busy_status(ssh->frontend, BUSY_NOT);
|
||||
|
||||
sha_string(&ssh->exhash, s->hostkeydata, s->hostkeylen);
|
||||
if (ssh->kex == &ssh_diffiehellman_gex) {
|
||||
sha_uint32(&ssh->exhash, s->pbits);
|
||||
|
@ -64,7 +64,7 @@ struct gui_data {
|
||||
int is_wide;
|
||||
} fontinfo[4];
|
||||
int xpos, ypos, gotpos, gravity;
|
||||
GdkCursor *rawcursor, *textcursor, *blankcursor, *currcursor;
|
||||
GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor;
|
||||
GdkColor cols[NALLCOLOURS];
|
||||
GdkColormap *colmap;
|
||||
wchar_t *pastein_data;
|
||||
@ -76,6 +76,7 @@ struct gui_data {
|
||||
int width, height;
|
||||
int ignore_sbar;
|
||||
int mouseptr_visible;
|
||||
int busy_status;
|
||||
guint term_paste_idle_id;
|
||||
int alt_keycode;
|
||||
int alt_digits;
|
||||
@ -372,15 +373,34 @@ gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void update_mouseptr(struct gui_data *inst)
|
||||
{
|
||||
switch (inst->busy_status) {
|
||||
case BUSY_NOT:
|
||||
if (!inst->mouseptr_visible) {
|
||||
gdk_window_set_cursor(inst->area->window, inst->blankcursor);
|
||||
} else if (send_raw_mouse) {
|
||||
gdk_window_set_cursor(inst->area->window, inst->rawcursor);
|
||||
} else {
|
||||
gdk_window_set_cursor(inst->area->window, inst->textcursor);
|
||||
}
|
||||
break;
|
||||
case BUSY_WAITING: /* XXX can we do better? */
|
||||
case BUSY_CPU:
|
||||
/* We always display these cursors. */
|
||||
gdk_window_set_cursor(inst->area->window, inst->waitcursor);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_mouseptr(struct gui_data *inst, int show)
|
||||
{
|
||||
if (!inst->cfg.hide_mouseptr)
|
||||
show = 1;
|
||||
if (show)
|
||||
gdk_window_set_cursor(inst->area->window, inst->currcursor);
|
||||
else
|
||||
gdk_window_set_cursor(inst->area->window, inst->blankcursor);
|
||||
inst->mouseptr_visible = show;
|
||||
update_mouseptr(inst);
|
||||
}
|
||||
|
||||
void draw_backing_rect(struct gui_data *inst)
|
||||
@ -1227,6 +1247,13 @@ gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void set_busy_status(void *frontend, int status)
|
||||
{
|
||||
struct gui_data *inst = (struct gui_data *)frontend;
|
||||
inst->busy_status = status;
|
||||
update_mouseptr(inst);
|
||||
}
|
||||
|
||||
/*
|
||||
* set or clear the "raw mouse message" mode
|
||||
*/
|
||||
@ -1235,11 +1262,7 @@ void set_raw_mouse_mode(void *frontend, int activate)
|
||||
struct gui_data *inst = (struct gui_data *)frontend;
|
||||
activate = activate && !inst->cfg.no_mouse_rep;
|
||||
send_raw_mouse = activate;
|
||||
if (send_raw_mouse)
|
||||
inst->currcursor = inst->rawcursor;
|
||||
else
|
||||
inst->currcursor = inst->textcursor;
|
||||
show_mouseptr(inst, inst->mouseptr_visible);
|
||||
update_mouseptr(inst);
|
||||
}
|
||||
|
||||
void request_resize(void *frontend, int w, int h)
|
||||
@ -3310,6 +3333,7 @@ int pt_main(int argc, char **argv)
|
||||
inst = snew(struct gui_data);
|
||||
memset(inst, 0, sizeof(*inst));
|
||||
inst->alt_keycode = -1; /* this one needs _not_ to be zero */
|
||||
inst->busy_status = BUSY_NOT;
|
||||
|
||||
/* defer any child exit handling until we're ready to deal with
|
||||
* it */
|
||||
@ -3520,6 +3544,7 @@ int pt_main(int argc, char **argv)
|
||||
|
||||
inst->textcursor = make_mouse_ptr(inst, GDK_XTERM);
|
||||
inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
|
||||
inst->waitcursor = make_mouse_ptr(inst, GDK_WATCH);
|
||||
inst->blankcursor = make_mouse_ptr(inst, -1);
|
||||
make_mouse_ptr(inst, -2); /* clean up cursor font */
|
||||
inst->currcursor = inst->textcursor;
|
||||
|
@ -31,6 +31,10 @@ void cleanup_exit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void set_busy_status(void *frontend, int status)
|
||||
{
|
||||
}
|
||||
|
||||
void update_specials_menu(void *frontend)
|
||||
{
|
||||
}
|
||||
|
@ -33,6 +33,10 @@ void cleanup_exit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void set_busy_status(void *frontend, int status)
|
||||
{
|
||||
}
|
||||
|
||||
void notify_remote_exit(void *frontend)
|
||||
{
|
||||
}
|
||||
|
@ -177,6 +177,8 @@ static Mouse_Button lastbtn;
|
||||
static int send_raw_mouse = 0;
|
||||
static int wheel_accumulator = 0;
|
||||
|
||||
static int busy_status = BUSY_NOT;
|
||||
|
||||
static char *window_name, *icon_name;
|
||||
|
||||
static int compose_state = 0;
|
||||
@ -949,6 +951,50 @@ void update_specials_menu(void *frontend)
|
||||
}
|
||||
}
|
||||
|
||||
static void update_mouse_pointer(void)
|
||||
{
|
||||
LPTSTR curstype;
|
||||
int force_visible = FALSE;
|
||||
static int forced_visible = FALSE;
|
||||
switch (busy_status) {
|
||||
case BUSY_NOT:
|
||||
if (send_raw_mouse)
|
||||
curstype = IDC_ARROW;
|
||||
else
|
||||
curstype = IDC_IBEAM;
|
||||
break;
|
||||
case BUSY_WAITING:
|
||||
curstype = IDC_APPSTARTING; /* this may be an abuse */
|
||||
force_visible = TRUE;
|
||||
break;
|
||||
case BUSY_CPU:
|
||||
curstype = IDC_WAIT;
|
||||
force_visible = TRUE;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
{
|
||||
HCURSOR cursor = LoadCursor(NULL, curstype);
|
||||
SetClassLong(hwnd, GCL_HCURSOR, (LONG)cursor);
|
||||
SetCursor(cursor); /* force redraw of cursor at current posn */
|
||||
}
|
||||
if (force_visible != forced_visible) {
|
||||
/* We want some cursor shapes to be visible always.
|
||||
* Along with show_mouseptr(), this manages the ShowCursor()
|
||||
* counter such that if we switch back to a non-force_visible
|
||||
* cursor, the previous visibility state is restored. */
|
||||
ShowCursor(force_visible);
|
||||
forced_visible = force_visible;
|
||||
}
|
||||
}
|
||||
|
||||
void set_busy_status(void *frontend, int status)
|
||||
{
|
||||
busy_status = status;
|
||||
update_mouse_pointer();
|
||||
}
|
||||
|
||||
/*
|
||||
* set or clear the "raw mouse message" mode
|
||||
*/
|
||||
@ -956,7 +1002,7 @@ void set_raw_mouse_mode(void *frontend, int activate)
|
||||
{
|
||||
activate = activate && !cfg.no_mouse_rep;
|
||||
send_raw_mouse = activate;
|
||||
SetCursor(LoadCursor(NULL, activate ? IDC_ARROW : IDC_IBEAM));
|
||||
update_mouse_pointer();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1736,6 +1782,8 @@ static Mouse_Button translate_button(Mouse_Button button)
|
||||
|
||||
static void show_mouseptr(int show)
|
||||
{
|
||||
/* NB that the counter in ShowCursor() is also frobbed by
|
||||
* update_mouse_pointer() */
|
||||
static int cursor_visible = 1;
|
||||
if (!cfg.hide_mouseptr) /* override if this feature disabled */
|
||||
show = 1;
|
||||
@ -2751,12 +2799,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
lpage_send(ldisc, CP_ACP, &c, 1, 1);
|
||||
}
|
||||
return 0;
|
||||
case WM_SETCURSOR:
|
||||
if (send_raw_mouse && LOWORD(lParam) == HTCLIENT) {
|
||||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case WM_SYSCOLORCHANGE:
|
||||
if (cfg.system_colour) {
|
||||
/* Refresh palette from system colours. */
|
||||
|
Loading…
Reference in New Issue
Block a user