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
*/
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);
/*
* 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) {
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);
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;
int width, height;
int ignore_sbar;
int mouseptr_visible;
+ int busy_status;
guint term_paste_idle_id;
int alt_keycode;
int alt_digits;
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)
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
*/
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)
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 */
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;
exit(code);
}
+void set_busy_status(void *frontend, int status)
+{
+}
+
void update_specials_menu(void *frontend)
{
}
exit(code);
}
+void set_busy_status(void *frontend, int status)
+{
+}
+
void notify_remote_exit(void *frontend)
{
}
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;
}
}
+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
*/
{
activate = activate && !cfg.no_mouse_rep;
send_raw_mouse = activate;
- SetCursor(LoadCursor(NULL, activate ? IDC_ARROW : IDC_IBEAM));
+ update_mouse_pointer();
}
/*
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;
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. */