Skip to content

Commit

Permalink
fix: prevent compositor blocking on linux
Browse files Browse the repository at this point in the history
  • Loading branch information
lodicolo committed Dec 28, 2024
1 parent 270961a commit 791c20b
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 14 deletions.
1 change: 1 addition & 0 deletions Intersect.Client.Core/Intersect.Client.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Lib.Harmony.Thin" Version="2.3.3" />
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" GeneratePathProperty="True" />
<PackageReference Include="MonoGame.Library.SDL" Version="2.26.5.5" GeneratePathProperty="True" />
<PackageReference Include="Steamworks.NET" Version="20.1.0" />
Expand Down
25 changes: 23 additions & 2 deletions Intersect.Client.Core/MonoGame/IntersectGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;
using System.Reflection;
using HarmonyLib;
using Intersect.Client.Framework.Database;
using Intersect.Client.Framework.Graphics;
using Intersect.Client.ThirdParty;
Expand All @@ -25,6 +26,7 @@
using MainMenu = Intersect.Client.Interface.Menu.MainMenu;
using Intersect.Logging;
using Intersect.Client.Interface.Shared;
using Intersect.Client.MonoGame.NativeInterop;

namespace Intersect.Client.MonoGame;

Expand Down Expand Up @@ -557,9 +559,28 @@ internal partial class MonoGameRunner : IPlatformRunner
/// <inheritdoc />
public void Start(IClientContext context, Action postStartupAction)
{
using (var game = new IntersectGame(context, postStartupAction))
var assemblyMonoGameFramework = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(assembly => assembly.FullName?.StartsWith("MonoGame.Framework") ?? false);
var typeInternalSdl = assemblyMonoGameFramework?.GetType("Sdl");
var methodSdlInit = typeInternalSdl?.GetMethod("Init");

var harmonyPatch = new Harmony(typeof(MonoGameRunner).Assembly.FullName ?? "Intersect.Client.Core");
harmonyPatch.Patch(methodSdlInit, postfix: SymbolExtensions.GetMethodInfo(() => SdlInitPost()));

using var game = new IntersectGame(context, postStartupAction);
game.Run();
}

private static void SdlInitPost()
{
if (PlatformHelper.CurrentPlatform != Platform.Linux)
{
return;
}

if (!Sdl2.SDL_SetHint(Sdl2.SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, false))
{
game.Run();
LegacyLogging.Logger?.Warn("Failed to set X11 Compositor hint");
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions Intersect.Client.Core/MonoGame/NativeInterop/Sdl2.Hints.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Runtime.InteropServices;
using System.Text;

namespace Intersect.Client.MonoGame.NativeInterop;

public partial class Sdl2
{
public const string SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR = "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR";

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate int SDL_SetHint_d(byte* name, byte* value);

private static SDL_SetHint_d SDL_SetHint_f = Loader.Functions.LoadFunction<SDL_SetHint_d>(nameof(SDL_SetHint));

public static unsafe bool SDL_SetHint(string name, string value)
{
fixed (byte* pValue = Encoding.UTF8.GetBytes(value))
{
fixed (byte* pName = Encoding.UTF8.GetBytes(name))
{
return SDL_SetHint_f(pName, pValue) != 0;
}
}
}

public static bool SDL_SetHint(string name, bool value) => SDL_SetHint(name, value ? "1" : "0");
}
4 changes: 2 additions & 2 deletions Intersect.Client.Core/MonoGame/NativeInterop/Sdl2.Video.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public partial class Sdl2

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private unsafe delegate int SDL_GetDisplayBounds_d(int displayIndex, SDL_Rect * rect);

private static SDL_GetDisplayBounds_d SDL_GetDisplayBounds_f =
Loader.Functions.LoadFunction<SDL_GetDisplayBounds_d>(nameof(SDL_GetDisplayBounds));

Expand All @@ -33,7 +33,7 @@ public static unsafe bool TryGetDisplayBounds(int displayIndex, out SDL_Rect bou
return SDL_GetDisplayBounds_f(displayIndex, boundsPointer) == 0;
}
}

public static SDL_Rect[] GetDisplayBounds()
{
var displayCount = SDL_GetNumVideoDisplays();
Expand Down
23 changes: 13 additions & 10 deletions Intersect.Client.Core/MonoGame/NativeInterop/Sdl2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static unsafe string SDL_GetError()
{
throw new PlatformNotSupportedException();
}

var textBytes = SDL_GetError_f();
var endTextBytes = textBytes;
while (*endTextBytes != default)
Expand All @@ -36,21 +36,23 @@ public static unsafe string SDL_GetError()
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private unsafe delegate void SDL_free_d(void* ptr);

private static SDL_free_d SDL_free = Loader.Functions.LoadFunction<SDL_free_d>(nameof(SDL_free));

private static SDL_free_d? SDL_free_f = Loader.Functions.LoadFunction<SDL_free_d>(nameof(SDL_free_f));

private static unsafe void SDL_free(void* ptr) => SDL_free_f!(ptr);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private unsafe delegate byte* SDL_GetClipboardText_d();

private static SDL_GetClipboardText_d SDL_GetClipboardText_f =
private static SDL_GetClipboardText_d? SDL_GetClipboardText_f =
Loader.Functions.LoadFunction<SDL_GetClipboardText_d>(nameof(SDL_GetClipboardText));

public static unsafe string SDL_GetClipboardText()
{
if (SDL_GetClipboardText_f == default || SDL_free == default)
if (SDL_GetClipboardText_f == default || SDL_free_f == default)
{
throw new PlatformNotSupportedException();
}

var textBytes = SDL_GetClipboardText_f();
var endTextBytes = textBytes;
while (*endTextBytes != default)
Expand All @@ -62,11 +64,11 @@ public static unsafe string SDL_GetClipboardText()
SDL_free(textBytes);
return text;
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private unsafe delegate int SDL_SetClipboardText_d(byte* text);

private static SDL_SetClipboardText_d SDL_SetClipboardText_f =
private static SDL_SetClipboardText_d? SDL_SetClipboardText_f =
Loader.Functions.LoadFunction<SDL_SetClipboardText_d>(nameof(SDL_SetClipboardText));

public static unsafe bool SDL_SetClipboardText(string text)
Expand All @@ -75,13 +77,14 @@ public static unsafe bool SDL_SetClipboardText(string text)
{
throw new PlatformNotSupportedException();
}

fixed (byte* textBytes = Encoding.UTF8.GetBytes(text))
{
return SDL_SetClipboardText_f(textBytes) == 0;
}
}

public static bool IsClipboardSupported => SDL_GetClipboardText_f != default &&
SDL_SetClipboardText_f != default && SDL_free != default;
SDL_SetClipboardText_f != default &&
SDL_free_f != default;
}

0 comments on commit 791c20b

Please sign in to comment.