libei-dotnet 1.6.0

dotnet add package libei-dotnet --version 1.6.0
                    
NuGet\Install-Package libei-dotnet -Version 1.6.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="libei-dotnet" Version="1.6.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="libei-dotnet" Version="1.6.0" />
                    
Directory.Packages.props
<PackageReference Include="libei-dotnet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add libei-dotnet --version 1.6.0
                    
#r "nuget: libei-dotnet, 1.6.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package libei-dotnet@1.6.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=libei-dotnet&version=1.6.0
                    
Install as a Cake Addin
#tool nuget:?package=libei-dotnet&version=1.6.0
                    
Install as a Cake Tool

libei-dotnet

.NET bindings for libei, the emulated-input library used by Wayland compositors and the XDG RemoteDesktop portal.

Install

dotnet add package libei-dotnet

Emulating input

Connect through the portal, bind the capabilities you want, and send events. The EIS implementation acts on nothing until a Frame closes the logical hardware event.

using Libei;
using Libei.Portal;

// The portal asks the user to approve this and hands back a socket to the
// compositor. Keep it alive for as long as the connection is used.
using var portal = new OeffisContext();
var eisFd = portal.Connect(OeffisDevice.Pointer | OeffisDevice.Keyboard);

using var context = EiContext.CreateSender("my app");
context.ConnectToFd(eisFd);

EiDevice? device = null;

while (true)
{
    context.Wait();       // poll(2) on context.Fd; use your own event loop instead
    context.Dispatch();

    foreach (var @event in context.Events())
    {
        using (@event)
        {
            switch (@event.Type)
            {
                case EiEventType.SeatAdded:
                    using (var seat = @event.GetSeat()!)
                    {
                        seat.BindCapabilities(EiDeviceCapability.Pointer);
                    }

                    break;

                case EiEventType.DeviceAdded:
                    device = @event.GetDevice();
                    break;

                case EiEventType.DeviceResumed:
                    device!.StartEmulating(sequence: 1);
                    device.PointerMotion(10, 5);
                    device.Frame(context.Now);   // nothing happens without this
                    device.StopEmulating();
                    break;
            }
        }
    }
}

Receiving input

A receiver context is the mirror image: the compositor sends input to you, and the same events arrive as typed EiEvent subclasses.

using var context = EiContext.CreateReceiver("my app");
context.ConnectToSocket();   // $LIBEI_SOCKET, else eis-0 in $XDG_RUNTIME_DIR

// ... dispatch as above ...
foreach (var @event in context.Events())
{
    using (@event)
    {
        if (@event is EiPointerMotionEvent motion)
        {
            Console.WriteLine($"dx={motion.Dx} dy={motion.Dy}");
        }
    }
}

Implementing the EIS side

Libei.Server is enough to write a compositor's EIS implementation in .NET.

using Libei;
using Libei.Server;

using var server = new EisContext();
server.ListenOnSocket();      // or UseFdBackend() + AddClient() to hand out sockets

server.Dispatch();
foreach (var @event in server.Events())
{
    using (@event)
    {
        switch (@event.Type)
        {
            case EisEventType.ClientConnect:
                using (var client = @event.GetClient()!)
                {
                    client.Connect();                  // or Disconnect() to reject
                    var seat = client.CreateSeat("seat0");
                    seat.ConfigureCapabilities(EiDeviceCapability.Pointer);
                    seat.Add();
                }

                break;

            case EisEventType.SeatBind:
                var bind = (EisSeatBindEvent)@event;
                using (var seat = @event.GetSeat()!)
                {
                    var device = seat.CreateDevice();
                    device.ConfigureName("virtual pointer");
                    device.ConfigureCapabilities(bind.Capabilities);
                    device.Add();
                    device.Resume();                   // devices start paused
                }

                break;

            case EisEventType.PointerMotion:
                var motion = (EisPointerMotionEvent)@event;
                // ... inject motion.Dx / motion.Dy into your compositor ...
                break;
        }
    }
}

Samples

dotnet run --project samples/Libei.NET.LoopbackSample        # client + server, one process
dotnet run --project samples/Libei.NET.DebugEventsSample -- --portal
dotnet run --project samples/Libei.NET.DemoClientSample -- --socket /run/user/1000/eis-0
dotnet run --project samples/Libei.NET.PortalSample -- --devices pointer --connect

Building

git submodule update --init
dotnet build
dotnet test
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.6.0 92 9/3/2026