<?xml version="1.0" encoding="UTF-8"?>
<protocol name="test">
  <copyright>
    Copyright (C) 2022 various contributors.

    This file is part of 12to11.

    12to11 is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    12to11 is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with 12to11.  If not, see https://www.gnu.org/licenses/.
  </copyright>

  <interface name="test_manager" version="1">
    <description summary="test interface">
      This protocol is used by the 12to11 protocol translator to
      support various tests.  The test_manager global allows creating
      a surface whose bounds and contents can be inspected, and
      connecting to the X server used by the compositor.

      Upon binding to the test_manager, a display_string event is sent
      containing the name of the X display.
    </description>

    <enum name="error">
      <entry name="role_present" value="1"
	     summary="given wl_surface has/had another role"/>
      <entry name="scale_lock_exists" value="2"
	     summary="another client has already locked the scale"/>
      <entry name="invalid_scale" value="3"
	     summary="the specified scale is invalid"/>
      <entry name="invalid_button" value="4"
	     summary="the specified button is invalid"/>
      <entry name="value_exists" value="5"
	     summary="the specified valuator is already included"/>
      <entry name="bad_seat_version" value="6"
	     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"/>
      <entry name="invalid_user_time" value="12"
	     summary="the specified user time lies in the past"/>
    </enum>

    <request name="get_test_surface">
      <description summary="obtain test surface role">
	Get a test_surface object for a particular surface.  If a role
	was already attached to this surface, or a role of a different
	type was previously attached, post a role_present error.

	Create the window immediately after get_test_surface is
	called; the window is mapped once a commit request with a
	non-nil buffer is made.  The window is created as an
	override-redirect child of the root window, at 0, 0.

	Once the window associated with the test_surface object is
	mapped, send a mapped event.
      </description>
      <arg name="id" type="new_id" interface="test_surface"/>
      <arg name="surface" type="object" interface="wl_surface"/>
    </request>

    <request name="get_scale_lock">
      <description summary="obtain scale lock">
	Create a new test_scale_lock object.  As long as this object
	exists, set the global output scale to the scale specified in
	this request (or in a subsequent test_scale_lock.set_scale
	request.)

	If a test_scale_lock object already exists, generate a
	scale_lock_exists error.

	If the scale is invalid (by being less than 0), post an
	invalid_scale error.
      </description>
      <arg name="id" type="new_id" interface="test_scale_lock"/>
      <arg name="global_scale" type="uint"/>
    </request>

    <request name="get_test_seat">
      <description summary="obtain test seat">
	Create a new seat controller object and its associated seat.
	The seat will not correspond to any real input device, but
	will allow artificial events to be constructed and processed.

	A test_seat_controller.bind_seat request can be used to bind
	to the given seat.
      </description>
      <arg name="id" type="new_id" interface="test_seat_controller"/>
    </request>

    <request name="get_serial">
      <description summary="obtain serial">
	Send a serial event with the next serial of the display.
      </description>
    </request>

    <event name="display_string">
      <description summary="X server name">
	The display_string event sends the name of the X display to
	clients.  It is sent immediately after binding to the
	test_manager object.
      </description>
      <arg name="name" type="string"/>
    </event>

    <event name="serial">
      <description summary="display serial">
	The serial event is sent in reply to the get_serial request.
	It provides the next serial that will be used by the display.
      </description>
      <arg name="serial" type="uint"/>
    </event>
  </interface>

  <interface name="test_surface" version="1">
    <description summary="test surface">
      This role provides a test surface.  Various buffers and
      subsurfaces can be attached, and the resulting display contents
      validated.

      When a buffer is commited to a test surface, the frame callback
      is run after any window configuration or resize has completed.
    </description>

    <request name="destroy" type="destructor">
      <description summary="destroy role">
	Destroy the test_surface role.  Subsequently, get_test_surface
	can be called again with its surface.
      </description>
    </request>

    <event name="mapped">
      <description summary="role initialized">
	The map event is sent once the window is mapped and its
	contents can be retrieved.  The two arguments are the XID of
	the window and the name of the display it is on.

	If the surface is mapped, then unmapped (by having a nil
	buffer attached) and then mapped again, without waiting for
	the first mapped event, the delivery of subsequent mapped
	events becomes undefined.
      </description>
      <arg name="xid" type="uint"/>
      <arg name="display_string" type="string"/>
    </event>
  </interface>

  <interface name="test_scale_lock" version="1">
    <description summary="test scale lock">
      A scale lock resource represents the "lock" a client holds on
      the global output scale.  While it still exists, the scale for
      every output will be whatever was specified when the lock was
      created or by the last set_scale request.
    </description>

    <request name="destroy" type="destructor">
      <description summary="destroy scale lock">
	Destroy the specified scale lock, restore the actual scale of
	each output, and let clients call get_scale_lock again.
      </description>
    </request>

    <request name="set_scale">
      <description summary="set the global output scale">
	Set the scale of each output to the specified scale, and
	resize all surfaces accordingly.  If the scale is invalid,
	post an invalid_scale error.
      </description>
      <arg name="scale" type="uint"/>
    </request>
  </interface>

  <interface name="test_XIButtonState" version="1">
    <description summary="XInput 2 button state">
      The button state associated with an event.
    </description>

    <request name="destroy" type="destructor">
      <description summary="destroy this resource">
	Destroy the given resource.
      </description>
    </request>

    <request name="add_button">
      <description summary="add button">
	Add the button with the given number to the button state.  If
	button is 0 or more than 8, raise an invalid_button error.
      </description>
      <arg name="button" type="uint"/>
    </request>

    <request name="remove_button">
      <description summary="remove button">
	Remove the button with the given number from the button state.
	If button is 0 or more than 8, raise an invalid_button error.
	If the button was not previously added to the button state, do
	nothing.
      </description>
      <arg name="button" type="uint"/>
    </request>
  </interface>

  <interface name="test_XIModifierState" version="1">
    <description summary="XInput 2 modifier state">
      The modifier state associated with an event.
    </description>

    <request name="destroy" type="destructor">
      <description summary="destroy this resource">
	Destroy the given resource.
      </description>
    </request>

    <request name="set_values">
      <description summary="set modifiers">
	Set the modifiers in this modifier state.
      </description>

      <arg name="base" type="int"/>
      <arg name="latched" type="int"/>
      <arg name="locked" type="int"/>
      <arg name="effective" type="int"/>
    </request>
  </interface>

  <interface name="test_XIValuatorState" version="1">
    <description summary="XInput 2 valuator state">
      The valuator state associated with an event.
    </description>

    <request name="destroy" type="destructor">
      <description summary="destroy this resource">
	Destroy the given resource.
      </description>
    </request>

    <request name="add_valuator">
      <description summary="add a valuator">
	Add a valuator with the given value to the specified valuator
	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.
      </description>

      <arg name="valuator" type="uint"/>
      <arg name="value" type="fixed"/>
    </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.
    </description>

    <request name="destroy" type="destructor">
      <description summary="destroy test seat controller">
	Destroy the test seat controller resource.
      </description>
    </request>

    <request name="bind_seat">
      <description summary="bind to the seat">
	Create a wl_seat resource for this seat controller's
	associated seat, with the specified version.  If the version
	is unsupported, raise a bad_seat_version error.
      </description>
      <arg name="version" type="uint"/>
      <arg name="id" type="new_id" interface="wl_seat"/>
    </request>

    <request name="get_XIModifierState">
      <description summary="obtain a test_XIModifierState">
	Create a test_XIModifierState resource with all fields set to
	0.
      </description>
      <arg name="id" type="new_id" interface="test_XIModifierState"/>
    </request>

    <request name="get_XIButtonState">
      <description summary="obtain a test_XIButtonState">
	Create a test_XIButtonState resource containing no buttons.
      </description>
      <arg name="id" type="new_id" interface="test_XIButtonState"/>
    </request>

    <request name="get_XIValuatorState">
      <description summary="obtain a test_XIValuatorState">
	Create a test_XIValuatorState resource containing no
	valuators.
      </description>
      <arg name="id" type="new_id" interface="test_XIValuatorState"/>
    </request>

    <request name="dispatch_XI_Enter">
      <description summary="dispatch entry event">
	Dispatch an XI_Enter event to the seat.  If buttons (or any
	following field) is null, use a value comprised of 0s instead.
      </description>

      <arg name="time" type="uint"/>
      <arg name="sourceid" type="int"/>
      <arg name="detail" type="int"/>
      <arg name="root" type="uint"/>
      <arg name="event" type="uint"/>
      <arg name="child" type="uint"/>
      <arg name="root_x" type="fixed"/>
      <arg name="root_y" type="fixed"/>
      <arg name="event_x" type="fixed"/>
      <arg name="event_y" type="fixed"/>
      <arg name="mode" type="int"/>
      <arg name="focus" type="int"/>
      <arg name="same_screen" type="int"/>
      <arg name="buttons" type="object" interface="test_XIButtonState"
	   allow-null="true"/>
      <arg name="mods" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
      <arg name="group" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
    </request>

    <request name="dispatch_XI_Leave">
      <description summary="dispatch leave event">
	Dispatch an XI_Leave event to the seat.  If buttons (or any
	following field) is null, use a value comprised of 0s instead.
      </description>

      <arg name="time" type="uint"/>
      <arg name="sourceid" type="int"/>
      <arg name="detail" type="int"/>
      <arg name="root" type="uint"/>
      <arg name="event" type="uint"/>
      <arg name="child" type="uint"/>
      <arg name="root_x" type="fixed"/>
      <arg name="root_y" type="fixed"/>
      <arg name="event_x" type="fixed"/>
      <arg name="event_y" type="fixed"/>
      <arg name="mode" type="int"/>
      <arg name="focus" type="int"/>
      <arg name="same_screen" type="int"/>
      <arg name="buttons" type="object" interface="test_XIButtonState"
	   allow-null="true"/>
      <arg name="mods" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
      <arg name="group" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
    </request>

    <request name="dispatch_XI_Motion">
      <description summary="dispatch motion event">
	Dispatch an XI_Motion device event to the seat.
      </description>

      <arg name="time" type="uint"/>
      <arg name="sourceid" type="int"/>
      <arg name="detail" type="int"/>
      <arg name="root" type="uint"/>
      <arg name="event" type="uint"/>
      <arg name="child" type="uint"/>
      <arg name="root_x" type="fixed"/>
      <arg name="root_y" type="fixed"/>
      <arg name="event_x" type="fixed"/>
      <arg name="event_y" type="fixed"/>
      <arg name="flags" type="int"/>
      <arg name="buttons" type="object" interface="test_XIButtonState"
	   allow-null="true"/>
      <arg name="valuators" type="object" interface="test_XIValuatorState"
	   allow-null="true"/>
      <arg name="mods" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
      <arg name="group" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
    </request>

    <request name="dispatch_XI_ButtonPress">
      <description summary="dispatch button press event">
	Dispatch an XI_ButtonPress device event to the seat.
      </description>

      <arg name="time" type="uint"/>
      <arg name="sourceid" type="int"/>
      <arg name="detail" type="int"/>
      <arg name="root" type="uint"/>
      <arg name="event" type="uint"/>
      <arg name="child" type="uint"/>
      <arg name="root_x" type="fixed"/>
      <arg name="root_y" type="fixed"/>
      <arg name="event_x" type="fixed"/>
      <arg name="event_y" type="fixed"/>
      <arg name="flags" type="int"/>
      <arg name="buttons" type="object" interface="test_XIButtonState"
	   allow-null="true"/>
      <arg name="valuators" type="object" interface="test_XIValuatorState"
	   allow-null="true"/>
      <arg name="mods" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
      <arg name="group" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
    </request>

    <request name="dispatch_XI_ButtonRelease">
      <description summary="dispatch button release event">
	Dispatch an XI_ButtonRelease device event to the seat.
      </description>

      <arg name="time" type="uint"/>
      <arg name="sourceid" type="int"/>
      <arg name="detail" type="int"/>
      <arg name="root" type="uint"/>
      <arg name="event" type="uint"/>
      <arg name="child" type="uint"/>
      <arg name="root_x" type="fixed"/>
      <arg name="root_y" type="fixed"/>
      <arg name="event_x" type="fixed"/>
      <arg name="event_y" type="fixed"/>
      <arg name="flags" type="int"/>
      <arg name="buttons" type="object" interface="test_XIButtonState"
	   allow-null="true"/>
      <arg name="valuators" type="object" interface="test_XIValuatorState"
	   allow-null="true"/>
      <arg name="mods" type="object" interface="test_XIModifierState"
	   allow-null="true"/>
      <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>

    <request name="set_last_user_time">
      <description summary="set seat user time">
	Set the user time of the specified seat to the specified time.
	If the last user time is greater than the specified time,
	raise an invalid_user_time error.

	The month describes the number of times the millisecond
	counter has wrapped around, and milliseconds specifies the X
	server time.  (This representation is also internally used in
	the X sample server.)
      </description>
      <arg name="months" type="uint"/>
      <arg name="milliseconds" type="uint"/>
    </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>
