Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Building LittleBigMouse

LittleBigMouse is a mixed .NET and native Windows project. The main UI is an
Avalonia .NET application, and the mouse hook is a native C++ executable.

## Prerequisites

- Windows 10 or Windows 11, x64
- Git
- Visual Studio 2022, or Visual Studio Build Tools 2022
- .NET 8 SDK, or a newer .NET SDK that can build `net8.0` projects
- Visual Studio workloads/components:
- `.NET desktop development`
- `Desktop development with C++`
- MSVC v143 C++ build tools
- Windows 10 or Windows 11 SDK

## Clone

Clone the repository with submodules:

```powershell
git clone --recurse-submodules https://github.com/thomcuddihy/LittleBigMouse.git
cd LittleBigMouse
```

If the repository was cloned without submodules, initialize them before
building:

```powershell
git submodule update --init --recursive
```

## Build With Visual Studio

1. Open `LittleBigMouse.sln` in Visual Studio 2022.
2. Select the `Release` configuration and `x64` platform.
3. Restore NuGet packages when Visual Studio prompts, or run `Restore NuGet Packages`.
4. Build `LittleBigMouse.Hook`.
5. Build `LittleBigMouse.Ui.Avalonia`.

The primary development output is:

```text
LittleBigMouse.Ui\LittleBigMouse.Ui.Avalonia\bin\x64\Release\net8.0\LittleBigMouse.Ui.Avalonia.exe
```

The native hook output is:

```text
LittleBigMouse.Hook\bin\x64\Release\LittleBigMouse.Hook.exe
```

When running from the repository build folders, the UI locates the hook from the
native project output path. If the UI starts but the hook does not, make sure
`LittleBigMouse.Hook.exe` was built for the same configuration and platform.

## Build From The Command Line

Use a **Developer PowerShell for VS 2022** or **x64 Native Tools Command Prompt
for VS 2022** so that MSBuild can find the Visual C++ toolchain and Windows SDK.

Restore the .NET dependencies:

```powershell
dotnet restore LittleBigMouse.Ui\LittleBigMouse.Ui.Avalonia\LittleBigMouse.Ui.Avalonia.csproj
```

Build the native hook:

```powershell
msbuild LittleBigMouse.Hook\LittleBigMouse.Hook.vcxproj /m /p:Configuration=Release /p:Platform=x64
```

Build the Avalonia UI:

```powershell
dotnet build LittleBigMouse.Ui\LittleBigMouse.Ui.Avalonia\LittleBigMouse.Ui.Avalonia.csproj -c Release -p:Platform=x64 --no-restore
```

Run the app from:

```powershell
.\LittleBigMouse.Ui\LittleBigMouse.Ui.Avalonia\bin\x64\Release\net8.0\LittleBigMouse.Ui.Avalonia.exe
```

## Full Solution Builds

Visual Studio can build the full solution when all optional project requirements
are installed. For command-line builds, the two-step build above is the
recommended path for producing the runnable application because it avoids mixing
the native C++ project and SDK-style .NET projects through a single MSBuild
invocation.

If your command-line environment can resolve both Visual C++ and .NET SDK
targets, a full solution build can be attempted with:

```powershell
msbuild LittleBigMouse.sln /restore /m /p:Configuration=Release /p:Platform=x64
```

## Troubleshooting

- `Microsoft.Cpp.Default.props` is missing: install the Visual Studio C++
workload and run the build from a Visual Studio developer shell.
- `The SDK 'Microsoft.NET.Sdk' specified could not be found`: install the .NET 8
SDK and confirm `dotnet --info` works in the current shell.
- Output DLLs cannot be copied because they are in use: close
`LittleBigMouse.Ui.Avalonia.exe` and `LittleBigMouse.Hook.exe`, then rebuild.
- The UI opens but the hook does not start: build `LittleBigMouse.Hook` for
`Release|x64` and confirm the hook executable exists in
`LittleBigMouse.Hook\bin\x64\Release`.
- NuGet vulnerability warnings may appear during restore/build. These warnings
do not necessarily block compilation, but should be reviewed before shipping a
release.
2 changes: 1 addition & 1 deletion HLab.Avalonia
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Platforms>x64;x86;AnyCpu</Platforms>
<OutputType>Library</OutputType>
<Configurations>Debug;Release;ReleaseDebug</Configurations>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ public static ZonesLayout ComputeZones(this IMonitorsLayout layout)
}
}

zones.Init();

zones.MaxTravelDistance = layout.Options.MaxTravelDistance;

zones.AdjustPointer = layout.Options.AdjustPointer;
Expand All @@ -60,7 +58,9 @@ public static ZonesLayout ComputeZones(this IMonitorsLayout layout)
zones.LoopX = layout.Options.LoopX;
zones.LoopY = layout.Options.LoopY;

zones.Init();

