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;
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);
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! */
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;
notify_toplevel_callback(inst);
+ inst->quit_fn_scheduled = FALSE;
+
return 0;
}
/*
* 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();
}
- gtk_idle_remove(inst->toplevel_callback_idle_id);
+ /*
+ * 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;
}
{
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)
for (i = 0; i < 2; i++)
if (fonts[i])
unifont_destroy(fonts[i]);
- return dupprintf("%s: unable to load wide font \"%s\"", fs->name);
+ return dupprintf("unable to load wide font \"%s\"", fs->name);
}
} else {
fonts[2] = NULL;
for (i = 0; i < 3; i++)
if (fonts[i])
unifont_destroy(fonts[i]);
- return dupprintf("%s: unable to load wide bold font \"%s\"",
- fs->name);
+ return dupprintf("unable to load wide bold font \"%s\"", fs->name);
}
}
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 */