XIValuatorState *states;
double *values;
bool found_valuator = false;
-#ifdef HAVE_XWIDGETS
- bool any_stop_p = false;
-#endif /* HAVE_XWIDGETS */
/* A fake XMotionEvent for x_note_mouse_movement. */
XMotionEvent ev;
x_display_set_last_user_time (dpyinfo, xi_event->time);
x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+ {
+#ifdef HAVE_XWIDGETS
+ struct xwidget_view *xwidget_view = xwidget_view_from_window (enter->event);
+#else
+ bool xwidget_view = false;
+#endif
+
+ /* One problem behind the design of XInput 2 scrolling is
+ that valuators are not unique to each window, but only
+ the window that has grabbed the valuator's device or
+ the window that the device's pointer is on top of can
+ receive motion events. There is also no way to
+ retrieve the value of a valuator outside of each motion
+ event.
+
+ As such, to prevent wildly inaccurate results when the
+ valuators have changed outside Emacs, we reset our
+ records of each valuator's value whenever the pointer
+ re-enters a frame after its valuators have potentially
+ been changed elsewhere. */
+ if (enter->detail != XINotifyInferior
+ && enter->mode != XINotifyPassiveUngrab
+ /* See the comment under FocusIn in
+ `x_detect_focus_change'. The main relevant culprit
+ these days seems to be XFCE. */
+ && enter->mode != XINotifyUngrab
+ && (xwidget_view
+ || (any && enter->event == FRAME_X_WINDOW (any))))
+ xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid);
- /* One problem behind the design of XInput 2 scrolling is
- that valuators are not unique to each window, but only
- the window that has grabbed the valuator's device or
- the window that the device's pointer is on top of can
- receive motion events. There is also no way to
- retrieve the value of a valuator outside of each motion
- event.
-
- As such, to prevent wildly inaccurate results when the
- valuators have changed outside Emacs, we reset our
- records of each valuator's value whenever the pointer
- re-enters a frame after its valuators have potentially
- been changed elsewhere. */
- if (enter->detail != XINotifyInferior
- && enter->mode != XINotifyPassiveUngrab
- /* See the comment under FocusIn in
- `x_detect_focus_change'. The main relevant culprit
- these days seems to be XFCE. */
- && enter->mode != XINotifyUngrab
- && any && enter->event == FRAME_X_WINDOW (any))
- xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid);
+#ifdef HAVE_XWIDGETS
+ if (xwidget_view)
+ {
+ *finish = X_EVENT_DROP;
+ xwidget_motion_or_crossing (xwidget_view, event);
+
+ goto XI_OTHER;
+ }
+#endif
+ }
f = any;
ev.window = leave->event;
any = x_any_window_to_frame (dpyinfo, leave->event);
+#ifdef HAVE_XWIDGETS
+ {
+ struct xwidget_view *xvw
+ = xwidget_view_from_window (leave->event);
+
+ if (xvw)
+ {
+ *finish = X_EVENT_DROP;
+ xwidget_motion_or_crossing (xvw, event);
+
+ goto XI_OTHER;
+ }
+ }
+#endif
+
x_display_set_last_user_time (dpyinfo, xi_event->time);
x_detect_focus_change (dpyinfo, any, event, &inev.ie);
#ifdef HAVE_XWIDGETS
if (xv)
{
+ /* FIXME: figure out what in GTK is
+ causing interval values to jump by
+ >100 at the end of a touch sequence
+ when an xwidget gets a scroll event
+ where is_stop is TRUE. */
+ if (fabs (delta) > 100)
+ continue;
if (val->horizontal)
xv_total_x += delta;
else
xv_total_y += delta;
found_valuator = true;
-
- if (delta == 0.0)
- any_stop_p = true;
-
continue;
}
#endif
if (found_valuator)
xwidget_scroll (xv, xev->event_x, xev->event_y,
- xv_total_x, xv_total_y, state,
- xev->time, any_stop_p);
+ -xv_total_x, -xv_total_y, state,
+ xev->time, (xv_total_x == 0.0
+ && xv_total_y == 0.0));
else
xwidget_motion_notify (xv, xev->event_x, xev->event_y,
state, xev->time);
GdkEvent *xg_event = gdk_event_new (down_p ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
struct xwidget *model = XXWIDGET (view->model);
GtkWidget *target;
-#ifdef HAVE_XINPUT2
- struct x_display_info *dpyinfo;
- struct xi_device_t *xi_device;
- GdkSeat *seat;
- GdkDevice *device;
-#endif
/* X and Y should be relative to the origin of view->wdesc. */
x += view->clip_left;
xg_event->button.time = time;
xg_event->button.device = find_suitable_pointer (view->frame);
-#ifdef HAVE_XINPUT2
- dpyinfo = FRAME_DISPLAY_INFO (view->frame);
- device = xg_event->button.device;
-
- for (int idx = 0; idx < dpyinfo->num_devices; ++idx)
- {
- xi_device = &dpyinfo->devices[idx];
-
- XIUngrabDevice (view->dpy, xi_device->device_id, CurrentTime);
- }
-
- if (device)
- {
- seat = gdk_device_get_seat (device);
- gdk_seat_ungrab (seat);
- }
-#endif
-
gtk_main_do_event (xg_event);
gdk_event_free (xg_event);
}
int x;
int y;
GtkWidget *target;
+#ifdef HAVE_XINPUT2
+ XIEnterEvent *xev = NULL;
+#endif
if (NILP (model->buffer))
return;
- xg_event = gdk_event_new (event->type == MotionNotify
- ? GDK_MOTION_NOTIFY
- : (event->type == LeaveNotify
- ? GDK_LEAVE_NOTIFY
- : GDK_ENTER_NOTIFY));
+#ifdef HAVE_XINPUT2
+ if (event->type != GenericEvent)
+#endif
+ {
+ xg_event = gdk_event_new (event->type == MotionNotify
+ ? GDK_MOTION_NOTIFY
+ : (event->type == LeaveNotify
+ ? GDK_LEAVE_NOTIFY
+ : GDK_ENTER_NOTIFY));
+ target = find_widget_at_pos (model->widgetwindow_osr,
+ (event->type == MotionNotify
+ ? event->xmotion.x + view->clip_left
+ : event->xcrossing.x + view->clip_left),
+ (event->type == MotionNotify
+ ? event->xmotion.y + view->clip_top
+ : event->xcrossing.y + view->clip_top),
+ &x, &y);
+ }
+#ifdef HAVE_XINPUT2
+ else
+ {
+ eassert (event->xcookie.evtype == XI_Enter
+ || event->xcookie.evtype == XI_Leave);
- target = find_widget_at_pos (model->widgetwindow_osr,
- (event->type == MotionNotify
- ? event->xmotion.x + view->clip_left
- : event->xcrossing.x + view->clip_left),
- (event->type == MotionNotify
- ? event->xmotion.y + view->clip_top
- : event->xcrossing.y + view->clip_top),
- &x, &y);
+ xev = (XIEnterEvent *) event->xcookie.data;
+ xg_event = gdk_event_new (event->type == XI_Enter
+ ? GDK_ENTER_NOTIFY
+ : GDK_LEAVE_NOTIFY);
+ target = find_widget_at_pos (model->widgetwindow_osr,
+ lrint (xev->event_x + view->clip_left),
+ lrint (xev->event_y + view->clip_top),
+ &x, &y);
+ }
+#endif
if (!target)
target = model->widget_osr;
xg_event->motion.state = event->xmotion.state;
xg_event->motion.device = find_suitable_pointer (view->frame);
}
+#ifdef HAVE_XINPUT2
+ else if (event->type == GenericEvent)
+ {
+ xg_event->crossing.x = (gdouble) xev->event_x;
+ xg_event->crossing.y = (gdouble) xev->event_y;
+ xg_event->crossing.x_root = (gdouble) xev->root_x;
+ xg_event->crossing.y_root = (gdouble) xev->root_y;
+ xg_event->crossing.time = xev->time;
+ xg_event->crossing.focus = xev->focus;
+ gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
+ }
+#endif
else
{
xg_event->crossing.detail = min (5, event->xcrossing.detail);
xg_event->crossing.y = y;
xg_event->crossing.x_root = event->xcrossing.x_root;
xg_event->crossing.y_root = event->xcrossing.y_root;
+ xg_event->crossing.focus = event->xcrossing.focus;
gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
}
XISetMask (m, XI_Motion);
XISetMask (m, XI_ButtonPress);
XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
XISelectEvents (xv->dpy, xv->wdesc, &mask, 1);
}
#endif