diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 7ff97f2d..cc21cc3c 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1829,17 +1829,15 @@ tablet_send_proximity_in(struct tablet_dispatch *tablet, return true; } -static inline bool +static inline void tablet_send_proximity_out(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, struct evdev_device *device, struct tablet_axes *axes, uint64_t time) { - if (!tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) - return false; - - if (!tablet_has_status(tablet, TABLET_TOOL_OUTSIDE_AREA)) { + if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY) && + !tablet_has_status(tablet, TABLET_TOOL_OUTSIDE_AREA)) { tablet_notify_proximity(&device->base, time, tool, @@ -1849,16 +1847,6 @@ tablet_send_proximity_out(struct tablet_dispatch *tablet, &tablet->area.x, &tablet->area.y); } - - tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); - tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); - tablet_unset_status(tablet, TABLET_TOOL_OUTSIDE_AREA); - - tablet_reset_changed_axes(tablet); - axes->delta.x = 0; - axes->delta.y = 0; - - return true; } static inline bool @@ -2003,12 +1991,7 @@ tablet_send_events(struct tablet_dispatch *tablet, tablet_send_buttons(tablet, tool, device, time); - if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) { - tablet_change_to_left_handed(device); - tablet_apply_rotation(device); - tablet_change_area(device); - tablet_history_reset(tablet); - } + tablet_send_proximity_out(tablet, tool, device, &axes, time); } /** @@ -2232,8 +2215,20 @@ reprocess: } - if (!tablet_has_status(tablet, TABLET_TOOL_OUTSIDE_AREA)) { + if (!tablet_has_status(tablet, TABLET_TOOL_OUTSIDE_AREA)) tablet_send_events(tablet, tool, device, time); + + if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { + tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); + tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); + tablet_unset_status(tablet, TABLET_TOOL_OUTSIDE_AREA); + + tablet_reset_changed_axes(tablet); + + tablet_change_to_left_handed(device); + tablet_apply_rotation(device); + tablet_change_area(device); + tablet_history_reset(tablet); } if (process_tool_twice) diff --git a/test/test-tablet.c b/test/test-tablet.c index 95345f3e..02771e8a 100644 --- a/test/test-tablet.c +++ b/test/test-tablet.c @@ -4294,6 +4294,84 @@ START_TEST(tablet_area_set_rectangle_move_in_margin) } END_TEST +START_TEST(tablet_area_set_rectangle_while_outside) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_device *d = dev->libinput_device; + struct libinput_event *ev; + struct libinput_event_tablet_tool *tev; + struct axis_replacement axes[] = { + { ABS_DISTANCE, 10 }, + { ABS_PRESSURE, 0 }, + { -1, -1 } + }; + double x, y; + + if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT)) + return LITEST_NOT_APPLICABLE; + + litest_checkpoint("Set tablet area"); + struct libinput_config_area_rectangle rect = { + 0.25, 0.25, 0.75, 0.75, + }; + + enum libinput_config_status status = libinput_device_config_area_set_rectangle(d, &rect); + litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + + litest_drain_events(li); + + litest_checkpoint("Proximity in + out outside tablet area"); + litest_tablet_proximity_in(dev, 10, 10, axes); + litest_tablet_proximity_out(dev); + litest_dispatch(li); + litest_timeout_tablet_proxout(); + litest_dispatch(li); + litest_assert_empty_queue(li); + litest_dispatch(li); + + litest_checkpoint("Update tablet area"); + rect = (struct libinput_config_area_rectangle) { + 0.05, 0.05, 0.95, 0.95, + }; + + status = libinput_device_config_area_set_rectangle(d, &rect); + litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + + litest_checkpoint("Proximity in + out inside tablet area"); + litest_tablet_proximity_in(dev, 11, 11, axes); + litest_tablet_motion(dev, 12, 12, axes); + litest_tablet_proximity_out(dev); + litest_dispatch(li); + litest_timeout_tablet_proxout(); + litest_dispatch(li); + + ev = libinput_get_event(li); + tev = litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN); + x = libinput_event_tablet_tool_get_x_transformed(tev, 100.0); + y = libinput_event_tablet_tool_get_y_transformed(tev, 100.0); + litest_assert_double_gt(x, 6); /* somewhere around 6%, precise number doesn't matter */ + litest_assert_double_gt(y, 6); + libinput_event_destroy(ev); + + ev = libinput_get_event(li); + tev = litest_is_tablet_event(ev, LIBINPUT_EVENT_TABLET_TOOL_AXIS); + x = libinput_event_tablet_tool_get_x_transformed(tev, 100.0); + y = libinput_event_tablet_tool_get_y_transformed(tev, 100.0); + litest_assert_double_gt(x, 6); + litest_assert_double_gt(y, 6); + libinput_event_destroy(ev); + + ev = libinput_get_event(li); + tev = litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT); + x = libinput_event_tablet_tool_get_x_transformed(tev, 100.0); + y = libinput_event_tablet_tool_get_y_transformed(tev, 100.0); + litest_assert_double_gt(x, 6); + litest_assert_double_gt(y, 6); + libinput_event_destroy(ev); +} +END_TEST + static void assert_pressure(struct libinput *li, enum libinput_event_type type, double expected_pressure) { @@ -7077,6 +7155,7 @@ TEST_COLLECTION(tablet) litest_add(tablet_area_set_rectangle_move_outside, LITEST_TABLET, LITEST_ANY); litest_add(tablet_area_set_rectangle_move_outside_to_inside, LITEST_TABLET, LITEST_ANY); litest_add(tablet_area_set_rectangle_move_in_margin, LITEST_TABLET, LITEST_ANY); + litest_add(tablet_area_set_rectangle_while_outside, LITEST_TABLET, LITEST_ANY); litest_add(tablet_pressure_min_max, LITEST_TABLET, LITEST_ANY); /* Tests for pressure offset with distance */