summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/events.c
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2014-04-14 08:35:50 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2014-04-14 08:35:50 +0000
commit8af55a14b7fb6dcc703f803ef3cd3cd359ae345d (patch)
treef828f1c548fdec0d51e315052a0cbdb58fd7d29e /Build/source/texk/xdvik/events.c
parent3606cb1179eae47f2ee7d2569ae7ac024deb1310 (diff)
xdvik 22.87
git-svn-id: svn://tug.org/texlive/trunk@33436 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/xdvik/events.c')
-rw-r--r--Build/source/texk/xdvik/events.c710
1 files changed, 693 insertions, 17 deletions
diff --git a/Build/source/texk/xdvik/events.c b/Build/source/texk/xdvik/events.c
index 4a78194f6c2..2ad55d03686 100644
--- a/Build/source/texk/xdvik/events.c
+++ b/Build/source/texk/xdvik/events.c
@@ -1,6 +1,6 @@
/*======================================================================*\
-Copyright (c) 1990-2004 Paul Vojta and others
+Copyright (c) 1990-2014 Paul Vojta and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -103,6 +103,27 @@ in xdvi.c.
extern int errno;
#endif /* X_NOT_STDC_ENV */
+#if HAVE_X11_INTRINSICI_H
+# include <X11/IntrinsicI.h>
+#else
+
+/* Taken from <X11/TranslateI.h> in libXt-1.1.3 (June 2012) */
+typedef struct _LateBindings {
+ unsigned int knot:1;
+ unsigned int pair:1;
+ unsigned short ref_count; /* garbage collection */
+ KeySym keysym;
+} LateBindings, *LateBindingsPtr;
+
+extern Boolean _XtComputeLateBindings(
+ Display* /* dpy */,
+ LateBindingsPtr /* lateModifiers */,
+ Modifiers* /* computed */,
+ Modifiers* /* computedMask */
+);
+
+#endif /* not HAVE_X11_INTRINSICI_H */
+
#if HAVE_XKB_BELL_EXT
# include <X11/XKBlib.h>
# define XdviBell(display, window, percent) \
@@ -179,6 +200,31 @@ extern int errno;
/* cannot be const since Strings in Action routines aren't either */
static char *Act_true_retval = "true";
static char *Act_false_retval = "false";
+
+
+#if HAVE_XI21
+
+int xi2_opcode;
+Boolean xi2_active = False;
+struct xi2_master *xi2_masters; /* linked list of master devs */
+struct xi2_master *xi2_current; /* current master device */
+struct xi2_slave *xi2_slaves; /* linked list of slave devs */
+
+struct xi2_slave xi2_no_slave; /* if no slave assigned yet */
+
+/*
+ * XInput 2.1 creates spurious enter/leave events around the time it
+ * creates fake wheel button events. So, we keep track of the last
+ * such fake button event, and if an enter/leave occurs too soon after
+ * that event, then we ignore the enter event.
+ * I've managed to get rid of this (by making sure that the relevant
+ * events come from the drawing window if possible), but I left the code
+ * here just in case.
+ */
+
+static Time xi2_ign_time; /* time of last XI 2.1 wheel button event */
+
+#endif
static sigset_t all_signals;
@@ -442,6 +488,8 @@ static XtActionsRec m_actions[] = {
{"set-paper-landscape", Act_set_paper_landscape},
#endif
{"load-url", Act_load_url},
+ {"scroll-list-up", Act_scroll_list_up},
+ {"scroll-list-down", Act_scroll_list_down},
{"pagehistory-clear", Act_pagehistory_clear},
{"pagehistory-back", Act_pagehistory_back},
{"pagehistory-forward", Act_pagehistory_forward},
@@ -539,7 +587,7 @@ compile_action(const char *str, struct xdvi_action **app)
}
free(params);
*app = NULL;
- return False;
+ return False;
}
params[num_params++] = xstrndup(p, p1 - p);
@@ -558,7 +606,7 @@ compile_action(const char *str, struct xdvi_action **app)
}
free(params);
*app = NULL;
- return False;
+ return False;
}
}
else { /* param is not quoted */
@@ -614,6 +662,35 @@ compile_action(const char *str, struct xdvi_action **app)
return True;
}
+/*
+ * cached_compile_action does the same as compile_action, but retains
+ * the compiled actions. It is used only in Act_mouse_modes(), which
+ * otherwise would recompile the same actions over and over again.
+ */
+
+struct avl_cached_action {
+ AVL_COMMON;
+ struct xdvi_action *ap;
+};
+
+
+static void
+cached_compile_action(const char *str, struct xdvi_action **app)
+{
+ static struct avl_cached_action *avl_ca_head = NULL;
+ struct avl_cached_action *avl_ca;
+
+ avl_ca = (struct avl_cached_action *)
+ avladd(str, strlen(str), (struct avl **) &avl_ca_head,
+ sizeof (struct avl_cached_action));
+
+ if (avl_ca->key == str) { /* if new record */
+ avl_ca->key = xstrdup(str); /* copy string to new storage */
+ compile_action(str, &avl_ca->ap);
+ }
+ *app = avl_ca->ap;
+}
+
/*
* Access to m_actions
@@ -2444,9 +2521,10 @@ Act_mouse_modes(Widget w, XEvent *event,
mode_idx = resource.mouse_mode;
}
- compile_action(params[mode_idx], &my_action);
+ cached_compile_action(params[mode_idx], &my_action);
for (i = 0, ap = my_action; ap; ap = ap->next, i++) {
String *args;
+ String retval;
TRACE_EVENTS((stderr, "Action %d for mode %lu: '%s', %d args |%s| maps to proc |%p|",
i, (unsigned long) mode_idx, ap->command, ap->num_params,
@@ -2463,7 +2541,9 @@ Act_mouse_modes(Widget w, XEvent *event,
/* now call the action proc directly */
XtCallActionProc(w, ap->command, event, args, ap->num_params);
- if (args[0] == Act_true_retval) { /* we may compare the pointers here */
+ retval = args[0];
+ free(args);
+ if (retval == Act_true_retval) { /* we may compare the pointers here */
/* Special case: Only invoke first action, not subsequent ones;
* e.g. if mouse is over a link and action is Act_href or
* Act_href_newwindow (currently the only cases where this is used).
@@ -2471,18 +2551,6 @@ Act_mouse_modes(Widget w, XEvent *event,
break;
}
}
-
- /* free all allocated action info. TODO: should we save it for later calls? */
- ap = my_action;
- while (ap) {
- struct xdvi_action *tmp_ap = ap;
- free(ap->command);
- while (ap->num_params > 0)
- free(ap->params[--(ap->num_params)]);
- free(ap->params);
- ap = tmp_ap->next;
- free(tmp_ap);
- }
}
@@ -3663,6 +3731,20 @@ Act_press(Widget w, XEvent *event,
struct mouse_acts *mactp;
struct xdvi_action *actp;
+#if HAVE_XI21
+ if (xi2_active
+ && (xi2_current->slave->btn_mask & (1 << event->xbutton.button))) {
+ TRACE_EVENTS((stderr, "Ignoring button %d press (XI 2.1 active)",
+ event->xbutton.button));
+ if (event->xbutton.button <= 5)
+ wheel_button = event->xbutton.button;
+ else
+ wheel_h_button = event->xbutton.button;
+ xi2_ign_time = event->xbutton.time;
+ return;
+ }
+#endif
+
for (mactp = mouse_actions; mactp != NULL; mactp = mactp->next) {
if (event->xbutton.button == mactp->button || mactp->button == 0) {
Modifiers mask = 0;
@@ -5025,6 +5107,516 @@ do_sigterm(void)
*/
}
+
+#if HAVE_XI21
+
+/*
+ * XInput 2.1 event processing.
+ *
+ * The XInput system has (virtual) "master" devices, including a master
+ * pointer and master keyboard (and maybe others), and "slave" devices
+ * that can be assigned to a master. Each master can have only one slave
+ * at a time. If you have two mice plugged in, for example, each is a
+ * separate slave device, and the one assigned to the master pointer device
+ * is whichever one was moved or clicked most recently. Moving or clicking
+ * the other mouse would then cause an XInput SlaveSwitch event, which
+ * notifies the X client that a different pointer is now active (and the
+ * previously active mouse would then become inactive).
+ *
+ * The code here looks not just at events from the master pointer, it also
+ * tracks events from the slave pointer devices. This is because the
+ * valuators for each slave pointer may have different scales.
+ *
+ * The XI_Motion events contain the master and slave ids of the device
+ * sending the event, so in principle it wouldn't be necessary to track
+ * SlaveSwitch events. However, we do track these events, because we need
+ * to know the valuator values at the time of the switch (otherwise, e.g.,
+ * the first click of a wheel mouse would be lost).
+ *
+ * It is also possible that a valuator may change while the pointer is
+ * outside of the drawing window. So, we need to reset the valuator
+ * values upon XI_Enter events. For some strange reason, we get extra
+ * XI_Enter events when using a traditional wheel mouse, and so the code
+ * takes care to ignore those. This only happens with the Xaw toolkit.
+ *
+ * Slave devices have events that notify clients when they are (i) added
+ * or removed, (ii) attached or detached, and (iii) enabled or disabled.
+ * We only worry about (iii), and for disabled devices we don't bother to
+ * delete the data structure.
+ *
+ */
+
+/*
+ * xi2_find_master: set xi2_current to record for given device id
+ * Return True if found, False if not.
+ */
+
+static Boolean
+xi2_find_master(int id)
+{
+ struct xi2_master *mp;
+
+ for (mp = xi2_masters; mp != NULL; mp = mp->next)
+ if (mp->id == id) {
+ xi2_current = mp;
+ return True;
+ }
+ return False;
+}
+
+/*
+ * xi2_find_slave: set xi2_current->slave to record for given slave device
+ * Return True if found, False if not.
+ */
+
+static Boolean
+xi2_find_slave(int id)
+{
+ struct xi2_slave *sp;
+
+ for (sp = xi2_slaves; sp != NULL; sp = sp->next)
+ if (sp->id == id) {
+ xi2_current->slave = sp;
+ return True;
+ }
+ return False;
+}
+
+/*
+ * Handle XI2 Enter event. We need to look at these events because if the
+ * user scrolls in some other window, then the valuator will be changed
+ * by a large amount, and that scrolling should not occur also in the
+ * main xdvi window when the user resumes scrolling here.
+ */
+
+static void
+xi2_ev_enter(XIEnterEvent *xi_event)
+{
+ XIDeviceInfo *info;
+ int ndevices;
+ int i;
+
+ if (xi_event->time < xi2_ign_time + 5) {
+ TRACE_EVENTS((stderr, "Ignoring XI_Enter event as spurious."));
+ return;
+ }
+
+ if (xi2_current->id != xi_event->deviceid
+ && !xi2_find_master(xi_event->deviceid)) {
+ TRACE_EVENTS((stderr,
+ "Ignoring XI_Enter event: master device %d not found",
+ xi_event->deviceid));
+ return;
+ }
+
+ if (xi_event->sourceid == xi2_current->id) {
+ TRACE_EVENTS((stderr,
+ "Ignoring XI_Enter event for master device."));
+ return;
+ }
+ else if (xi_event->sourceid != xi2_current->slave->id) {
+ struct xi2_slave *prev_slave = xi2_current->slave;
+
+ if (!xi2_find_slave(xi_event->sourceid)) {
+ TRACE_EVENTS((stderr,
+ "Ignoring XI_Enter event: device %d->%d not found.",
+ xi_event->deviceid, xi_event->sourceid));
+ return;
+ }
+ TRACE_EVENTS((stderr,
+ "%s %d->%d",
+ prev_slave == &xi2_no_slave
+ ? "Implicit switch in XI_Enter to"
+ : "Received out-of-turn XI_Enter event for",
+ xi_event->deviceid, xi_event->sourceid));
+ if (!xi2_current->slave->enabled)
+ TRACE_EVENTS((stderr, "Caution: slave is not enabled."));
+ }
+ else {
+ TRACE_EVENTS((stderr, "Received XI_Enter event"));
+ }
+
+ info = XIQueryDevice(DISP, xi_event->sourceid, &ndevices);
+ if (info == NULL || ndevices != 1) {
+ TRACE_EVENTS((stderr, "xi2_ev_enter: XIQueryDevice failed for %d",
+ xi_event->sourceid));
+ return;
+ }
+
+ for (i = 0; i < info->num_classes; ++i)
+ if (info->classes[i]->type == XIValuatorClass) {
+ XIValuatorClassInfo *valuator;
+
+ valuator = (XIValuatorClassInfo *) info->classes[i];
+ if (valuator->number == xi2_current->slave->vert.number) {
+ xi2_current->slave->vert.lastexact =
+ xi2_current->slave->vert.lastval = valuator->value;
+ xi2_current->slave->vert.serial =
+ LastKnownRequestProcessed(DISP);
+ }
+ else if (valuator->number == xi2_current->slave->horiz.number) {
+ xi2_current->slave->horiz.lastexact =
+ xi2_current->slave->horiz.lastval = valuator->value;
+ xi2_current->slave->horiz.serial =
+ LastKnownRequestProcessed(DISP);
+ }
+ }
+ XIFreeDeviceInfo(info);
+}
+
+static void
+xi2_emulate_action(struct xdvi_action *actp, struct xi2_valinfo *valinfo,
+ double value)
+{
+ double factor;
+ int dist;
+
+ for (; actp != NULL; actp = actp->next) {
+ if (actp->proc == Act_wheel || actp->proc == Act_hwheel) {
+ if (actp->num_params == 0)
+ factor = resource.wheel_unit;
+ else if (index(actp->params[0], '.') == NULL)
+ factor = atoi(actp->params[0]);
+ else
+ factor = atof(actp->params[0]) * resource.wheel_unit;
+ factor /= valinfo->increment;
+
+ if (valinfo->factor != fabs(factor)) {
+ valinfo->lastval = valinfo->lastexact;
+ valinfo->factor = fabs(factor);
+ }
+
+ /*
+ * In extreme cases, the server may reset the valuator to zero
+ * to avoid large values. The next few lines avoid the extreme
+ * scrolling event that would otherwise occur in this event.
+ */
+ if (fabs(value - valinfo->lastval) > INT_MAX / 2) {
+ valinfo->lastval +=
+ value > valinfo->lastval ? INT_MAX : -INT_MAX;
+ TRACE_EVENTS((stderr,
+ "Adjusted for pointer overflow; lastval = %g, new = %g\n",
+ valinfo->lastval, value));
+ }
+
+ dist = (value - valinfo->lastval) * factor;
+ if (dist == 0) {
+ valinfo->lastexact = value;
+ continue;
+ }
+
+ if (actp->proc == Act_wheel) {
+# if XAW
+ if (globals.widgets.y_bar != NULL)
+ XtCallCallbacks(globals.widgets.y_bar, XtNscrollProc,
+ cast_int_to_XtPointer(dist));
+# else /* MOTIF */
+ get_xy();
+ set_bar_value(globals.widgets.y_bar,
+ dist - m_window_y, (int) (globals.page.h - mane.height));
+# endif /* MOTIF */
+ }
+ else { /* Act_hwheel */
+# if XAW
+ if (globals.widgets.x_bar != NULL)
+ XtCallCallbacks(globals.widgets.x_bar, XtNscrollProc,
+ cast_int_to_XtPointer(dist));
+# else /* MOTIF */
+ get_xy();
+ set_bar_value(globals.widgets.x_bar,
+ dist - m_window_x, (int) (globals.page.w - mane.width));
+# endif /* MOTIF */
+ }
+ /* The next line puts back any rounding error */
+ valinfo->lastval += dist / factor;
+ valinfo->lastexact = value;
+ }
+ else if (actp->proc == Act_mouse_modes) {
+ size_t mode_idx = 0; /* default: one action for all modes */
+ struct xdvi_action *my_action = NULL;
+
+ if (actp->num_params > 1) { /* if different actions */
+ if (resource.mouse_mode >= actp->num_params) {
+ size_t k;
+
+ XDVI_WARNING((stderr, "X action 'mouse-modes' called "
+ "with only %d parameters, should be %d",
+ actp->num_params, resource.mouse_mode + 1));
+ for (k = 0; k < actp->num_params; k++) {
+ XDVI_WARNING((stderr, " Param %d: `%s'",
+ (int)(k + 1), actp->params[k]));
+ }
+ return;
+ }
+ mode_idx = resource.mouse_mode;
+ }
+
+ cached_compile_action(actp->params[mode_idx], &my_action);
+ xi2_emulate_action(my_action, valinfo, value);
+ }
+ else
+ TRACE_EVENTS((stderr, "Mouse_translations action is neither "
+ "wheel() nor hwheel(); ignoring."));
+ }
+}
+
+static void
+xi2_do_valuator(XIDeviceEvent *xi_event, struct xi2_valinfo *valinfo,
+ int button, double value)
+{
+ struct mouse_acts *mactp;
+ Modifiers state;
+
+ state = xi_event->buttons.mask[0];
+ if (xi_event->buttons.mask_len >= 2) {
+ state |= xi_event->buttons.mask[1] << 8;
+ if (xi_event->buttons.mask_len >= 3) {
+ state |= xi_event->buttons.mask[2] << 16;
+ if (xi_event->buttons.mask_len >= 4)
+ state |= xi_event->buttons.mask[3] << 24;
+ }
+ }
+
+ for (mactp = mouse_actions; mactp != NULL; mactp = mactp->next)
+ if (mactp->button == button || mactp->button == 0) {
+ Modifiers mask = 0;
+ Modifiers mods_value = 0;
+
+ if (mactp->late_bindings == NULL
+ || _XtComputeLateBindings(DISP, mactp->late_bindings,
+ &mods_value, &mask)) {
+ mask |= mactp->mask;
+ mods_value |= mactp->value;
+ if (((mods_value ^ state) & mask) == 0) {
+ xi2_emulate_action(mactp->action, valinfo, value);
+ return;
+ }
+ }
+ }
+}
+
+static void
+xi2_ev_motion(XIDeviceEvent *xi_event)
+{
+ double *val;
+ int i;
+ XEvent event;
+
+ if (xi2_current->id != xi_event->deviceid
+ && !xi2_find_master(xi_event->deviceid)) {
+ TRACE_EVENTS((stderr,
+ "Ignoring XI_Motion event: master device %d not found",
+ xi_event->deviceid));
+ return;
+ }
+
+ if (xi2_current->slave->id != xi_event->sourceid) {
+ struct xi2_slave *prev_slave = xi2_current->slave;
+
+ if (!xi2_find_slave(xi_event->sourceid)) {
+ TRACE_EVENTS((stderr,
+ "Ignoring XI_Motion event: device %d->%d not found.",
+ xi_event->deviceid, xi_event->sourceid));
+ return;
+ }
+ TRACE_EVENTS((stderr, "%s %d->%d\n",
+ prev_slave == &xi2_no_slave
+ ? "Implicit switch in XI_Motion to"
+ : "Received out-of-turn XI_Motion event for",
+ xi_event->deviceid, xi_event->sourceid));
+ if (!xi2_current->slave->enabled)
+ TRACE_EVENTS((stderr, "Caution: slave is not enabled."));
+ }
+
+ val = xi_event->valuators.values;
+ for (i = 0; i < xi_event->valuators.mask_len * 8; ++i)
+ if (XIMaskIsSet(xi_event->valuators.mask, i)) {
+ if (i == xi2_current->slave->vert.number) {
+ if ((long) (xi_event->serial
+ - xi2_current->slave->vert.serial) < 0) {
+ TRACE_EVENTS((stderr,
+ "Vertical valuator in EnterEvent was outdated "
+ "(%lu < %lu)",
+ xi_event->serial, xi2_current->slave->vert.serial));
+ xi2_current->slave->vert.serial = xi_event->serial;
+ xi2_current->slave->vert.lastexact =
+ xi2_current->slave->vert.lastval = *val;
+ }
+ else
+ xi2_do_valuator(xi_event, &xi2_current->slave->vert, 5,
+ *val);
+ }
+ else if (i == xi2_current->slave->horiz.number) {
+ if ((long) (xi_event->serial
+ - xi2_current->slave->horiz.serial) < 0) {
+ TRACE_EVENTS((stderr,
+ "Horizontal valuator in EnterEvent was outdated"));
+ xi2_current->slave->horiz.serial = xi_event->serial;
+ xi2_current->slave->horiz.lastexact =
+ xi2_current->slave->horiz.lastval = *val;
+ }
+ else
+ xi2_do_valuator(xi_event, &xi2_current->slave->horiz, 7,
+ *val);
+ }
+ ++val;
+ }
+
+ /* For some reason the X server doesn't want to send a core motion
+ * event if an XInput motion event is already being sent.
+ * So we need to fake it. The routines called from Act_motion()
+ * should be sure to use only the fields provided here. */
+ event.xmotion.window = xi_event->event;
+ event.xmotion.x = xi_event->event_x;
+ event.xmotion.y = xi_event->event_y;
+ event.xmotion.x_root = xi_event->root_x;
+ event.xmotion.y_root = xi_event->root_y;
+ Act_motion(NULL, &event, NULL, NULL);
+}
+
+static void
+xi2_ev_devchange(XIDeviceChangedEvent *xi_event)
+{
+ struct xi2_slave *sp;
+
+ if (xi_event->reason == XISlaveSwitch) {
+ struct xi2_master *mp;
+
+ TRACE_EVENTS((stderr,
+ "Received XI_DeviceChanged event, XISlaveSwitch, device = %d->%d",
+ xi_event->deviceid, xi_event->sourceid));
+
+ for (sp = xi2_slaves;; sp = sp->next) {
+ if (sp == NULL) {
+ TRACE_EVENTS((stderr, "ignoring (device not found)"));
+ return;
+ }
+ if (sp->id == xi_event->sourceid)
+ break;
+ }
+
+ for (mp = xi2_masters;; mp = mp->next) {
+ if (mp == NULL) {
+ TRACE_EVENTS((stderr,
+ "Cannot switch slave (master device not found)"));
+ return;
+ }
+ if (mp->id == xi_event->deviceid)
+ break;
+ }
+ mp->slave = sp;
+
+ /* A valuator may change when a slave is switched off */
+ xi2_init_valuators(sp, xi_event->classes, xi_event->num_classes);
+
+ if (!sp->enabled)
+ TRACE_EVENTS((stderr, "Caution: slave device is not enabled."));
+ }
+ else if (xi_event->reason == XIDeviceChange) {
+ /* In principle, this will add any device, but there's no "use" */
+ /* field, so no easy way to check if it's a suitable slave device.*/
+ TRACE_EVENTS((stderr,
+ "Received XI_DeviceChanged event, XIDeviceChange, device = %d->%d",
+ xi_event->deviceid, xi_event->sourceid));
+
+ for (sp = xi2_slaves;; sp = sp->next) {
+ if (sp == NULL) {
+ TRACE_EVENTS((stderr, " (new device)"));
+ sp = xmalloc(sizeof (struct xi2_slave));
+ sp->id = xi_event->sourceid;
+ sp->enabled = 0;
+ sp->next = xi2_slaves;
+ xi2_slaves = sp;
+ break;
+ }
+ if (sp->id == xi_event->sourceid)
+ break;
+ }
+
+ xi2_init_valuators(sp, xi_event->classes, xi_event->num_classes);
+
+ if (!xi2_active && sp->btn_mask) {
+ TRACE_EVENTS((stderr, "Activating XI2 now."));
+ xi2_activate();
+ }
+ }
+ else {
+ TRACE_EVENTS((stderr,
+ "Ignoring XI_DeviceChanged event with unknown reason %x, "
+ "device = %d->%d",
+ xi_event->reason, xi_event->deviceid, xi_event->sourceid));
+ }
+}
+
+
+static void
+xi2_ev_hierchange(XIHierarchyEvent *xi_event)
+{
+ XIHierarchyInfo *infp, *inf_end;
+
+ if (globals.debug & DBG_EVENT) {
+ fprintf(stderr, "%s:%d: XI_HierarchyChanged event: ",
+ __FILE__, __LINE__);
+ if (xi_event->flags & XIMasterAdded)
+ fputs(" XIMasterAdded", stderr);
+ if (xi_event->flags & XIMasterRemoved)
+ fputs(" XIMasterRemoved", stderr);
+ if (xi_event->flags & XISlaveAdded)
+ fputs(" XISlaveAdded", stderr);
+ if (xi_event->flags & XISlaveRemoved)
+ fputs(" XISlaveRemoved", stderr);
+ if (xi_event->flags & XISlaveAttached)
+ fputs(" XISlaveAttached", stderr);
+ if (xi_event->flags & XISlaveDetached)
+ fputs(" XISlaveDetached", stderr);
+ if (xi_event->flags & XIDeviceEnabled)
+ fputs(" XIDeviceEnabled", stderr);
+ if (xi_event->flags & XIDeviceDisabled)
+ fputs(" XIDeviceDisabled", stderr);
+ if (!xi_event->flags)
+ fputs("no flags(?)", stderr);
+ fputc('\n', stderr);
+ }
+
+ if (!(xi_event->flags & (XIDeviceEnabled | XIDeviceDisabled)))
+ return;
+
+ inf_end = xi_event->info + (xi_event->num_info - 1);
+ for (infp = xi_event->info; infp <= inf_end; ++infp) {
+ struct xi2_slave *sp;
+
+ if (infp->use != XISlavePointer && infp->use != XIFloatingSlave)
+ continue;
+
+ for (sp = xi2_slaves;; sp = sp->next) {
+ if (sp == NULL) {
+ if (infp->enabled)
+ TRACE_EVENTS((stderr,
+ " Ignoring enable request for %d->%d (not found)",
+ infp->attachment, infp->deviceid));
+ break;
+ }
+ if (sp->id == infp->deviceid) {
+ if (infp->enabled != sp->enabled) {
+ TRACE_EVENTS((stderr, " %s %d->%d",
+ infp->enabled ? "Enabling" : "Disabling",
+ infp->attachment, infp->deviceid));
+ sp->enabled = infp->enabled;
+ if (!sp->enabled && xi2_current->slave == sp) {
+ TRACE_EVENTS((stderr,
+ " Removing from master device"));
+ xi2_current->slave = &xi2_no_slave;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+#endif /* HAVE_XI21 */
+
+
/*
* Since redrawing the screen is (potentially) a slow task, xdvi checks
* for incoming events while this is occurring. It does not register
@@ -5221,12 +5813,56 @@ read_events(unsigned int ret_mask)
#endif /* HAVE_POLL */
}
}
+
XtAppNextEvent(globals.app, &event);
+
#ifdef MOTIF
if ((resource.expert_mode & XPRT_SHOW_TOOLBAR) != 0)
TipAppHandle(globals.app, &event);
#endif
+#if HAVE_XI21
+ if (event.xany.type == GenericEvent
+ && event.xcookie.extension == xi2_opcode) {
+ if (!XGetEventData(DISP, &event.xcookie)) {
+ TRACE_EVENTS((stderr,
+ "Received XI2 event, of type %d, with no cookie",
+ event.xcookie.evtype));
+ }
+ else {
+ switch (event.xcookie.evtype) {
+
+ case XI_HierarchyChanged:
+ xi2_ev_hierchange(event.xcookie.data);
+ break;
+
+ case XI_DeviceChanged:
+ xi2_ev_devchange(event.xcookie.data);
+ break;
+
+ case XI_Enter:
+ xi2_ev_enter(event.xcookie.data);
+ break;
+
+ case XI_Motion:
+ /* This needs to be filled in by the client */
+ ((XIDeviceEvent *) event.xcookie.data)->serial
+ = event.xany.serial;
+ xi2_ev_motion(event.xcookie.data);
+ break;
+
+ default:
+ TRACE_EVENTS((stderr,
+ "Received XI2 event of unknown type %d",
+ event.xcookie.evtype));
+
+ }
+ XFreeEventData(DISP, &event.xcookie);
+ }
+ continue;
+ }
+#endif /* HAVE_XI21 */
+
if (resized)
get_geom();
@@ -5774,6 +6410,46 @@ watch_file_cb(XtPointer client_data, XtIntervalId *id)
}
}
+void
+Act_scroll_list_up(Widget w, XEvent *event, String *params,
+ Cardinal *num_params)
+{
+ UNUSED(w);
+ UNUSED(event);
+ UNUSED(params);
+ UNUSED(num_params);
+
+ if (current_page == 0) {
+ xdvi_bell();
+ /* statusline_info(STATUS_SHORT, "First page of DVI file"); */
+ return;
+ }
+ goto_page(check_goto_page(current_page - 1, True),
+ resource.keep_flag ? NULL : home, False);
+ search_signal_page_changed();
+ statusline_erase("Page history:");
+}
+
+void
+Act_scroll_list_down(Widget w, XEvent *event, String *params,
+ Cardinal *num_params)
+{
+ UNUSED(w);
+ UNUSED(event);
+ UNUSED(params);
+ UNUSED(num_params);
+
+ if (current_page >= total_pages - 1) {
+ xdvi_bell();
+ /* statusline_info(STATUS_SHORT, "Last page of DVI file"); */
+ return;
+ }
+ goto_page(check_goto_page(current_page + 1, True),
+ resource.keep_flag ? NULL : home, False);
+ search_signal_page_changed();
+ statusline_erase("Page history:");
+}
+
void Act_pagehistory_back(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
int arg;