Skip to content

Commit

Permalink
Fixed memory issues caused by the Diablo IV window focus check.
Browse files Browse the repository at this point in the history
  • Loading branch information
josdemmers committed Aug 13, 2024
1 parent 0cbea87 commit a95f57a
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 57 deletions.
85 changes: 42 additions & 43 deletions D4Companion.Services/ScreenCaptureHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public class ScreenCaptureHandler : IScreenCaptureHandler
private ScreenCapture _screenCapture = new ScreenCapture();
private int _offsetTop = 0;
private int _offsetLeft = 0;
private IntPtr _windowHandle = IntPtr.Zero;

// Start of Constructors region

Expand Down Expand Up @@ -147,6 +146,10 @@ await Task.Run(() =>

private void UpdateScreen()
{
// Note: Keep windowHandle local. On some systems making this a private class variable somehow locks the variable and prevents any garbage collection from happening.
// Memory usage jumps to 10GB+ after a few minutes.
IntPtr windowHandle = IntPtr.Zero;

bool windowFound = false;
Process[] processes = new Process[0];
Process[] processesGeForceNOW = new Process[0];
Expand All @@ -157,7 +160,7 @@ private void UpdateScreen()
processes = Process.GetProcessesByName("firefox");
foreach (Process p in processes)
{
_windowHandle = p.MainWindowHandle;
windowHandle = p.MainWindowHandle;
if (p.MainWindowTitle.StartsWith("Screenshot"))
{
windowFound = true;
Expand All @@ -169,70 +172,66 @@ private void UpdateScreen()
{
IntPtr windowHandleActive = PInvoke.User32.GetForegroundWindow();

// Only update window handle when there has been a change in active window.
if (_windowHandle == IntPtr.Zero || _windowHandle != windowHandleActive)
// Release mode - using game client
processes = Process.GetProcessesByName("Diablo IV");
foreach (Process p in processes)
{
// Release mode - using game client
processes = Process.GetProcessesByName("Diablo IV");
foreach (Process p in processes)
{
_windowHandle = p.MainWindowHandle;
if (_windowHandle == windowHandleActive)
{
windowFound = true;
break;
}
windowHandle = p.MainWindowHandle;
if (windowHandle == windowHandleActive)
{
windowFound = true;
break;
}
}

if (!windowFound)
if (!windowFound)
{
// Release mode - using GeForceNOW
processesGeForceNOW = Process.GetProcessesByName("GeForceNOW");
foreach (Process p in processesGeForceNOW)
{
// Release mode - using GeForceNOW
processesGeForceNOW = Process.GetProcessesByName("GeForceNOW");
foreach (Process p in processesGeForceNOW)
windowHandle = p.MainWindowHandle;
if (windowHandle == windowHandleActive && p.MainWindowTitle.Contains("Diablo"))
{
_windowHandle = p.MainWindowHandle;
if (_windowHandle == windowHandleActive && p.MainWindowTitle.Contains("Diablo"))
{
windowFound = true;
break;
}
windowFound = true;
break;
}
}
}

// Skip screencapture process when there is no active Diablo window.
if (windowHandleActive == IntPtr.Zero || windowHandleActive != _windowHandle)
{
// Reset offset used for mousecoordinates.
_offsetTop = 0;
_offsetLeft = 0;
// Skip screencapture process when there is no active Diablo window.
if (windowHandleActive == IntPtr.Zero || windowHandleActive != windowHandle)
{
// Reset offset used for mousecoordinates.
_offsetTop = 0;
_offsetLeft = 0;

// Reset screencapture. Empty screencapture will clear tooltip.
_currentScreen = null;
_eventAggregator.GetEvent<ScreenCaptureReadyEvent>().Publish(new ScreenCaptureReadyEventParams
{
CurrentScreen = _currentScreen
});
_delayUpdateScreen = _settingsManager.Settings.ScreenCaptureDelay;
return;
}
// Reset screencapture. Empty screencapture will clear tooltip.
_currentScreen = null;
_eventAggregator.GetEvent<ScreenCaptureReadyEvent>().Publish(new ScreenCaptureReadyEventParams
{
CurrentScreen = _currentScreen
});
_delayUpdateScreen = ScreenCaptureConstants.DelayErrorShort;
return;
}
}

if (_windowHandle.ToInt64() > 0)
if (windowHandle.ToInt64() > 0)
{
_eventAggregator.GetEvent<WindowHandleUpdatedEvent>().Publish(new WindowHandleUpdatedEventParams { WindowHandle = _windowHandle });
_eventAggregator.GetEvent<WindowHandleUpdatedEvent>().Publish(new WindowHandleUpdatedEventParams { WindowHandle = windowHandle });

// Update window position
PInvoke.RECT region;
PInvoke.User32.GetWindowRect(_windowHandle, out region);
PInvoke.User32.GetWindowRect(windowHandle, out region);
_offsetTop = region.top;
_offsetLeft = region.left;

if (IsEnabled)
{
if (!IsScreencaptureLocked)
{
_currentScreen = _screenCapture.GetScreenCapture(_windowHandle) ?? _currentScreen;
_currentScreen = _screenCapture.GetScreenCapture(windowHandle) ?? _currentScreen;
//_currentScreen = new Bitmap("debug-path-to-image");
}

Expand Down
26 changes: 14 additions & 12 deletions D4Companion.Services/ScreenProcessHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,20 @@ private void HandleScreenCaptureReadyEvent(ScreenCaptureReadyEventParams screenC
if (!IsEnabled) return;
if (_processTask != null && (_processTask.Status.Equals(TaskStatus.Running) || _processTask.Status.Equals(TaskStatus.WaitingForActivation))) return;

// Note: Do not move this inside ProcessScreen task. It delays the garbage collection.
// Publish empty tooltip to clear overlay when currentScreen is empty.
if (screenCaptureReadyEventParams.CurrentScreen == null)
{
_currentTooltip = new ItemTooltipDescriptor();
_eventAggregator.GetEvent<TooltipDataReadyEvent>().Publish(new TooltipDataReadyEventParams
{
Tooltip = _currentTooltip
});

return;
}


_processTask?.Dispose();
_processTask = Task.Run(() => ProcessScreen(screenCaptureReadyEventParams.CurrentScreen));
}
Expand Down Expand Up @@ -240,18 +254,6 @@ private void ProcessScreen(Bitmap? currentScreen)
{
//_logger.LogDebug($"{MethodBase.GetCurrentMethod()?.Name}");

// Publish empty tooltip to clear overlay when currentScreen is empty.
if (currentScreen == null)
{
_currentTooltip = new ItemTooltipDescriptor();
_eventAggregator.GetEvent<TooltipDataReadyEvent>().Publish(new TooltipDataReadyEventParams
{
Tooltip = _currentTooltip
});

return;
}

try
{
var watch = System.Diagnostics.Stopwatch.StartNew();
Expand Down
4 changes: 2 additions & 2 deletions D4Companion/common.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<FileVersion>3.8.5.0</FileVersion>
<Version>3.8.5.0</Version>
<FileVersion>3.8.6.0</FileVersion>
<Version>3.8.6.0</Version>
<Copyright>Copyright © 2024</Copyright>
<TargetFramework>net6.0-windows</TargetFramework>
</PropertyGroup>
Expand Down

0 comments on commit a95f57a

Please sign in to comment.