diff --git a/tests/seat_test.c b/tests/seat_test.c
index 2b445ec..8517bb5 100644
--- a/tests/seat_test.c
+++ b/tests/seat_test.c
@@ -20,39 +20,83 @@ along with 12to11. If not, see . */
#include "test_harness.h"
#include
+#include
enum test_expect_event_kind
{
POINTER_ENTER_EVENT,
POINTER_FRAME_EVENT,
POINTER_MOTION_EVENT,
+ POINTER_LEAVE_EVENT,
+ POINTER_BUTTON_EVENT,
};
-struct test_expect_data
+struct test_recorded_event
{
- /* The coordinates of the event. */
- double x, y;
-
- /* What kind of event is being waited for. */
+ /* What kind of event this is. */
enum test_expect_event_kind kind;
- /* Whether or not the expected event arrived. */
- bool arrived;
+ /* The last event. */
+ struct test_recorded_event *last;
+};
+
+struct test_recorded_enter_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+
+ /* The surface of the event. */
+ struct wl_surface *surface;
+
+ /* The coordinates of the event. */
+ double x, y;
+};
+
+struct test_recorded_frame_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+};
+
+struct test_recorded_motion_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+
+ /* The coordinates of the event. */
+ double x, y;
+};
+
+struct test_recorded_leave_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+};
+
+struct test_recorded_button_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+
+ /* The button and state. */
+ uint32_t button, state;
};
enum test_kind
{
MAP_WINDOW_KIND,
TEST_ENTRY_KIND,
+ TEST_CLICK_KIND,
};
static const char *test_names[] =
{
"map_window",
"test_entry",
+ "test_click",
};
-#define LAST_TEST TEST_ENTRY_KIND
+#define LAST_TEST TEST_CLICK_KIND
#define TEST_SOURCE_DEVICE 4500000
/* The display. */
@@ -71,11 +115,11 @@ static Window test_surface_window;
static struct test_surface *test_surface;
static struct wl_surface *wayland_surface;
-/* How many elements are in the current listener data. */
-static int num_listener_data;
+/* Whether or not events are being recorded. */
+static bool recording_events;
-/* The current listener data. */
-struct test_expect_data *current_listener_data;
+/* If so, the tail of the event list. */
+static struct test_recorded_event *record_tail;
@@ -83,6 +127,13 @@ struct test_expect_data *current_listener_data;
static void submit_surface_damage (struct wl_surface *, int, int, int, int);
static void expect_surface_enter (double, double);
static void expect_surface_motion (double, double);
+static void record_events (void);
+static void expect_frame_event (void);
+static void expect_enter_event (double, double);
+static void expect_motion_event (double, double);
+static void expect_leave_event (void);
+static void expect_button_event (int, int);
+static void expect_no_events (void);
@@ -110,11 +161,148 @@ test_get_root (void)
+static void
+run_click_test (struct test_XIButtonState *button_state)
+{
+ /* First, get all events that should already have arrived. */
+ wl_display_roundtrip (display->display);
+
+ /* Next, dispatch the button press events. */
+ test_seat_controller_dispatch_XI_ButtonPress (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 1,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (1.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (1.0),
+ wl_fixed_from_double (2.0),
+ 0,
+ button_state,
+ NULL, NULL, NULL);
+ test_XIButtonState_add_button (button_state, 1);
+
+ test_seat_controller_dispatch_XI_ButtonPress (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 2,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (1.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (1.0),
+ wl_fixed_from_double (2.0),
+ 0,
+ button_state,
+ NULL, NULL, NULL);
+ test_XIButtonState_add_button (button_state, 2);
+
+ /* Now, dispatch the motion and leave events. */
+ test_seat_controller_dispatch_XI_Motion (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 0,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ 0,
+ button_state,
+ NULL, NULL, NULL);
+ test_seat_controller_dispatch_XI_Leave (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ XINotifyAncestor,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ XINotifyNormal,
+ False, True,
+ button_state, NULL, NULL);
+
+ /* And release the buttons. */
+ test_seat_controller_dispatch_XI_ButtonRelease (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 1,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ 0,
+ button_state,
+ NULL, NULL, NULL);
+ test_XIButtonState_remove_button (button_state, 2);
+
+ test_seat_controller_dispatch_XI_ButtonRelease (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 2,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ 0,
+ button_state,
+ NULL, NULL, NULL);
+ test_XIButtonState_remove_button (button_state, 1);
+
+ /* Send the ungrab leave event. */
+ test_seat_controller_dispatch_XI_Leave (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ XINotifyAncestor,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ wl_fixed_from_double (550.0),
+ XINotifyUngrab,
+ False, True,
+ button_state, NULL, NULL);
+
+ /* Now, verify the events that arrive. */
+ record_events ();
+ expect_frame_event ();
+ expect_leave_event ();
+ expect_frame_event ();
+ expect_button_event (BTN_MIDDLE, WL_POINTER_BUTTON_STATE_RELEASED);
+ expect_frame_event ();
+ expect_button_event (BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
+ expect_frame_event ();
+ expect_motion_event (550.0, 550.0);
+ expect_frame_event ();
+ expect_button_event (BTN_MIDDLE, WL_POINTER_BUTTON_STATE_PRESSED);
+ expect_frame_event ();
+ expect_button_event (BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
+ expect_no_events ();
+}
+
static void
test_single_step (enum test_kind kind)
{
struct wl_buffer *buffer;
+ struct test_XIButtonState *button_state;
+ again:
test_log ("running test step: %s", test_names[kind]);
switch (kind)
@@ -169,7 +357,39 @@ test_single_step (enum test_kind kind)
/* Expect mouse motion at the specified coordinates. */
expect_surface_motion (1.0, 2.0);
- break;
+
+ /* Run the click test. */
+ kind = TEST_CLICK_KIND;
+ goto again;
+
+ case TEST_CLICK_KIND:
+ /* Test clicking and grab processing. Press buttons 1 and 2,
+ dispatch a motion event at 550, 550, a NotifyNormal leave
+ event at 550, 550, and finally button release events for both
+ buttons followed by a NotifyUngrab leave event. Verify that
+ only the following events are sent in the given order:
+
+ button (SERIAL, TIME, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED)
+ frame ()
+ button (SERIAL, TIME, BTN_MIDDLE, WL_POINTER_BUTTON_STATE_PRESSED)
+ frame ()
+ motion (TIME, 550.0, 550.0)
+ frame ()
+ button (SERIAL, TIME, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED)
+ frame ()
+ button (SERIAL, TIME, BTN_MIDDLE, WL_POINTER_BUTTON_STATE_RELEASED)
+ frame ()
+ leave ()
+ frame () */
+
+ /* Initialize the button state. */
+ button_state
+ = test_seat_controller_get_XIButtonState (display->seat->controller);
+
+ if (!button_state)
+ report_test_failure ("failed to obtain button state resource");
+
+ run_click_test (button_state);
}
if (kind == LAST_TEST)
@@ -178,62 +398,164 @@ test_single_step (enum test_kind kind)
+/* Record events previously sent to the seat's pointer or keyboard
+ device, and place them into `record_tail'. */
+
+static void
+record_events (void)
+{
+ recording_events = true;
+ wl_display_roundtrip (display->display);
+ recording_events = false;
+}
+
+static void
+expect_frame_event (void)
+{
+ struct test_recorded_event *event;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = event->last;
+
+ if (event->kind == POINTER_FRAME_EVENT)
+ free (event);
+ else
+ report_test_failure ("a frame event was expected, but not received");
+}
+
+static void
+expect_enter_event (double x, double y)
+{
+ struct test_recorded_event *event;
+ struct test_recorded_enter_event *enter;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = event->last;
+
+ if (event->kind == POINTER_ENTER_EVENT)
+ {
+ enter = (struct test_recorded_enter_event *) event;
+
+ if (enter->x == x && enter->y == y)
+ free (event);
+ else
+ report_test_failure ("expected enter event received "
+ "with incorrect coordinates");
+ }
+ else
+ report_test_failure ("expected enter event, but it was not received");
+}
+
+static void
+expect_motion_event (double x, double y)
+{
+ struct test_recorded_event *event;
+ struct test_recorded_motion_event *motion;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = event->last;
+
+ if (event->kind == POINTER_MOTION_EVENT)
+ {
+ motion = (struct test_recorded_motion_event *) event;
+
+ if (motion->x == x && motion->y == y)
+ free (event);
+ else
+ report_test_failure ("expected motion event received "
+ "with incorrect coordinates");
+ }
+ else
+ report_test_failure ("expected motion event, but it was not received");
+}
+
+static void
+expect_leave_event (void)
+{
+ struct test_recorded_event *event;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = event->last;
+
+ if (event->kind == POINTER_LEAVE_EVENT)
+ free (event);
+ else
+ report_test_failure ("a leave event was expected, but not received");
+}
+
+static void
+expect_button_event (int button, int state)
+{
+ struct test_recorded_event *event;
+ struct test_recorded_button_event *button_event;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = event->last;
+
+ if (event->kind == POINTER_BUTTON_EVENT)
+ {
+ button_event = (struct test_recorded_button_event *) event;
+
+ if (button_event->button == button && button_event->state == state)
+ free (event);
+ else
+ report_test_failure ("expected button event received "
+ "with incorrect parameters");
+ }
+ else
+ report_test_failure ("expected button event, but it was not received");
+}
+
+static void
+expect_no_events (void)
+{
+ if (record_tail)
+ report_test_failure ("expected there to be no more events, "
+ "yet some arrived");
+}
+
static void
expect_surface_enter (double x, double y)
{
- struct test_expect_data data[2];
+ /* Record events. */
+ record_events ();
- test_log ("waiting for enter at %g, %g", x, y);
-
- memset (data, 0, sizeof data);
-
- data[0].x = x;
- data[0].y = y;
- data[0].kind = POINTER_ENTER_EVENT;
- data[1].kind = POINTER_FRAME_EVENT;
-
- /* Set the current listener data and do a roundtrip. */
- current_listener_data = data;
- num_listener_data = 2;
-
- wl_display_roundtrip (display->display);
- current_listener_data = NULL;
- num_listener_data = 0;
-
- /* See whether or not the event arrived. */
- if (!data[0].arrived || !data[1].arrived)
- report_test_failure ("expected events did not arrive");
- else
- test_log ("received enter followed by frame");
+ /* Expect an enter event, followed by a frame event. */
+ expect_frame_event ();
+ expect_enter_event (x, y);
+ expect_no_events ();
}
static void
expect_surface_motion (double x, double y)
{
- struct test_expect_data data[2];
+ /* Record events. */
+ record_events ();
- test_log ("waiting for motion at %g, %g", x, y);
-
- memset (data, 0, sizeof data);
-
- data[0].x = x;
- data[0].y = y;
- data[0].kind = POINTER_MOTION_EVENT;
- data[1].kind = POINTER_FRAME_EVENT;
-
- /* Set the current listener data and do a roundtrip. */
- current_listener_data = data;
- num_listener_data = 2;
-
- wl_display_roundtrip (display->display);
- current_listener_data = NULL;
- num_listener_data = 0;
-
- /* See whether or not the event arrived. */
- if (!data[0].arrived || !data[1].arrived)
- report_test_failure ("expected events did not arrive");
- else
- test_log ("received motion followed by frame");
+ /* Expect a motion event followed by a frame event. */
+ expect_frame_event ();
+ expect_motion_event (x, y);
+ expect_no_events ();
}
@@ -260,36 +582,14 @@ static const struct test_surface_listener test_surface_listener =
-/* Obtain the next test data record. The events arriving are checked
- to be in the order in which they arrive in
- current_listener_data. */
-
-static struct test_expect_data *
-get_next_expect_data (void)
-{
- int i;
-
- for (i = 0; i < num_listener_data; ++i)
- {
- if (current_listener_data[i].arrived)
- continue;
-
- return ¤t_listener_data[i];
- }
-
- return NULL;
-}
-
static void
handle_pointer_enter (void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t surface_x, wl_fixed_t surface_y)
{
- struct test_expect_data *test_data;
+ struct test_recorded_enter_event *event;
- test_data = get_next_expect_data ();
-
- if (!test_data)
+ if (!recording_events)
{
test_log ("ignored enter event at %g %g",
wl_fixed_to_double (surface_x),
@@ -297,26 +597,40 @@ handle_pointer_enter (void *data, struct wl_pointer *wl_pointer,
return;
}
- if (test_data->kind != POINTER_ENTER_EVENT)
- return;
+ event = malloc (sizeof *event);
- test_log ("got enter event at %g, %g",
- wl_fixed_to_double (surface_x),
- wl_fixed_to_double (surface_y));
+ if (!event)
+ report_test_failure ("failed to record event");
- if (test_data->x == wl_fixed_to_double (surface_x)
- && test_data->y == wl_fixed_to_double (surface_y))
- test_data->arrived = true;
- else
- report_test_failure ("missed enter event at %g %g",
- test_data->x, test_data->y);
+ event->header.kind = POINTER_ENTER_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+ event->x = wl_fixed_to_double (surface_x);
+ event->y = wl_fixed_to_double (surface_x);
+ event->surface = surface;
}
static void
handle_pointer_leave (void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface)
{
- /* ... */
+ struct test_recorded_leave_event *event;
+
+ if (!recording_events)
+ {
+ test_log ("ignored leave event");
+ return;
+ }
+
+ event = malloc (sizeof *event);
+
+ if (!event)
+ report_test_failure ("failed to record event");
+
+ event->header.kind = POINTER_LEAVE_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
}
static void
@@ -324,11 +638,9 @@ handle_pointer_motion (void *data, struct wl_pointer *wl_pointer,
uint32_t time, wl_fixed_t surface_x,
wl_fixed_t surface_y)
{
- struct test_expect_data *test_data;
+ struct test_recorded_motion_event *event;
- test_data = get_next_expect_data ();
-
- if (!test_data)
+ if (!recording_events)
{
test_log ("ignored motion event at %g %g",
wl_fixed_to_double (surface_x),
@@ -336,19 +648,17 @@ handle_pointer_motion (void *data, struct wl_pointer *wl_pointer,
return;
}
- if (test_data->kind != POINTER_MOTION_EVENT)
- return;
+ event = malloc (sizeof *event);
- test_log ("got motion event at %g, %g",
- wl_fixed_to_double (surface_x),
- wl_fixed_to_double (surface_y));
+ if (!event)
+ report_test_failure ("failed to record event");
- if (test_data->x == wl_fixed_to_double (surface_x)
- && test_data->y == wl_fixed_to_double (surface_y))
- test_data->arrived = true;
- else
- report_test_failure ("missed motion event at %g %g",
- test_data->x, test_data->y);
+ event->header.kind = POINTER_MOTION_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+ event->x = wl_fixed_to_double (surface_x);
+ event->y = wl_fixed_to_double (surface_y);
}
static void
@@ -356,7 +666,34 @@ handle_pointer_button (void *data, struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time, uint32_t button,
uint32_t state)
{
- /* TODO... */
+ struct test_recorded_button_event *event;
+
+ if (!recording_events)
+ {
+ test_log ("ignored button event");
+ return;
+ }
+
+ event = malloc (sizeof *event);
+
+ if (!event)
+ report_test_failure ("failed to record event");
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
+#endif
+
+ event->header.kind = POINTER_BUTTON_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+ event->button = button;
+ event->state = state;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
}
static void
@@ -369,21 +706,31 @@ handle_pointer_axis (void *data, struct wl_pointer *wl_pointer,
static void
handle_pointer_frame (void *data, struct wl_pointer *wl_pointer)
{
- struct test_expect_data *test_data;
+ struct test_recorded_frame_event *event;
- test_data = get_next_expect_data ();
-
- if (!test_data)
+ if (!recording_events)
{
test_log ("ignored frame event");
return;
}
- if (test_data->kind != POINTER_FRAME_EVENT)
- return;
+ event = malloc (sizeof *event);
- test_log ("got frame event");
- test_data->arrived = true;
+ if (!event)
+ report_test_failure ("failed to record event");
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
+#endif
+
+ event->header.kind = POINTER_FRAME_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
}
static void