X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fgtkwin.c;h=e8345881cd803d391da8aa1ccf6fdca7433bd99f;hb=89da2ddf564a93414ee9ab2df3f053608094e417;hp=812e4faf99041f62acb3b6dd003a5872ac116a9b;hpb=85d1e7608ebbb8c717a7e64f13beb936ad51e1fd;p=PuTTY.git diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 812e4faf..e8345881 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -94,6 +94,7 @@ struct gui_data { int mouseptr_visible; int busy_status; guint toplevel_callback_idle_id; + int idle_fn_scheduled, quit_fn_scheduled; int alt_keycode; int alt_digits; char *wintitle; @@ -132,7 +133,7 @@ struct draw_ctx { static int send_raw_mouse; -static char *app_name = "pterm"; +static const char *app_name = "pterm"; static void start_backend(struct gui_data *inst); static void exit_callback(void *vinst); @@ -142,7 +143,7 @@ char *x_get_default(const char *key) return XGetDefault(GDK_DISPLAY(), app_name, key); } -void connection_fatal(void *frontend, char *p, ...) +void connection_fatal(void *frontend, const char *p, ...) { struct gui_data *inst = (struct gui_data *)frontend; @@ -193,7 +194,7 @@ int platform_default_i(const char *name, int def) } /* Dummy routine, only required in plink. */ -void ldisc_update(void *frontend, int echo, int edit) +void frontend_echoedit_update(void *frontend, int echo, int edit) { } @@ -220,7 +221,7 @@ int from_backend_eof(void *frontend) return TRUE; /* do respond to incoming EOF with outgoing */ } -int get_userpass_input(prompts_t *p, unsigned char *in, int inlen) +int get_userpass_input(prompts_t *p, const unsigned char *in, int inlen) { struct gui_data *inst = (struct gui_data *)p->frontend; int ret; @@ -884,7 +885,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) * NetHack keypad mode. */ if (nethack_mode) { - char *keys = NULL; + const char *keys = NULL; switch (event->keyval) { case GDK_KP_1: case GDK_KP_End: keys = "bB\002"; break; case GDK_KP_2: case GDK_KP_Down: keys = "jJ\012"; break; @@ -1233,26 +1234,32 @@ gboolean button_internal(struct gui_data *inst, guint32 timestamp, GdkEventType type, guint ebutton, guint state, gdouble ex, gdouble ey) { - int shift, ctrl, alt, x, y, button, act; + int shift, ctrl, alt, x, y, button, act, raw_mouse_mode; /* Remember the timestamp. */ inst->input_event_time = timestamp; show_mouseptr(inst, 1); - if (ebutton == 4 && type == GDK_BUTTON_PRESS) { - term_scroll(inst->term, 0, -5); - return TRUE; - } - if (ebutton == 5 && type == GDK_BUTTON_PRESS) { - term_scroll(inst->term, 0, +5); - return TRUE; - } - shift = state & GDK_SHIFT_MASK; ctrl = state & GDK_CONTROL_MASK; alt = state & GDK_MOD1_MASK; + raw_mouse_mode = + send_raw_mouse && !(shift && conf_get_int(inst->conf, + CONF_mouse_override)); + + if (!raw_mouse_mode) { + if (ebutton == 4 && type == GDK_BUTTON_PRESS) { + term_scroll(inst->term, 0, -5); + return TRUE; + } + if (ebutton == 5 && type == GDK_BUTTON_PRESS) { + term_scroll(inst->term, 0, +5); + return TRUE; + } + } + if (ebutton == 3 && ctrl) { gtk_menu_popup(GTK_MENU(inst->menu), NULL, NULL, NULL, NULL, ebutton, timestamp); @@ -1265,6 +1272,10 @@ gboolean button_internal(struct gui_data *inst, guint32 timestamp, button = MBT_MIDDLE; else if (ebutton == 3) button = MBT_RIGHT; + else if (ebutton == 4) + button = MBT_WHEEL_UP; + else if (ebutton == 5) + button = MBT_WHEEL_DOWN; else return FALSE; /* don't even know what button! */ @@ -1276,9 +1287,7 @@ gboolean button_internal(struct gui_data *inst, guint32 timestamp, default: return FALSE; /* don't know this event type */ } - if (send_raw_mouse && !(shift && conf_get_int(inst->conf, - CONF_mouse_override)) && - act != MA_CLICK && act != MA_RELEASE) + if (raw_mouse_mode && act != MA_CLICK && act != MA_RELEASE) return TRUE; /* we ignore these in raw mouse mode */ x = (ex - inst->window_border) / inst->font_width; @@ -1403,6 +1412,8 @@ static gint quit_toplevel_callback_func(gpointer data) notify_toplevel_callback(inst); + inst->quit_fn_scheduled = FALSE; + return 0; } @@ -1414,16 +1425,36 @@ static gint idle_toplevel_callback_func(gpointer data) /* * We don't run the callbacks if we're in the middle of a * subsidiary gtk_main. Instead, ask for a callback when we - * get back out of the subsidiary main loop, so we can - * reschedule ourself then. + * get back out of the subsidiary main loop (if we haven't + * already arranged one), so we can reschedule ourself then. + */ + if (!inst->quit_fn_scheduled) { + gtk_quit_add(2, quit_toplevel_callback_func, inst); + inst->quit_fn_scheduled = TRUE; + } + /* + * And unschedule this idle function, since we've now done + * everything we can until the innermost gtk_main has quit and + * can reschedule us with a chance of actually taking action. */ - gtk_quit_add(2, quit_toplevel_callback_func, inst); + if (inst->idle_fn_scheduled) { /* double-check, just in case */ + gtk_idle_remove(inst->toplevel_callback_idle_id); + inst->idle_fn_scheduled = FALSE; + } } else { run_toplevel_callbacks(); } - if (!toplevel_callback_pending()) + /* + * If we've emptied our toplevel callback queue, unschedule + * ourself. Otherwise, leave ourselves pending so we'll be called + * again to deal with more callbacks after another round of the + * event loop. + */ + if (!toplevel_callback_pending() && inst->idle_fn_scheduled) { gtk_idle_remove(inst->toplevel_callback_idle_id); + inst->idle_fn_scheduled = FALSE; + } return TRUE; } @@ -1432,8 +1463,11 @@ static void notify_toplevel_callback(void *frontend) { struct gui_data *inst = (struct gui_data *)frontend; - inst->toplevel_callback_idle_id = - gtk_idle_add(idle_toplevel_callback_func, inst); + if (!inst->idle_fn_scheduled) { + inst->toplevel_callback_idle_id = + gtk_idle_add(idle_toplevel_callback_func, inst); + inst->idle_fn_scheduled = TRUE; + } } static gint timer_trigger(gpointer data) @@ -1442,7 +1476,21 @@ static gint timer_trigger(gpointer data) unsigned long next, then; long ticks; - if (run_timers(now, &next)) { + /* + * Destroy the timer we got here on. + */ + if (timer_id) { + gtk_timeout_remove(timer_id); + timer_id = 0; + } + + /* + * run_timers() may cause a call to timer_change_notify, in which + * case a new timer will already have been set up and left in + * timer_id. If it hasn't, and run_timers reports that some timing + * still needs to be done, we do it ourselves. + */ + if (run_timers(now, &next) && !timer_id) { then = now; now = GETTICKCOUNT(); if (now - then > next - then) @@ -1454,8 +1502,9 @@ static gint timer_trigger(gpointer data) } /* - * Never let a timer resume. If we need another one, we've - * asked for it explicitly above. + * Returning FALSE means 'don't call this timer again', which + * _should_ be redundant given that we removed it above, but just + * in case, return FALSE anyway. */ return FALSE; } @@ -2554,7 +2603,7 @@ GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val) return ret; } -void modalfatalbox(char *p, ...) +void modalfatalbox(const char *p, ...) { va_list ap; fprintf(stderr, "FATAL ERROR: "); @@ -2565,7 +2614,7 @@ void modalfatalbox(char *p, ...) exit(1); } -void cmdline_error(char *p, ...) +void cmdline_error(const char *p, ...) { va_list ap; fprintf(stderr, "%s: ", appname); @@ -2646,7 +2695,7 @@ int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch, #define SECOND_PASS_ONLY { if (!do_everything) continue; } while (--argc > 0) { - char *p = *++argv; + const char *p = *++argv; int ret; /* @@ -2971,7 +3020,7 @@ void reset_terminal_menuitem(GtkMenuItem *item, gpointer data) struct gui_data *inst = (struct gui_data *)data; term_pwron(inst->term, TRUE); if (inst->ldisc) - ldisc_send(inst->ldisc, NULL, 0, 0); + ldisc_echoedit_update(inst->ldisc); } void copy_all_menuitem(GtkMenuItem *item, gpointer data) @@ -3039,7 +3088,7 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data) */ if (inst->ldisc) { ldisc_configure(inst->ldisc, inst->conf); - ldisc_send(inst->ldisc, NULL, 0, 0); + ldisc_echoedit_update(inst->ldisc); } /* Pass new config data to the terminal */ term_reconfig(inst->term, inst->conf); @@ -3604,6 +3653,8 @@ int pt_main(int argc, char **argv) inst->busy_status = BUSY_NOT; inst->conf = conf_new(); inst->wintitle = inst->icontitle = NULL; + inst->quit_fn_scheduled = FALSE; + inst->idle_fn_scheduled = FALSE; /* defer any child exit handling until we're ready to deal with * it */ @@ -3873,7 +3924,7 @@ int pt_main(int argc, char **argv) start_backend(inst); - ldisc_send(inst->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ + ldisc_echoedit_update(inst->ldisc); /* cause ldisc to notice changes */ /* now we're reday to deal with the child exit handler being * called */