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" />
<PackageReference Include="libei-dotnet" />
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
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#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
#tool nuget:?package=libei-dotnet&version=1.6.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
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 | Versions 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 |