return zones;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x64;x86</Platforms>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions LittleBigMouse.Hook/Engine/Zone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ bool Zone::Contains(const geo::Point<double>& mm) const
geo::Point<long> Zone::InsidePixelsBounds(const geo::Point<long> px) const
{
auto x = px.X();
auto y = px.X();
auto y = px.Y();

if (x < _pixelsBounds.Left()) x = _pixelsBounds.Left();
else if (x > _pixelsBounds.Right() - 1) x = _pixelsBounds.Right() - 1;
Expand Down Expand Up @@ -155,7 +155,7 @@ std::vector<geo::Rect<long>> Reachable(const geo::Rect<long>& source, const geo:

if(top >= bottom)
{
auto start = geo::Rect<long>(left, source.Top(), right, source.Height());
auto start = geo::Rect<long>(left, source.Top(), right - left, source.Height());
auto dest = geo::Rect<long>(left, target.Top(), right - left, target.Height());
return {start,dest};
}
Expand Down
2 changes: 1 addition & 1 deletion LittleBigMouse.Hook/Engine/ZoneLink.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ZoneLink
long TargetToPixel;

double BorderResistance;
long BorderResistancePixel;
long BorderResistancePixel = 0;

//long SourceLengthPixel;
//long TargetLengthPixel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Platforms>x64;x86;AnyCpu</Platforms>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<LangVersion>preview</LangVersion>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Platforms>AnyCPU;x64;x86</Platforms>
<LangVersion>preview</LangVersion>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<Platforms>x64;x86;AnyCpu</Platforms>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>x64;x86;AnyCpu</Platforms>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PackageIcon>lbm.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/mgth/LittleBigMouse</RepositoryUrl>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
<ApplicationManifest>app.manifest</ApplicationManifest>
<StartupObject>LittleBigMouse.Ui.Avalonia.Program</StartupObject>
<Title>Little Big Mouse</Title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public LittleBigMouseClientService(ILayoutOptions options)
OnStateChanged(LittleBigMouseEvent.Connected);
};

LaunchDaemon();
_client.Listen();
}

Expand Down Expand Up @@ -96,7 +97,16 @@ public Task StartAsync(ZonesLayout zonesLayout, CancellationToken token = defaul
void CreateExcludedFile()
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var file = Path.Combine(path,"Mgth","LittleBigMouse","Excluded.txt");
var directory = Path.Combine(path,"Mgth","LittleBigMouse");
Directory.CreateDirectory(directory);

var file = Path.Combine(directory,"Excluded.txt");
if (Directory.Exists(file))
{
Debug.WriteLine($"Excluded path is a directory, skipping file setup : {file}");
return;
}

if(File.Exists(file))
{
// Riot games -> Riot Games (was misspelled in 5.0.4.0) TODO : remove in a version or two
Expand Down Expand Up @@ -128,32 +138,51 @@ public void LaunchDaemon()
}

var path = Assembly.GetEntryAssembly()?.Location;
if (path is null) return;
if (path is null)
{
Debug.WriteLine("Unable to resolve entry assembly path for daemon launch");
return;
}

if (path.Contains(@"\bin\"))
{
// .\LittleBigMouse.Ui.Avalonia\bin\x64\Debug\net8.0\LittleBigMouse.Ui.Avalonia.dll
// .\x64\Debug\LittleBigMouse.Hook.exe
// .\LittleBigMouse.Hook\bin\x64\Debug\LittleBigMouse.Hook.exe

path = path.Replace(@"\LittleBigMouse.Ui\LittleBigMouse.Ui.Avalonia\", @"\LittleBigMouse.Hook\");
path = path.Replace(@"\net8.0\", @"\");
}

path = path.Replace(@"\LittleBigMouse.Ui.Avalonia.dll", @"\LittleBigMouse.Hook.exe");
var directory = Path.GetDirectoryName(path);
if (directory is null)
{
Debug.WriteLine($"Hook directory is null for path : {path}");
return;
}

path = Path.Combine(directory, "LittleBigMouse.Hook.exe");

if (!File.Exists(path))
{
Debug.WriteLine($"Not found : {path}");
return;
}

CreateExcludedFile();
try
{
CreateExcludedFile();
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to create excluded file : {ex}");
}

try
{
var startInfo = new ProcessStartInfo
{
FileName = path,
WorkingDirectory = directory,

//RedirectStandardOutput = true,
//RedirectStandardError = true,
Expand All @@ -175,9 +204,9 @@ public void LaunchDaemon()

Debug.WriteLine($"Started : {process.ProcessName} {process.Id}");
}
catch (ExecutionEngineException ex)
catch (Exception ex)
{

Debug.WriteLine($"Failed to start daemon : {path} : {ex}");
}
}

Expand Down Expand Up @@ -230,4 +259,4 @@ async Task SendMessagesAsync(IEnumerable<CommandMessage> messages, CancellationT

[GeneratedRegex("<Payload>(.*)</Payload>")]
private static partial Regex PayloadRegex();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<Platforms>x64;x86;AnyCpu</Platforms>
<LangVersion>preview</LangVersion>
<Version>5.2.4.0</Version>
<Version>5.2.6.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down