forked from 12to11/12to11
Add scroll valuator tests
* 12to11-test.xml (test_manager): <error>: New errors. (test_XIDeviceInfo, test_device_controller): New interfaces. (test_seat_controller): <get_device_controller>: New request. <device_id>: New event. * seat.c (NoticeDeviceDisabled): Ignore test seats. (XLSeatDispatchCoreKeyEvent): Expand commentary. * test_seat.c (struct _TestDeviceController) (struct _TestXIDeviceInfo): New structs. (DestroyXIValuatorState): New function. (AddValuatorToTestXIValuatorState): Fix crashes. (XIValuatorState_impl): Add DestroyXIValuatorState. (DestroyDeviceInfo, SetDeviceId, SetName, SetUse, SetAttachment) (SetEnabled, AddXIScrollClassInfo, AddXIValuatorClassInfo): New functions. (XIDeviceInfo_impl): New interface implementation. (HandleXIDeviceInfoDestroy): New function. (DestroyDeviceController, AddDeviceInfo, GetDeviceInfo): New functions. (device_controller_impl): New interface. (HandleTestDeviceControllerDestroy): New function. (GetDeviceController): New function. (seat_controller_impl): Add it. (XLGetTestSeat): Send new `device_id' event. * tests/seat_test.c (enum test_expect_event_kind): Add POINTER_AXIS_VALUE120_EVENT. (struct test_recorded_axis_value120_event): New event kind. (enum test_kind): Add TEST_VALUATOR_KIND. (test_names): Add test_valuator. (LAST_TEST): Set to TEST_VALUATOR_KIND. (run_valuator_test): New function. (test_single_step): Implement accordingly. (expect_axis_value120_event, handle_pointer_axis_value120): New functions. * tests/test_harness.c (handle_seat_controller_device_id): New function. (seat_controller_listener): New listener. (test_init_seat): Wait for device ID and init device controller. * tests/test_harness.h (struct test_seat): Add device controller and device ID fields.
This commit is contained in:
parent
e2afe671df
commit
163dca96bd
6 changed files with 992 additions and 12 deletions
168
12to11-test.xml
168
12to11-test.xml
|
@ -45,6 +45,14 @@
|
|||
summary="an invalid version was specified"/>
|
||||
<entry name="invalid_valuator" value="7"
|
||||
summary="the specified valuator is invalid"/>
|
||||
<entry name="invalid_device_id" value="8"
|
||||
summary="the specified device ID is too small"/>
|
||||
<entry name="incomplete_device_info" value="9"
|
||||
summary="the specified device info is incomplete"/>
|
||||
<entry name="device_exists" value="10"
|
||||
summary="the specified artifical device already exists"/>
|
||||
<entry name="invalid_label" value="11"
|
||||
summary="the specified label is invalid"/>
|
||||
</enum>
|
||||
|
||||
<request name="get_test_surface">
|
||||
|
@ -239,12 +247,156 @@
|
|||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="test_XIDeviceInfo" version="1">
|
||||
<description summary="XInput 2 device information">
|
||||
Simulated XInput 2 device information for a device.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy test device info">
|
||||
Destroy the test device info resource.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_device_id">
|
||||
<description summary="set the device ID">
|
||||
Set the device ID of this device info structure to the
|
||||
specified ID. If the ID is less than 65536, post an
|
||||
invalid_device_id error.
|
||||
</description>
|
||||
|
||||
<arg name="device_id" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="set_name">
|
||||
<description summary="set the device name">
|
||||
Set the name of this device to the specified name.
|
||||
</description>
|
||||
|
||||
<arg name="name" type="string"/>
|
||||
</request>
|
||||
|
||||
<request name="set_use">
|
||||
<description summary="set the device use">
|
||||
Set the use of this device to the specified value.
|
||||
</description>
|
||||
|
||||
<arg name="use" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="set_attachment">
|
||||
<description summary="set the device attachment">
|
||||
Set the device attachment to the master pointer and keyboard
|
||||
of the specified seat controller.
|
||||
</description>
|
||||
|
||||
<arg name="attachment" type="object"
|
||||
interface="test_seat_controller"/>
|
||||
</request>
|
||||
|
||||
<request name="set_enabled">
|
||||
<description summary="set device enabled">
|
||||
Set whether or not the device is enabled.
|
||||
</description>
|
||||
|
||||
<arg name="enabled" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="add_XIScrollClassInfo">
|
||||
<description summary="add a scroll class to the device information">
|
||||
Add a scroll class with the specified type, source ID, number,
|
||||
scroll type, increment and flags to the device info.
|
||||
|
||||
If the specified source device ID is less than 65536, post an
|
||||
invalid_device_id error.
|
||||
</description>
|
||||
|
||||
<arg name="sourceid" type="int"/>
|
||||
<arg name="number" type="int"/>
|
||||
<arg name="scroll_type" type="int"/>
|
||||
<arg name="increment" type="fixed"/>
|
||||
<arg name="flags" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="add_XIValuatorClassInfo">
|
||||
<description summary="add a valuator class to the device information">
|
||||
Add a valuator class with the specified type, source ID,
|
||||
number, label, min, max, value, resolution and mode to the
|
||||
device info.
|
||||
|
||||
If the specified source device ID is less than 65536, post an
|
||||
invalid_device_id error.
|
||||
|
||||
Intern the label into an atom. If the string is empty, raise
|
||||
an invalid_label error.
|
||||
</description>
|
||||
|
||||
<arg name="sourceid" type="int"/>
|
||||
<arg name="number" type="int"/>
|
||||
<arg name="label" type="string"/>
|
||||
<arg name="min" type="fixed"/>
|
||||
<arg name="max" type="fixed"/>
|
||||
<arg name="value" type="fixed"/>
|
||||
<arg name="resolution" type="int"/>
|
||||
<arg name="mode" type="int"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="test_device_controller" version="1">
|
||||
<description summary="test device controller">
|
||||
This object allows registering a list of artificial input
|
||||
devices to use during tests. These devices must have a device
|
||||
ID larger than 65535, and are removed upon destruction of the
|
||||
test controller resource.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy test device controller">
|
||||
Destroy the test device controller resource.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="add_device_info">
|
||||
<description summary="add artificial device">
|
||||
Register a device with the specified device information. If
|
||||
the device info is incomplete, meaning that one of
|
||||
set_device_id, set_name, set_use, set_attachment, or
|
||||
set_enabled was not called after it was created, post an
|
||||
incomplete_device_info error. If the device ID already
|
||||
exists, post a device_exists error if the device was not
|
||||
created by this device controller, or update the device with
|
||||
the new information if it was.
|
||||
|
||||
If a test seat is created with the device ID in the specified
|
||||
device info after add_device_info is called, then the seat
|
||||
will not possess this device info.
|
||||
|
||||
The device will be removed upon destruction of the
|
||||
test_device_controller resource.
|
||||
</description>
|
||||
|
||||
<arg name="device_info" type="object" interface="test_XIDeviceInfo"/>
|
||||
</request>
|
||||
|
||||
<request name="get_device_info">
|
||||
<description summary="create device info">
|
||||
Create a device information object. The device information
|
||||
object is not associated with the test controller in any way.
|
||||
</description>
|
||||
|
||||
<arg name="id" type="new_id" interface="test_XIDeviceInfo"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="test_seat_controller" version="1">
|
||||
<description summary="test seat">
|
||||
This object extends a wl_seat created with the
|
||||
test_manager.get_test_seat request with several requests to
|
||||
dispatch generated events.
|
||||
|
||||
Immediately after being created, a device_id event is sent with
|
||||
the device ID of this seat.
|
||||
|
||||
If the seat associated with the test controller is destroyed by
|
||||
the time a request is made with the test controller, the latter
|
||||
request is simply ignored.
|
||||
|
@ -420,5 +572,21 @@
|
|||
<arg name="group" type="object" interface="test_XIModifierState"
|
||||
allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<request name="get_device_controller">
|
||||
<description summary="get device controller">
|
||||
Obtain a new device controller.
|
||||
</description>
|
||||
|
||||
<arg name="id" type="new_id" interface="test_device_controller"/>
|
||||
</request>
|
||||
|
||||
<event name="device_id">
|
||||
<description summary="device ID">
|
||||
This event is sent immediately after the test_seat_controller
|
||||
is created, with the device ID of the test seat.
|
||||
</description>
|
||||
<arg name="device_id" type="uint"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
14
seat.c
14
seat.c
|
@ -95,6 +95,7 @@ enum
|
|||
IsInPinchGesture = (1 << 9),
|
||||
IsInSwipeGesture = (1 << 10),
|
||||
IsTestSeat = (1 << 11),
|
||||
IsTestDeviceSpecified = (1 << 12),
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -2189,7 +2190,9 @@ NoticeDeviceDisabled (int deviceid)
|
|||
|
||||
seat = XLLookUpAssoc (seats, deviceid);
|
||||
|
||||
if (seat)
|
||||
/* Test seats should not be destroyed here. */
|
||||
|
||||
if (seat && !(seat->flags & IsTestSeat))
|
||||
{
|
||||
/* The device has been disabled, mark the seat inert and
|
||||
dereference it. The seat is still referred to by the
|
||||
|
@ -6181,13 +6184,16 @@ XLSeatDispatchCoreKeyEvent (Seat *seat, Surface *surface, XEvent *event,
|
|||
if (keysym)
|
||||
{
|
||||
/* If looking up the event keycode also results in the keysym,
|
||||
then just use the keycode specified in the event. */
|
||||
then just use the keycode specified in the event. This is
|
||||
because French keyboard layouts have multiple keycodes that
|
||||
decode to the same keysym, which causes problems later on
|
||||
when Wayland clients keep repeating the "a" key, as a keysym
|
||||
was looked up for the key press but not for the corresponding
|
||||
key release. */
|
||||
if (XkbLookupKeySym (compositor.display, event->xkey.keycode,
|
||||
event->xkey.state, &mods_return, &sym_return)
|
||||
&& keysym == sym_return)
|
||||
{
|
||||
keycode = event->xkey.keycode;
|
||||
}
|
||||
else
|
||||
keycode = XKeysymToKeycode (compositor.display, keysym);
|
||||
|
||||
|
|
451
test_seat.c
451
test_seat.c
|
@ -23,9 +23,11 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
|||
have to include anything itself! */
|
||||
|
||||
typedef struct _TestSeatController TestSeatController;
|
||||
typedef struct _TestDeviceController TestDeviceController;
|
||||
typedef struct _TestXIModifierState TestXIModifierState;
|
||||
typedef struct _TestXIValuatorState TestXIValuatorState;
|
||||
typedef struct _TestXIButtonState TestXIButtonState;
|
||||
typedef struct _TestXIDeviceInfo TestXIDeviceInfo;
|
||||
|
||||
/* The current test seat counter. */
|
||||
static unsigned int test_seat_counter;
|
||||
|
@ -42,6 +44,18 @@ struct _TestSeatController
|
|||
struct wl_resource *resource;
|
||||
};
|
||||
|
||||
struct _TestDeviceController
|
||||
{
|
||||
/* The associated struct wl_resource. */
|
||||
struct wl_resource *resource;
|
||||
|
||||
/* Array of device IDs used by this test device controller. */
|
||||
int *device_ids;
|
||||
|
||||
/* Number of device IDs associated with this controller. */
|
||||
int num_ids;
|
||||
};
|
||||
|
||||
struct _TestXIModifierState
|
||||
{
|
||||
/* Modifier state. These fields mean the same as they do in
|
||||
|
@ -73,6 +87,43 @@ struct _TestXIButtonState
|
|||
unsigned char mask[XIMaskLen (8)];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
StateDeviceIdSet = 1,
|
||||
StateNameSet = 1 << 1,
|
||||
StateUseSet = 1 << 2,
|
||||
StateAttachmentSet = 1 << 3,
|
||||
StateEnabledSet = 1 << 4,
|
||||
StateComplete = 0x1f,
|
||||
};
|
||||
|
||||
struct _TestXIDeviceInfo
|
||||
{
|
||||
/* The associated resource. */
|
||||
struct wl_resource *resource;
|
||||
|
||||
/* The device name. */
|
||||
char *name;
|
||||
|
||||
/* Array of classes. */
|
||||
XIAnyClassInfo **classes;
|
||||
|
||||
/* The device ID. */
|
||||
int device_id;
|
||||
|
||||
/* The use, attachment. */
|
||||
int use, attachment;
|
||||
|
||||
/* Whether or not the device is enabled. */
|
||||
Bool enabled;
|
||||
|
||||
/* The number of classes there are. */
|
||||
int num_classes;
|
||||
|
||||
/* How many fields are set. */
|
||||
int state;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void
|
||||
|
@ -168,6 +219,13 @@ HandleXIButtonStateDestroy (struct wl_resource *resource)
|
|||
|
||||
|
||||
|
||||
static void
|
||||
DestroyXIValuatorState (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
AddValuatorToTestXIValuatorState (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
|
@ -200,7 +258,7 @@ AddValuatorToTestXIValuatorState (struct wl_client *client,
|
|||
if (state->mask_len < XIMaskLen (valuator))
|
||||
{
|
||||
state->mask = XLRealloc (state->mask,
|
||||
state->mask_len);
|
||||
XIMaskLen (valuator));
|
||||
|
||||
/* Clear the newly allocated part of the mask. */
|
||||
memset (state->mask + state->mask_len,
|
||||
|
@ -221,7 +279,7 @@ AddValuatorToTestXIValuatorState (struct wl_client *client,
|
|||
if (i == valuator)
|
||||
/* Insert the new value. */
|
||||
new_values[j++] = wl_fixed_to_double (value);
|
||||
else if (XIMaskIsSet (state->mask, valuator))
|
||||
else if (XIMaskIsSet (state->mask, i))
|
||||
/* Use the old value. */
|
||||
new_values[j++] = *old_values++;
|
||||
}
|
||||
|
@ -238,6 +296,7 @@ AddValuatorToTestXIValuatorState (struct wl_client *client,
|
|||
|
||||
static const struct test_XIValuatorState_interface XIValuatorState_impl =
|
||||
{
|
||||
.destroy = DestroyXIValuatorState,
|
||||
.add_valuator = AddValuatorToTestXIValuatorState,
|
||||
};
|
||||
|
||||
|
@ -261,7 +320,354 @@ HandleXIValuatorStateDestroy (struct wl_resource *resource)
|
|||
|
||||
|
||||
static void
|
||||
DestroyTestSeatController (struct wl_client *client,
|
||||
DestroyDeviceInfo (struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
SetDeviceId (struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t device_id)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
|
||||
if (device_id < 65536)
|
||||
{
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_DEVICE_ID,
|
||||
"invalid device id specified");
|
||||
return;
|
||||
}
|
||||
|
||||
info->device_id = device_id;
|
||||
info->state |= StateDeviceIdSet;
|
||||
}
|
||||
|
||||
static void
|
||||
SetName (struct wl_client *client, struct wl_resource *resource,
|
||||
const char *name)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
|
||||
if (info->name)
|
||||
XLFree (info->name);
|
||||
info->name = XLStrdup (name);
|
||||
info->state |= StateNameSet;
|
||||
}
|
||||
|
||||
static void
|
||||
SetUse (struct wl_client *client, struct wl_resource *resource,
|
||||
int32_t use)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
info->use = use;
|
||||
info->state |= StateUseSet;
|
||||
}
|
||||
|
||||
static void
|
||||
SetAttachment (struct wl_client *client, struct wl_resource *resource,
|
||||
struct wl_resource *attachment_resource)
|
||||
{
|
||||
TestSeatController *controller;
|
||||
TestXIDeviceInfo *info;
|
||||
|
||||
controller = wl_resource_get_user_data (attachment_resource);
|
||||
info = wl_resource_get_user_data (resource);
|
||||
|
||||
info->attachment = controller->seat->master_pointer;
|
||||
info->state |= StateAttachmentSet;
|
||||
}
|
||||
|
||||
static void
|
||||
SetEnabled (struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t enabled)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
|
||||
if (enabled)
|
||||
info->enabled = True;
|
||||
else
|
||||
info->enabled = False;
|
||||
info->state |= StateEnabledSet;
|
||||
}
|
||||
|
||||
static void
|
||||
AddXIScrollClassInfo (struct wl_client *client, struct wl_resource *resource,
|
||||
int32_t sourceid, int32_t number, int32_t scroll_type,
|
||||
wl_fixed_t increment, int32_t flags)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
XIScrollClassInfo *class;
|
||||
|
||||
if (sourceid < 65536)
|
||||
{
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_DEVICE_ID,
|
||||
"invalid device ID specified");
|
||||
return;
|
||||
}
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
|
||||
class = XLMalloc (sizeof *class);
|
||||
class->type = XIScrollClass;
|
||||
class->sourceid = sourceid;
|
||||
class->number = number;
|
||||
class->scroll_type = scroll_type;
|
||||
class->increment = wl_fixed_to_double (increment);
|
||||
class->flags = flags;
|
||||
|
||||
/* Extend info->classes to hold more classes. */
|
||||
info->num_classes++;
|
||||
info->classes = XLRealloc (info->classes,
|
||||
sizeof *info->classes * info->num_classes);
|
||||
|
||||
/* Attach the class. */
|
||||
info->classes[info->num_classes - 1] = (XIAnyClassInfo *) class;
|
||||
}
|
||||
|
||||
static void
|
||||
AddXIValuatorClassInfo (struct wl_client *client, struct wl_resource *resource,
|
||||
int32_t sourceid, int32_t number, const char *label,
|
||||
wl_fixed_t min, wl_fixed_t max, wl_fixed_t value,
|
||||
int32_t resolution, int32_t mode)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
XIValuatorClassInfo *class;
|
||||
|
||||
if (sourceid < 65536)
|
||||
{
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_DEVICE_ID,
|
||||
"invalid device ID specified");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Avoid interning empty strings. */
|
||||
|
||||
if (!strlen (label))
|
||||
{
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_LABEL,
|
||||
"the specified label is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
class = XLMalloc (sizeof *class);
|
||||
class->type = XIValuatorClass;
|
||||
class->sourceid = sourceid;
|
||||
class->number = number;
|
||||
class->label = InternAtom (label);
|
||||
class->min = wl_fixed_to_double (min);
|
||||
class->max = wl_fixed_to_double (max);
|
||||
class->value = wl_fixed_to_double (value);
|
||||
class->resolution = resolution;
|
||||
class->mode = mode;
|
||||
|
||||
/* Extend info->classes to hold more classes. */
|
||||
info->num_classes++;
|
||||
info->classes = XLRealloc (info->classes,
|
||||
sizeof *info->classes * info->num_classes);
|
||||
|
||||
/* Attach the class. */
|
||||
info->classes[info->num_classes - 1] = (XIAnyClassInfo *) class;
|
||||
}
|
||||
|
||||
static const struct test_XIDeviceInfo_interface XIDeviceInfo_impl =
|
||||
{
|
||||
.destroy = DestroyDeviceInfo,
|
||||
.set_device_id = SetDeviceId,
|
||||
.set_name = SetName,
|
||||
.set_use = SetUse,
|
||||
.set_attachment = SetAttachment,
|
||||
.set_enabled = SetEnabled,
|
||||
.add_XIScrollClassInfo = AddXIScrollClassInfo,
|
||||
.add_XIValuatorClassInfo = AddXIValuatorClassInfo,
|
||||
};
|
||||
|
||||
static void
|
||||
HandleXIDeviceInfoDestroy (struct wl_resource *resource)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
int i;
|
||||
|
||||
info = wl_resource_get_user_data (resource);
|
||||
|
||||
/* Free the name. */
|
||||
XLFree (info->name);
|
||||
|
||||
/* Free each of the classes. */
|
||||
for (i = 0; i < info->num_classes; ++i)
|
||||
XLFree (info->classes[i]);
|
||||
|
||||
/* Free the class array. */
|
||||
XLFree (info->classes);
|
||||
|
||||
/* Free the info itself. */
|
||||
XLFree (info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
DestroyDeviceController (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
AddDeviceInfo (struct wl_client *client, struct wl_resource *resource,
|
||||
struct wl_resource *device_info)
|
||||
{
|
||||
TestDeviceController *controller;
|
||||
TestXIDeviceInfo *info;
|
||||
Seat *seat;
|
||||
DeviceInfo *deviceinfo;
|
||||
int i;
|
||||
XIDeviceInfo test_info;
|
||||
|
||||
/* Add a virtual device to the device controller. */
|
||||
controller = wl_resource_get_user_data (resource);
|
||||
info = wl_resource_get_user_data (device_info);
|
||||
|
||||
/* First, ensure that the device info is completely specified. */
|
||||
|
||||
if ((info->state & StateComplete) != StateComplete)
|
||||
{
|
||||
wl_resource_post_error (resource,
|
||||
TEST_MANAGER_ERROR_INCOMPLETE_DEVICE_INFO,
|
||||
"the specified device information was not"
|
||||
" completely specified");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Next, check whether or not a device already exists. */
|
||||
seat = XLLookUpAssoc (seats, info->device_id);
|
||||
deviceinfo = XLLookUpAssoc (devices, info->device_id);
|
||||
|
||||
if ((seat && seat->flags & IsTestDeviceSpecified) || deviceinfo)
|
||||
{
|
||||
/* If a device already exists, see whether or not it was created
|
||||
by this test device controller. */
|
||||
|
||||
for (i = 0; i < controller->num_ids; ++i)
|
||||
{
|
||||
if (controller->device_ids[i] == info->device_id)
|
||||
/* It was created by this controller. Simply update the
|
||||
values. */
|
||||
goto continue_update;
|
||||
}
|
||||
|
||||
/* Otherwise, post an error. */
|
||||
wl_resource_post_error (resource,
|
||||
TEST_MANAGER_ERROR_DEVICE_EXISTS,
|
||||
"the device %d already exists, and was "
|
||||
"not created by this controller",
|
||||
info->device_id);
|
||||
return;
|
||||
}
|
||||
|
||||
continue_update:
|
||||
|
||||
/* Now, construct the XIDeviceInfo. */
|
||||
test_info.deviceid = info->device_id;
|
||||
test_info.name = info->name;
|
||||
test_info.use = info->use;
|
||||
test_info.attachment = info->attachment;
|
||||
test_info.enabled = info->enabled;
|
||||
test_info.num_classes = info->num_classes;
|
||||
test_info.classes = info->classes;
|
||||
|
||||
/* If the seat exists, repopulate its valuators with that specified
|
||||
in the device info. */
|
||||
|
||||
if (seat)
|
||||
{
|
||||
FreeValuators (seat);
|
||||
UpdateValuators (seat, &test_info);
|
||||
|
||||
/* Next, set a flag that means the seat has its information
|
||||
provided by device info. */
|
||||
seat->flags |= IsTestDeviceSpecified;
|
||||
}
|
||||
|
||||
/* Now, record the device info. */
|
||||
RecordDeviceInformation (&test_info);
|
||||
}
|
||||
|
||||
static void
|
||||
GetDeviceInfo (struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id)
|
||||
{
|
||||
TestXIDeviceInfo *info;
|
||||
|
||||
info = XLSafeMalloc (sizeof *info);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
wl_resource_post_no_memory (resource);
|
||||
return;
|
||||
}
|
||||
|
||||
memset (info, 0, sizeof *info);
|
||||
info->resource
|
||||
= wl_resource_create (client, &test_XIDeviceInfo_interface,
|
||||
wl_resource_get_version (resource), id);
|
||||
|
||||
if (!info->resource)
|
||||
{
|
||||
XLFree (info);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation (info->resource, &XIDeviceInfo_impl,
|
||||
info, HandleXIDeviceInfoDestroy);
|
||||
}
|
||||
|
||||
static const struct test_device_controller_interface device_controller_impl =
|
||||
{
|
||||
.destroy = DestroyDeviceController,
|
||||
.add_device_info = AddDeviceInfo,
|
||||
.get_device_info = GetDeviceInfo,
|
||||
};
|
||||
|
||||
static void
|
||||
HandleTestDeviceControllerDestroy (struct wl_resource *resource)
|
||||
{
|
||||
TestDeviceController *controller;
|
||||
int i;
|
||||
Seat *seat;
|
||||
|
||||
controller = wl_resource_get_user_data (resource);
|
||||
|
||||
/* Remove each device associated with the device controller. */
|
||||
for (i = 0; i < controller->num_ids; ++i)
|
||||
{
|
||||
NoticeDeviceDisabled (controller->device_ids[i]);
|
||||
|
||||
/* NoticeDeviceDisabled is special-cased to not free valuators
|
||||
for test seats. If there is a seat associated with this
|
||||
device ID, free the valuators on it as well. */
|
||||
seat = XLLookUpAssoc (seats, controller->device_ids[i]);
|
||||
FreeValuators (seat);
|
||||
|
||||
/* Clear the test device specified flag. */
|
||||
seat->flags &= ~IsTestDeviceSpecified;
|
||||
}
|
||||
|
||||
XLFree (controller);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
DestroySeatController (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
|
@ -664,9 +1070,41 @@ DispatchXIButtonRelease (struct wl_client *client, struct wl_resource *resource,
|
|||
DispatchTestEvent (controller, event, (XIEvent *) &test_event);
|
||||
}
|
||||
|
||||
static void
|
||||
GetDeviceController (struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id)
|
||||
{
|
||||
TestDeviceController *controller;
|
||||
|
||||
controller = XLSafeMalloc (sizeof *controller);
|
||||
|
||||
if (!controller)
|
||||
{
|
||||
wl_resource_post_no_memory (resource);
|
||||
return;
|
||||
}
|
||||
|
||||
memset (controller, 0, sizeof *controller);
|
||||
controller->resource
|
||||
= wl_resource_create (client, &test_device_controller_interface,
|
||||
wl_resource_get_version (resource), id);
|
||||
|
||||
if (!controller->resource)
|
||||
{
|
||||
XLFree (controller);
|
||||
wl_resource_post_no_memory (resource);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation (controller->resource,
|
||||
&device_controller_impl,
|
||||
controller,
|
||||
HandleTestDeviceControllerDestroy);
|
||||
}
|
||||
|
||||
static const struct test_seat_controller_interface seat_controller_impl =
|
||||
{
|
||||
.destroy = DestroyTestSeatController,
|
||||
.destroy = DestroySeatController,
|
||||
.bind_seat = BindSeat,
|
||||
.get_XIModifierState = GetXIModifierState,
|
||||
.get_XIButtonState = GetXIButtonState,
|
||||
|
@ -676,6 +1114,7 @@ static const struct test_seat_controller_interface seat_controller_impl =
|
|||
.dispatch_XI_Motion = DispatchXIMotion,
|
||||
.dispatch_XI_ButtonPress = DispatchXIButtonPress,
|
||||
.dispatch_XI_ButtonRelease = DispatchXIButtonRelease,
|
||||
.get_device_controller = GetDeviceController,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -787,4 +1226,8 @@ XLGetTestSeat (struct wl_client *client, struct wl_resource *resource,
|
|||
|
||||
wl_resource_set_implementation (controller->resource, &seat_controller_impl,
|
||||
controller, HandleControllerResourceDestroy);
|
||||
|
||||
/* Send the device ID to the client. */
|
||||
test_seat_controller_send_device_id (controller->resource,
|
||||
seat->master_pointer);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ enum test_expect_event_kind
|
|||
POINTER_MOTION_EVENT,
|
||||
POINTER_LEAVE_EVENT,
|
||||
POINTER_BUTTON_EVENT,
|
||||
POINTER_AXIS_VALUE120_EVENT,
|
||||
};
|
||||
|
||||
struct test_recorded_event
|
||||
|
@ -82,6 +83,18 @@ struct test_recorded_button_event
|
|||
uint32_t button, state;
|
||||
};
|
||||
|
||||
struct test_recorded_axis_value120_event
|
||||
{
|
||||
/* The event header. */
|
||||
struct test_recorded_event header;
|
||||
|
||||
/* The axis. */
|
||||
uint32_t axis;
|
||||
|
||||
/* The value120. */
|
||||
int32_t value120;
|
||||
};
|
||||
|
||||
struct test_subsurface
|
||||
{
|
||||
/* The subsurface itself. */
|
||||
|
@ -97,6 +110,7 @@ enum test_kind
|
|||
TEST_ENTRY_KIND,
|
||||
TEST_CLICK_KIND,
|
||||
TEST_GRAB_KIND,
|
||||
TEST_VALUATOR_KIND,
|
||||
};
|
||||
|
||||
static const char *test_names[] =
|
||||
|
@ -105,9 +119,10 @@ static const char *test_names[] =
|
|||
"test_entry",
|
||||
"test_click",
|
||||
"test_grab",
|
||||
"test_valuator",
|
||||
};
|
||||
|
||||
#define LAST_TEST TEST_GRAB_KIND
|
||||
#define LAST_TEST TEST_VALUATOR_KIND
|
||||
#define TEST_SOURCE_DEVICE 4500000
|
||||
|
||||
/* The display. */
|
||||
|
@ -148,6 +163,7 @@ static void expect_enter_event (struct wl_surface *, 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_axis_value120_event (uint32_t, int32_t);
|
||||
static void expect_no_events (void);
|
||||
|
||||
|
||||
|
@ -466,6 +482,159 @@ run_grab_test (struct test_XIButtonState *button_state,
|
|||
expect_enter_event (wayland_surface, 0.0, 0.0);
|
||||
}
|
||||
|
||||
static void
|
||||
run_valuator_test (void)
|
||||
{
|
||||
struct test_XIDeviceInfo *info;
|
||||
struct test_XIValuatorState *valuator_state;
|
||||
|
||||
/* First, create the device info. */
|
||||
info
|
||||
= test_device_controller_get_device_info (display->seat->device_controller);
|
||||
|
||||
/* Send the first 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 (-1.0),
|
||||
wl_fixed_from_double (-1.0),
|
||||
wl_fixed_from_double (-1.0),
|
||||
wl_fixed_from_double (-1.0),
|
||||
XINotifyNormal,
|
||||
False, True,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Set the device ID and add the valuators. */
|
||||
test_XIDeviceInfo_set_device_id (info, display->seat->device_id);
|
||||
test_XIDeviceInfo_set_use (info, XIMasterPointer);
|
||||
test_XIDeviceInfo_set_attachment (info, display->seat->controller);
|
||||
test_XIDeviceInfo_set_name (info, "Test virtual pointer");
|
||||
test_XIDeviceInfo_set_enabled (info, 1);
|
||||
test_XIDeviceInfo_add_XIScrollClassInfo (info,
|
||||
TEST_SOURCE_DEVICE,
|
||||
1,
|
||||
XIScrollTypeVertical,
|
||||
wl_fixed_from_double (1.0),
|
||||
XIScrollFlagPreferred);
|
||||
test_XIDeviceInfo_add_XIScrollClassInfo (info,
|
||||
TEST_SOURCE_DEVICE,
|
||||
2,
|
||||
XIScrollTypeHorizontal,
|
||||
wl_fixed_from_double (2.0),
|
||||
XIScrollFlagPreferred);
|
||||
test_XIDeviceInfo_add_XIValuatorClassInfo (info,
|
||||
TEST_SOURCE_DEVICE,
|
||||
1,
|
||||
"Rel Scroll Vertical",
|
||||
wl_fixed_from_double (0.0),
|
||||
wl_fixed_from_double (0.0),
|
||||
wl_fixed_from_double (0.0),
|
||||
1,
|
||||
XIModeRelative);
|
||||
test_XIDeviceInfo_add_XIValuatorClassInfo (info,
|
||||
TEST_SOURCE_DEVICE,
|
||||
2,
|
||||
"Rel Scroll Horizontal",
|
||||
wl_fixed_from_double (0.0),
|
||||
wl_fixed_from_double (0.0),
|
||||
wl_fixed_from_double (0.0),
|
||||
1,
|
||||
XIModeRelative);
|
||||
test_device_controller_add_device_info (display->seat->device_controller,
|
||||
info);
|
||||
test_XIDeviceInfo_destroy (info);
|
||||
|
||||
/* Dispatch the first entry event. */
|
||||
test_seat_controller_dispatch_XI_Enter (display->seat->controller,
|
||||
test_get_time (),
|
||||
TEST_SOURCE_DEVICE,
|
||||
XINotifyAncestor,
|
||||
test_get_root (),
|
||||
test_surface_window,
|
||||
None,
|
||||
wl_fixed_from_double (1.0),
|
||||
wl_fixed_from_double (1.0),
|
||||
wl_fixed_from_double (1.0),
|
||||
wl_fixed_from_double (1.0),
|
||||
XINotifyNormal,
|
||||
False, True, NULL, NULL,
|
||||
NULL);
|
||||
|
||||
/* Create the valuator state. */
|
||||
valuator_state
|
||||
= test_seat_controller_get_XIValuatorState (display->seat->controller);
|
||||
|
||||
if (!valuator_state)
|
||||
report_test_failure ("failed to create valuator state");
|
||||
|
||||
test_XIValuatorState_add_valuator (valuator_state, 1,
|
||||
wl_fixed_from_double (1.0));
|
||||
test_XIValuatorState_add_valuator (valuator_state, 2,
|
||||
wl_fixed_from_double (1.0));
|
||||
|
||||
/* Dispatch the first motion event. */
|
||||
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 (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
0,
|
||||
NULL,
|
||||
valuator_state,
|
||||
NULL, NULL);
|
||||
test_XIValuatorState_destroy (valuator_state);
|
||||
|
||||
/* Dispatch the second motion event. */
|
||||
valuator_state
|
||||
= test_seat_controller_get_XIValuatorState (display->seat->controller);
|
||||
|
||||
if (!valuator_state)
|
||||
report_test_failure ("failed to create valuator state");
|
||||
|
||||
test_XIValuatorState_add_valuator (valuator_state, 1,
|
||||
wl_fixed_from_double (1.1));
|
||||
test_XIValuatorState_add_valuator (valuator_state, 2,
|
||||
wl_fixed_from_double (2.6));
|
||||
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 (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
0,
|
||||
NULL,
|
||||
valuator_state,
|
||||
NULL, NULL);
|
||||
test_XIValuatorState_destroy (valuator_state);
|
||||
|
||||
/* Now, verify the events that arrive. */
|
||||
record_events ();
|
||||
expect_frame_event ();
|
||||
expect_axis_value120_event (WL_POINTER_AXIS_VERTICAL_SCROLL, 12);
|
||||
expect_axis_value120_event (WL_POINTER_AXIS_HORIZONTAL_SCROLL, 96);
|
||||
expect_frame_event ();
|
||||
expect_motion_event (2.0, 2.0);
|
||||
expect_frame_event ();
|
||||
expect_enter_event (wayland_surface, 1.0, 1.0);
|
||||
expect_frame_event ();
|
||||
expect_leave_event ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_single_step (enum test_kind kind)
|
||||
{
|
||||
|
@ -473,6 +642,8 @@ test_single_step (enum test_kind kind)
|
|||
struct test_XIButtonState *button_state;
|
||||
struct test_subsurface *child;
|
||||
|
||||
button_state = NULL;
|
||||
|
||||
again:
|
||||
test_log ("running test step: %s", test_names[kind]);
|
||||
|
||||
|
@ -613,7 +784,99 @@ test_single_step (enum test_kind kind)
|
|||
|
||||
/* Run the test. */
|
||||
run_grab_test (button_state, child);
|
||||
kind = TEST_VALUATOR_KIND;
|
||||
goto again;
|
||||
|
||||
case TEST_VALUATOR_KIND:
|
||||
/* Dispatch a leave event at -1, -1, and then attach the following
|
||||
scroll valuator information to the seat:
|
||||
|
||||
type
|
||||
ScrollClass
|
||||
number
|
||||
1
|
||||
scroll_type
|
||||
Vertical
|
||||
flags
|
||||
Preferred
|
||||
increment
|
||||
1.0
|
||||
|
||||
type
|
||||
ScrollClass
|
||||
number
|
||||
2
|
||||
scroll_type
|
||||
Horizontal
|
||||
flags
|
||||
Preferred
|
||||
increment
|
||||
2.0
|
||||
|
||||
type
|
||||
ValuatorClass
|
||||
sourceid
|
||||
TEST_SOURCE_DEVICE
|
||||
number
|
||||
1
|
||||
label
|
||||
Rel Scroll Vertical
|
||||
min
|
||||
0.0
|
||||
max
|
||||
0.0
|
||||
resolution
|
||||
1
|
||||
mode
|
||||
Relative
|
||||
value
|
||||
0.0
|
||||
|
||||
type
|
||||
ValuatorClass
|
||||
sourceid
|
||||
TEST_SOURCE_DEVICE
|
||||
number
|
||||
2
|
||||
label
|
||||
Rel Scroll Horizontal
|
||||
min
|
||||
0.0
|
||||
max
|
||||
0.0
|
||||
resolution
|
||||
1
|
||||
mode
|
||||
Relative
|
||||
value
|
||||
0.0
|
||||
|
||||
then, dispatch an entry event at 1, 1, followed by two motion
|
||||
events at 2, 2 with the following valuators:
|
||||
|
||||
1, 1.0, 2, 1.0
|
||||
1, 1.1, 2, 2.6
|
||||
|
||||
verify that the following events arrive in the specified order:
|
||||
|
||||
leave ()
|
||||
frame ()
|
||||
enter (SERIAL, PARENT, 1.0, 1.0)
|
||||
frame ()
|
||||
|
||||
motion (TIME, 2.0, 2.0) (this motion event should arrive because
|
||||
the entry event happened after
|
||||
the scroll valuator information was
|
||||
recorded. The first motion event to
|
||||
arrive after that should be used to obtain
|
||||
the current value of the valuator, and
|
||||
not for calculating scroll deltas.)
|
||||
frame ();
|
||||
axis_value120 (WL_POINTER_AXIS_HORIZONTAL_SCROLL, 96)
|
||||
axis_value120 (WL_POINTER_AXIS_VERTICAL_SCROLL, 12)
|
||||
frame (); */
|
||||
|
||||
run_valuator_test ();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -752,6 +1015,37 @@ expect_button_event (int button, int state)
|
|||
report_test_failure ("expected button event, but it was not received");
|
||||
}
|
||||
|
||||
static void
|
||||
expect_axis_value120_event (uint32_t axis, int32_t value120)
|
||||
{
|
||||
struct test_recorded_event *event;
|
||||
struct test_recorded_axis_value120_event *axis_value120_event;
|
||||
|
||||
event = record_tail;
|
||||
|
||||
if (!event)
|
||||
report_test_failure ("expected event not sent");
|
||||
|
||||
record_tail = event->last;
|
||||
|
||||
if (event->kind == POINTER_AXIS_VALUE120_EVENT)
|
||||
{
|
||||
axis_value120_event
|
||||
= (struct test_recorded_axis_value120_event *) event;
|
||||
|
||||
if (axis_value120_event->axis == axis
|
||||
&& axis_value120_event->value120 == value120)
|
||||
free (event);
|
||||
else
|
||||
report_test_failure ("expected axis_value120 event received "
|
||||
"with incorrect parameters (axis: %"PRIu32","
|
||||
" value120: %"PRIi32")", axis, value120);
|
||||
}
|
||||
else
|
||||
report_test_failure ("expected axis_value120 event, but it was not "
|
||||
"received");
|
||||
}
|
||||
|
||||
static void
|
||||
expect_no_events (void)
|
||||
{
|
||||
|
@ -1011,7 +1305,34 @@ static void
|
|||
handle_pointer_axis_value120 (void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t axis, int32_t value120)
|
||||
{
|
||||
/* TODO... */
|
||||
struct test_recorded_axis_value120_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_AXIS_VALUE120_EVENT;
|
||||
event->header.last = record_tail;
|
||||
record_tail = &event->header;
|
||||
|
||||
event->axis = axis;
|
||||
event->value120 = value120;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct wl_pointer_listener pointer_listener =
|
||||
|
|
|
@ -825,6 +825,26 @@ test_init (void)
|
|||
= getenv ("TEST_WRITE_REFERENCE") != NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handle_seat_controller_device_id (void *data,
|
||||
struct test_seat_controller *controller,
|
||||
uint32_t device_id)
|
||||
{
|
||||
struct test_display *display;
|
||||
|
||||
display = data;
|
||||
display->seat->device_id = device_id;
|
||||
}
|
||||
|
||||
static const struct test_seat_controller_listener seat_controller_listener =
|
||||
{
|
||||
handle_seat_controller_device_id,
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
test_init_seat (struct test_display *display)
|
||||
{
|
||||
|
@ -842,6 +862,22 @@ test_init_seat (struct test_display *display)
|
|||
if (!display->seat->controller)
|
||||
report_test_failure ("failed to obtain seat controller");
|
||||
|
||||
display->seat->device_controller
|
||||
= test_seat_controller_get_device_controller (display->seat->controller);
|
||||
|
||||
if (!display->seat->device_controller)
|
||||
report_test_failure ("failed to obtain device controller");
|
||||
|
||||
/* Fetch the device ID of the seat. */
|
||||
display->seat->device_id = 0;
|
||||
test_seat_controller_add_listener (display->seat->controller,
|
||||
&seat_controller_listener,
|
||||
display);
|
||||
wl_display_roundtrip (display->display);
|
||||
|
||||
if (!display->seat->device_id)
|
||||
report_test_failure ("failed to obtain device ID");
|
||||
|
||||
/* The protocol translator currently supports version 8 of wl_seat,
|
||||
so bind to that. */
|
||||
|
||||
|
|
|
@ -40,12 +40,18 @@ struct test_seat
|
|||
/* The test seat, if any. */
|
||||
struct test_seat_controller *controller;
|
||||
|
||||
/* The device manager, if any. */
|
||||
struct test_device_controller *device_controller;
|
||||
|
||||
/* The seat resource itself. */
|
||||
struct wl_seat *seat;
|
||||
|
||||
/* The wl_pointer resource. */
|
||||
struct wl_pointer *pointer;
|
||||
|
||||
/* The device ID of the seat. */
|
||||
uint32_t device_id;
|
||||
|
||||
/* The buttons currently held down. */
|
||||
unsigned char buttons;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue