VirtualTouchpad.md

February 25, 2026 · View on GitHub

VirtualTouchpad Documentation

The VirtualTouchpad interface provides functionality to simulate touch inputs, multitouch gestures, and button actions using a virtual device. The VirtualTouchpadFactory is used to configure and create instances of VirtualTouchpad.


VirtualTouchpad

The VirtualTouchpad interface defines the core functionalities of a virtual touchpad.

It supports 3 protocols (see multi-touch-protocol) :

  • the legacy single touch protocol by using the Touch
  • the multitouch Protocol A by activating it with WithLegacyMultitouch using the MultiTouch function.
  • the multitouch Protocol B using the MultiTouch function.

Coordinates X and Y are between -1 and 1 (normalized)
Pressure is between 0 and 1

Methods

ActionDescription
RegisterRegisters the virtual touchpad device with the system.
UnregisterUnregisters the virtual touchpad device, releasing system resources.
TouchSimulates a single touch event at the specified coordinates with pressure.
MultiTouchSimulates multitouch events using multiple touch slots. Returns the updated touch slots after the gesture.
The slot IDs are automatically managed, so reuse the previous result on the next call.
PressButtonSimulates pressing a touchpad button.
ReleaseButtonSimulates releasing a touchpad button.
ClickSimulates a single click of the specified button.
DoubleClickSimulates a double click of the specified button.
ClickLeftConvenience method to simulate a single left click.
ClickRightConvenience method to simulate a single right click.
DoubleClickLeftConvenience method to simulate a double left click.
DoubleClickRightConvenience method to simulate a double right click.
SendSends a raw input event of the specified type, code, and value.

Touchpad Handling

Touchpads use absolute axes to represent the position of touch points. Each touch point has two main axes: X (horizontal) and Y (vertical). Additionally, touchpads often provide a pressure value that indicates how firmly the user is pressing on the surface. The ranges for these values can vary depending on the hardware.

To simplify handling these variations, this package normalizes touch coordinates and pressure values to standard ranges. This ensures consistent behavior across different touchpad devices.

Normalization

Normalized values follow these conventions:

  • X and Y Axes:

    • -1.0: Fully left or fully up.
    • 0.0: Centered.
    • 1.0: Fully right or fully down.
  • Pressure:

    • 0.0: No pressure (touch lifted or minimal contact).
    • 1.0: Maximum pressure (fully pressed).

This standardization allows you to work with consistent touch input, regardless of the underlying device.

Custom Configuration

The behavior of a virtual touchpad depends directly on its configuration. You can define and configure axes (ABS_X, ABS_Y or ABS_PRESSURE) with custom ranges, resolutions, and properties to suit your specific requirements.

For more detail, look the code of NewGenericTouchpad.


VirtualTouchpadFactory

The VirtualTouchpadFactory is used to configure and create instances of VirtualTouchpad. It supports method chaining for easy setup.

Methods

ActionDescription
WithDeviceAttaches an existing VirtualDevice to the touchpad.
WithClickDelaySets the delay between press and release for a single click.
WithDoubleClickDelaySets the delay between two clicks for a double click.
WithAxesConfigures the absolute axes supported by the touchpad (e.g., X, Y coordinates).
WithButtonsConfigures the buttons supported by the touchpad.
WithPropertiesConfigures the properties of the touchpad (e.g., multitouch support).
WithLegacyMultitouchEnables legacy multitouch protocol (Protocol A).
CreateCreates an instance of VirtualTouchpad with the specified configuration.

Example Usage

Here’s how to configure and use a VirtualTouchpad:

package main

import (
  "fmt"
  virtual_device "github.com/jbdemonte/virtual-device"
  "github.com/jbdemonte/virtual-device/linux"
  "github.com/jbdemonte/virtual-device/touchpad"
  "log"
  "time"
)

func main() {
    tp := touchpad.NewVirtualTouchpadFactory().
            WithDevice(
              virtual_device.NewVirtualDevice().
                WithBusType(linux.BUS_USB).
                WithVendor(0x02).
                WithProduct(0x07).
                WithVersion(0x01).
                WithName("Synaptics TouchPad"),
            ).
            WithAxes([]virtual_device.AbsAxis{
              {Axis: linux.ABS_X, Min: 1472, Value: 1472, Max: 5472, Resolution: 40},
              {Axis: linux.ABS_Y, Min: 1408, Value: 1408, Max: 4448, Resolution: 40},
              {Axis: linux.ABS_PRESSURE, Min: 0, Value: 0, Max: 255, IsUnidirectional: true},
              {Axis: linux.ABS_MT_SLOT, Min: 0, Value: 0, Max: 4},
              {Axis: linux.ABS_MT_POSITION_X, Min: 1472, Value: 0, Max: 5472, Resolution: 40},
              {Axis: linux.ABS_MT_POSITION_Y, Min: 1408, Value: 1408, Max: 4448, Resolution: 40},
              {Axis: linux.ABS_MT_TRACKING_ID, Min: 0, Value: 0, Max: 65535},
            }).
            WithButtons([]linux.Button{
              linux.BTN_LEFT,
              linux.BTN_RIGHT,
              linux.BTN_TOOL_FINGER,
              linux.BTN_TOUCH,
              linux.BTN_TOOL_DOUBLETAP,
              linux.BTN_TOOL_TRIPLETAP,
            }).
            WithProperties([]linux.InputProp{
              linux.INPUT_PROP_POINTER, linux.INPUT_PROP_BUTTONPAD,
            }).
      Create() 
    
    err := tp.Register()
    if err != nil {
      log.Fatalf("Failed to register virtual touchpad: %v", err)
    }
    defer tp.Unregister()
    
    
    fmt.Println("2 fingers")
    slots := tp.MultiTouch([]touchpad.TouchSlot{
      {X: 0, Y: 0, Pressure: 0.5},
      {X: 0.2, Y: 0.2, Pressure: 0.5},
    })
    
    time.Sleep(2_000 * time.Millisecond)
    fmt.Println("move #0")
    slots[0].X = 0.8
    slots[0].Pressure = 1
    slots = tp.MultiTouch(slots)
    
    time.Sleep(2_000 * time.Millisecond)
    fmt.Println("add one finger")
    slots = append(slots, touchpad.TouchSlot{
        X: -0.3, Y: -0.4, Pressure: 0.2,
    })
    slots = tp.MultiTouch(slots)
    
    time.Sleep(2_000 * time.Millisecond)
    fmt.Println("release all fingers")
    slots[0].Pressure = 0
    slots[1].Pressure = 0
    slots[2].Pressure = 0
    slots = tp.MultiTouch(slots)

}

This documentation outlines the essential steps for configuring, registering, and using a VirtualTouchpad to simulate touch inputs and gestures.