diff --git a/12to11-test.xml b/12to11-test.xml
index 870fbba..9f9334d 100644
--- a/12to11-test.xml
+++ b/12to11-test.xml
@@ -276,6 +276,10 @@
state. If the value already exists, post a value_exists
error. If the valuator is more than 65535 or 0, post an
invalid_valuator error.
+
+ If this valuator is passed to a request that generates events
+ with raw valuators, the value specified will be used as the
+ raw value for the valuator as well.
@@ -632,6 +636,130 @@
+
+
+ Dispatch a focus in event to the seat.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dispatch a focus out event to the seat.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dispatch a raw key press event to the seat.
+
+
+
+
+
+
+
+
+
+
+ Dispatch a raw key release event to the seat.
+
+
+
+
+
+
+
+
+
+
+ Dispatch a regular key press event to the seat.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dispatch a regular key release event to the seat.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This event is sent immediately after the test_seat_controller
diff --git a/seat.c b/seat.c
index 05673eb..9efafca 100644
--- a/seat.c
+++ b/seat.c
@@ -1833,6 +1833,13 @@ MakeSeatForDevicePair (int master_keyboard, int master_pointer,
seat->latched_group = state.latched_group;
seat->effective_group = state.group;
+ /* If a keymap is already attached, initialize seat->key_pressed
+ now. */
+ if (xkb_desc)
+ seat->key_pressed
+ = XLCalloc (MaskLen (xkb_desc->max_key_code
+ - xkb_desc->min_key_code), 1);
+
/* And select for XKB events from the master keyboard device. If
the server does not support accessing input extension devices
with Xkb, an error will result. */
diff --git a/test_seat.c b/test_seat.c
index c8f37c7..8f3ef18 100644
--- a/test_seat.c
+++ b/test_seat.c
@@ -1129,6 +1129,135 @@ SetLastUserTime (struct wl_client *client, struct wl_resource *resource,
controller->seat->last_user_time.milliseconds = milliseconds;
}
+static void
+DispatchXIFocusIn (struct wl_client *client, struct wl_resource *resource,
+ uint32_t time, int32_t sourceid, int32_t detail,
+ uint32_t root, uint32_t event, uint32_t child,
+ wl_fixed_t root_x, wl_fixed_t root_y,
+ wl_fixed_t event_x, wl_fixed_t event_y, int32_t mode,
+ int32_t focus, int32_t same_screen,
+ struct wl_resource *buttons_resource,
+ struct wl_resource *mods_resource,
+ struct wl_resource *group_resource)
+{
+ TestSeatController *controller;
+ XIFocusInEvent test_event;
+
+ controller = wl_resource_get_user_data (resource);
+ GenerateCrossingEvent (XI_FocusIn, controller, test_event);
+
+ /* Now dispatch the event. */
+ DispatchTestEvent (controller, event, (XIEvent *) &test_event);
+}
+
+static void
+DispatchXIFocusOut (struct wl_client *client, struct wl_resource *resource,
+ uint32_t time, int32_t sourceid, int32_t detail,
+ uint32_t root, uint32_t event, uint32_t child,
+ wl_fixed_t root_x, wl_fixed_t root_y,
+ wl_fixed_t event_x, wl_fixed_t event_y, int32_t mode,
+ int32_t focus, int32_t same_screen,
+ struct wl_resource *buttons_resource,
+ struct wl_resource *mods_resource,
+ struct wl_resource *group_resource)
+{
+ TestSeatController *controller;
+ XIFocusInEvent test_event;
+
+ controller = wl_resource_get_user_data (resource);
+ GenerateCrossingEvent (XI_FocusOut, controller, test_event);
+
+ /* Now dispatch the event. */
+ DispatchTestEvent (controller, event, (XIEvent *) &test_event);
+}
+
+#define GenerateRawEvent(event_type, controller, test_event) \
+ test_event.type = GenericEvent; \
+ test_event.serial = request_serial_counter++; \
+ test_event.send_event = True; \
+ test_event.display = compositor.display; \
+ test_event.extension = xi2_opcode; \
+ test_event.evtype = event_type; \
+ test_event.time = time; \
+ test_event.deviceid = controller->seat->master_pointer; \
+ test_event.sourceid = sourceid; \
+ test_event.detail = detail; \
+ test_event.flags = flags; \
+ TranslateTestValuators (valuators_resource, &test_event.valuators); \
+ test_event.raw_values = test_event.valuators.values;
+
+static void
+DispatchXIRawKeyPress (struct wl_client *client, struct wl_resource *resource,
+ uint32_t time, int32_t sourceid, int32_t detail,
+ int32_t flags, struct wl_resource *valuators_resource)
+{
+ TestSeatController *controller;
+ XIRawEvent test_event;
+
+ controller = wl_resource_get_user_data (resource);
+ GenerateRawEvent (XI_RawKeyPress, controller, test_event);
+
+ /* Now dispatch the event. */
+ HandleRawKey (&test_event);
+}
+
+static void
+DispatchXIRawKeyRelease (struct wl_client *client, struct wl_resource *resource,
+ uint32_t time, int32_t sourceid, int32_t detail,
+ int32_t flags, struct wl_resource *valuators_resource)
+{
+ TestSeatController *controller;
+ XIRawEvent test_event;
+
+ controller = wl_resource_get_user_data (resource);
+ GenerateRawEvent (XI_RawKeyRelease, controller, test_event);
+
+ /* Now dispatch the event. */
+ HandleRawKey (&test_event);
+}
+
+static void
+DispatchXIKeyPress (struct wl_client *client, struct wl_resource *resource,
+ uint32_t time, int32_t sourceid, int32_t detail,
+ uint32_t root, uint32_t event, uint32_t child,
+ wl_fixed_t root_x, wl_fixed_t root_y,
+ wl_fixed_t event_x, wl_fixed_t event_y, int32_t flags,
+ struct wl_resource *buttons_resource,
+ struct wl_resource *valuators_resource,
+ struct wl_resource *mods_resource,
+ struct wl_resource *group_resource)
+{
+ TestSeatController *controller;
+ XIDeviceEvent test_event;
+
+ controller = wl_resource_get_user_data (resource);
+ GenerateDeviceEvent (XI_KeyPress, controller, test_event);
+
+ /* Now dispatch the event. */
+ DispatchTestEvent (controller, event, (XIEvent *) &test_event);
+}
+
+static void
+DispatchXIKeyRelease (struct wl_client *client, struct wl_resource *resource,
+ uint32_t time, int32_t sourceid, int32_t detail,
+ uint32_t root, uint32_t event, uint32_t child,
+ wl_fixed_t root_x, wl_fixed_t root_y,
+ wl_fixed_t event_x, wl_fixed_t event_y, int32_t flags,
+ struct wl_resource *buttons_resource,
+ struct wl_resource *valuators_resource,
+ struct wl_resource *mods_resource,
+ struct wl_resource *group_resource)
+{
+ TestSeatController *controller;
+ XIDeviceEvent test_event;
+
+ controller = wl_resource_get_user_data (resource);
+ GenerateDeviceEvent (XI_KeyRelease, controller, test_event);
+
+ /* Now dispatch the event. */
+ DispatchTestEvent (controller, event, (XIEvent *) &test_event);
+}
+
static const struct test_seat_controller_interface seat_controller_impl =
{
.destroy = DestroySeatController,
@@ -1143,6 +1272,12 @@ static const struct test_seat_controller_interface seat_controller_impl =
.dispatch_XI_ButtonRelease = DispatchXIButtonRelease,
.get_device_controller = GetDeviceController,
.set_last_user_time = SetLastUserTime,
+ .dispatch_XI_FocusIn = DispatchXIFocusIn,
+ .dispatch_XI_FocusOut = DispatchXIFocusOut,
+ .dispatch_XI_RawKeyPress = DispatchXIRawKeyPress,
+ .dispatch_XI_RawKeyRelease = DispatchXIRawKeyRelease,
+ .dispatch_XI_KeyPress = DispatchXIKeyPress,
+ .dispatch_XI_KeyRelease = DispatchXIKeyRelease,
};
static void
@@ -1248,6 +1383,11 @@ XLGetTestSeat (struct wl_client *client, struct wl_resource *resource,
/* Add the seat to the live seat list. */
live_seats = XLListPrepend (live_seats, seat);
+ /* Initialize seat->key_pressed. */
+ seat->key_pressed
+ = XLCalloc (MaskLen (xkb_desc->max_key_code
+ - xkb_desc->min_key_code), 1);
+
/* Retain the seat. */
RetainSeat (seat);
controller->seat = seat;
diff --git a/tests/seat_test.c b/tests/seat_test.c
index 6502866..8a64023 100644
--- a/tests/seat_test.c
+++ b/tests/seat_test.c
@@ -30,6 +30,9 @@ enum test_expect_event_kind
POINTER_LEAVE_EVENT,
POINTER_BUTTON_EVENT,
POINTER_AXIS_VALUE120_EVENT,
+ KEYBOARD_ENTER_EVENT,
+ KEYBOARD_KEY_EVENT,
+ KEYBOARD_MODIFIERS_EVENT,
};
struct test_recorded_event
@@ -95,6 +98,45 @@ struct test_recorded_axis_value120_event
int32_t value120;
};
+struct test_recorded_keyboard_enter_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+
+ /* The event surface. */
+ struct wl_surface *surface;
+
+ /* The keys. */
+ uint32_t *keys;
+
+ /* The number of keys in that array. */
+ size_t num_keys;
+};
+
+struct test_recorded_keyboard_key_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+
+ /* The key. */
+ uint32_t key;
+
+ /* And the key state. */
+ uint32_t state;
+};
+
+struct test_recorded_keyboard_modifiers_event
+{
+ /* The event header. */
+ struct test_recorded_event header;
+
+ /* The modifiers. */
+ uint32_t base, latched, locked;
+
+ /* The group. */
+ uint32_t group;
+};
+
struct test_subsurface
{
/* The subsurface itself. */
@@ -111,6 +153,7 @@ enum test_kind
TEST_CLICK_KIND,
TEST_GRAB_KIND,
TEST_VALUATOR_KIND,
+ TEST_KEY_KIND,
};
static const char *test_names[] =
@@ -120,9 +163,10 @@ static const char *test_names[] =
"test_click",
"test_grab",
"test_valuator",
+ "test_key",
};
-#define LAST_TEST TEST_VALUATOR_KIND
+#define LAST_TEST TEST_KEY_KIND
#define TEST_SOURCE_DEVICE 4500000
/* The display. */
@@ -164,6 +208,11 @@ static void expect_motion_event (double, double);
static void expect_leave_event (void);
static void expect_button_event (int, int);
static void expect_axis_value120_event (uint32_t, int32_t);
+static void expect_keyboard_enter_event (struct wl_surface *, uint32_t *,
+ size_t);
+static void expect_keyboard_key_event (uint32_t, uint32_t);
+static void expect_keyboard_modifiers_event (uint32_t, uint32_t,
+ uint32_t, uint32_t);
static void expect_no_events (void);
@@ -635,6 +684,71 @@ run_valuator_test (void)
expect_leave_event ();
}
+static void
+run_key_test (void)
+{
+ test_seat_controller_dispatch_XI_FocusIn (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ XINotifyAncestor,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ XINotifyNonlinear,
+ 0,
+ 1,
+ NULL, NULL, NULL);
+ test_seat_controller_dispatch_XI_RawKeyPress (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 67,
+ 0,
+ NULL);
+ test_seat_controller_dispatch_XI_KeyPress (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 67,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ 0,
+ NULL, NULL, NULL, NULL);
+ test_seat_controller_dispatch_XI_RawKeyRelease (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 67,
+ 0,
+ NULL);
+ test_seat_controller_dispatch_XI_KeyRelease (display->seat->controller,
+ test_get_time (),
+ TEST_SOURCE_DEVICE,
+ 67,
+ test_get_root (),
+ test_surface_window,
+ None,
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ wl_fixed_from_double (2.0),
+ 0,
+ NULL, NULL, NULL, NULL);
+
+ /* Now, verify the events as they arrive. */
+ record_events ();
+ expect_keyboard_key_event (59, WL_KEYBOARD_KEY_STATE_RELEASED);
+ expect_keyboard_key_event (59, WL_KEYBOARD_KEY_STATE_PRESSED);
+ expect_keyboard_modifiers_event (0, 0, 0, 0);
+ expect_keyboard_enter_event (wayland_surface, NULL, 0);
+}
+
static void
test_single_step (enum test_kind kind)
{
@@ -877,6 +991,22 @@ test_single_step (enum test_kind kind)
frame (); */
run_valuator_test ();
+ kind = TEST_KEY_KIND;
+ goto again;
+
+ case TEST_KEY_KIND:
+ /* Test simple key press and key release. Dispatch an
+ XI_FocusIn event to the test surface. Then, press and
+ release the keycode 67, generating both raw and device
+ events. Verify that the following events are sent to the
+ keyboard.
+
+ enter (SERIAL, SURFACE, array[0])
+ modifiers (SERIAL, 0, 0, 0, 0)
+ key (SERIAL, TIME, 59, WL_KEYBOARD_KEY_STATE_PRESSED)
+ key (SERIAL, TIME, 59, WL_KEYBOARD_KEY_STATE_RELEASED) */
+
+ run_key_test ();
break;
}
@@ -1046,6 +1176,105 @@ expect_axis_value120_event (uint32_t axis, int32_t value120)
"received");
}
+static void
+expect_keyboard_enter_event (struct wl_surface *surface, uint32_t *keys,
+ size_t num_keys)
+{
+ struct test_recorded_event *event;
+ struct test_recorded_keyboard_enter_event *keyboard_enter_event;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = record_tail->last;
+
+ if (event->kind == KEYBOARD_ENTER_EVENT)
+ {
+ keyboard_enter_event
+ = (struct test_recorded_keyboard_enter_event *) event;
+
+ if (keyboard_enter_event->num_keys != num_keys
+ || surface != keyboard_enter_event->surface
+ || memcmp (keyboard_enter_event->keys, keys,
+ num_keys * sizeof *keys))
+ report_test_failure ("expected keyboard_enter event passed"
+ " with invalid parameters");
+ else
+ {
+ free (keyboard_enter_event->keys);
+ free (event);
+ }
+ }
+ else
+ report_test_failure ("expected keyboard_enter_event, but it was"
+ " not received");
+}
+
+static void
+expect_keyboard_key_event (uint32_t key, uint32_t state)
+{
+ struct test_recorded_event *event;
+ struct test_recorded_keyboard_key_event *keyboard_key_event;
+
+ event = record_tail;
+
+ if (!event)
+ report_test_failure ("expected event not sent");
+
+ record_tail = record_tail->last;
+
+ if (event->kind == KEYBOARD_KEY_EVENT)
+ {
+ keyboard_key_event
+ = (struct test_recorded_keyboard_key_event *) event;
+
+ if (key != keyboard_key_event->key
+ || state != keyboard_key_event->state)
+ report_test_failure ("expected keyboard_key passed with"
+ " invalid parameters");
+ else
+ free (event);
+ }
+ else
+ report_test_failure ("expected keyboard_key_event, but it was"
+ " not received");
+}
+
+static void
+expect_keyboard_modifiers_event (uint32_t base, uint32_t latched,
+ uint32_t locked, uint32_t group)
+{
+ struct test_recorded_event *event;
+ struct test_recorded_keyboard_modifiers_event *keyboard_modifiers_event;
+
+ event = record_tail;
+
+ if (!event)
+ return;
+
+ record_tail = record_tail->last;
+
+ if (event->kind == KEYBOARD_MODIFIERS_EVENT)
+ {
+ keyboard_modifiers_event
+ = (struct test_recorded_keyboard_modifiers_event *) event;
+
+ if (keyboard_modifiers_event->base != base
+ || keyboard_modifiers_event->latched != latched
+ || keyboard_modifiers_event->locked != locked
+ || keyboard_modifiers_event->group != group)
+ report_test_failure ("expected keyboard_modifiers passed with"
+ " invalid parameters");
+ else
+ free (event);
+ }
+ else
+ report_test_failure ("expected keyboard_modifiers_event, but it was"
+ " not received");
+}
+
static void
expect_no_events (void)
{
@@ -1351,6 +1580,156 @@ static const struct wl_pointer_listener pointer_listener =
+static void
+handle_keyboard_keymap (void *data, struct wl_keyboard *keyboard,
+ uint32_t format, int32_t fd, uint32_t size)
+{
+ close (fd);
+}
+
+static void
+handle_keyboard_enter (void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, struct wl_surface *surface,
+ struct wl_array *keys)
+{
+ struct test_recorded_keyboard_enter_event *event;
+
+ if (!recording_events)
+ {
+ test_log ("ignored keyboard enter 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 = KEYBOARD_ENTER_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+ if (keys->size % sizeof (uint32_t))
+ report_test_failure ("reported key size modulo"
+ " uint32_t!");
+
+ event->keys = malloc (keys->size);
+
+ if (!event->keys)
+ report_test_failure ("failed to allocate key array");
+
+ memcpy (event->keys, keys->data, keys->size);
+ event->num_keys = keys->size / sizeof (uint32_t);
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+}
+
+static void
+handle_keyboard_leave (void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, struct wl_surface *surface)
+{
+
+}
+
+static void
+handle_keyboard_key (void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, uint32_t time, uint32_t key,
+ uint32_t state)
+{
+ struct test_recorded_keyboard_key_event *event;
+
+ if (!recording_events)
+ {
+ test_log ("ignored keyboard key 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 = KEYBOARD_KEY_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+ event->key = key;
+ event->state = state;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+}
+
+static void
+handle_keyboard_modifiers (void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, uint32_t mods_depressed,
+ uint32_t mods_latched, uint32_t mods_locked,
+ uint32_t group)
+{
+ struct test_recorded_keyboard_modifiers_event *event;
+
+ if (!recording_events)
+ {
+ test_log ("ignored modifiers event");
+ return;
+ }
+
+ event = malloc (sizeof *event);
+
+ if (!event)
+ report_test_failure ("failed to record modifiers event");
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
+#endif
+
+ event->header.kind = KEYBOARD_MODIFIERS_EVENT;
+ event->header.last = record_tail;
+ record_tail = &event->header;
+
+ event->base = mods_depressed;
+ event->latched = mods_latched;
+ event->locked = mods_locked;
+ event->group = group;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+}
+
+static void
+handle_keyboard_repeat_info (void *data, struct wl_keyboard *keyboard,
+ int32_t rate, int32_t delay)
+{
+
+}
+
+static const struct wl_keyboard_listener keyboard_listener =
+ {
+ handle_keyboard_keymap,
+ handle_keyboard_enter,
+ handle_keyboard_leave,
+ handle_keyboard_key,
+ handle_keyboard_modifiers,
+ handle_keyboard_repeat_info,
+ };
+
+
+
static void
submit_surface_damage (struct wl_surface *surface, int x, int y, int width,
int height)
@@ -1420,6 +1799,10 @@ run_test (void)
wl_pointer_add_listener (display->seat->pointer, &pointer_listener,
NULL);
+ /* And the keyboard listener. */
+ wl_keyboard_add_listener (display->seat->keyboard, &keyboard_listener,
+ NULL);
+
while (true)
{
if (wl_display_dispatch (display->display) == -1)
diff --git a/tests/test_harness.c b/tests/test_harness.c
index 3ca8959..2c5e630 100644
--- a/tests/test_harness.c
+++ b/tests/test_harness.c
@@ -907,6 +907,12 @@ test_init_seat (struct test_display *display)
if (!display->seat->pointer)
report_test_failure ("failed to bind to test pointer");
+
+ display->seat->keyboard
+ = wl_seat_get_keyboard (display->seat->seat);
+
+ if (!display->seat->keyboard)
+ report_test_failure ("failed to bind to test keyboard");
}
void __attribute__ ((noreturn))
diff --git a/tests/test_harness.h b/tests/test_harness.h
index 46298a9..2bab262 100644
--- a/tests/test_harness.h
+++ b/tests/test_harness.h
@@ -49,6 +49,9 @@ struct test_seat
/* The wl_pointer resource. */
struct wl_pointer *pointer;
+ /* The keyboard resource. */
+ struct wl_keyboard *keyboard;
+
/* The device ID of the seat. */
uint32_t device_id;