Skip to content

Commit bcec185

Browse files
committed
Check whether taking a screenshot from the window resulted in only black pixels.
In that case, throw an exception to inform the user that they should disable background mode.
1 parent 106536b commit bcec185

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

TTMouseclickSimulator/Core/Environment/AbstractWindowsEnvironment.cs

+18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Diagnostics.CodeAnalysis;
66
using System.Drawing;
77
using System.Drawing.Imaging;
8+
using System.Runtime.CompilerServices;
89
using System.Windows.Forms;
910

1011
namespace TTMouseclickSimulator.Core.Environment;
@@ -588,6 +589,7 @@ public ScreenshotColor GetPixel(Coordinates coords)
588589
return this.GetPixel(coords.X, coords.Y);
589590
}
590591

592+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
591593
public ScreenshotColor GetPixel(int x, int y)
592594
{
593595
// Only do these checks in Debug mode so we get optimal performance
@@ -623,6 +625,22 @@ public ScreenshotColor GetPixel(int x, int y)
623625
};
624626
}
625627

628+
public bool ContainsOnlyBlackPixels()
629+
{
630+
// Check whether the screenshot contains only black pixels, which means it
631+
// probably didn't work.
632+
int* scan0 = this.scan0;
633+
int count = this.bmp.Width * this.bmp.Height;
634+
635+
for (int i = 0; i < count; i++)
636+
{
637+
if ((scan0[i] & 0xFFFFFF) is not 0)
638+
return false;
639+
}
640+
641+
return true;
642+
}
643+
626644
public void Dispose()
627645
{
628646
this.Dispose(true);

TTMouseclickSimulator/Core/Environment/StandardInteractionProvider.cs

+27-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ internal class StandardInteractionProvider : IInteractionProvider, IDisposable
2828
// Window-relative (when using backgroundMode) or absolute mouse coordinates
2929
private Coordinates? lastSetMouseCoordinates;
3030

31+
// Specifies we could already take the first sceenshot successfully.
32+
private bool firstWindowScreenshotSuccessful;
33+
34+
private bool canRetryOnException = true;
35+
3136
public StandardInteractionProvider(
3237
Simulator simulator,
3338
AbstractWindowsEnvironment environmentInterface,
@@ -61,6 +66,7 @@ public void Dispose()
6166
public async Task InitializeAsync()
6267
{
6368
this.lastSetMouseCoordinates = null;
69+
this.firstWindowScreenshotSuccessful = false;
6470

6571
while (true)
6672
{
@@ -278,11 +284,30 @@ public IScreenshotContent GetCurrentWindowScreenshot()
278284
// won't allow us to access the pixel data). If this will generally no longer work
279285
// with a future verison of the game, we may need to revert using the screen copy
280286
// also for background mode, but set the game window as topmost window.
287+
bool fromScreen = !this.backgroundMode;
281288
this.environmentInterface.CreateWindowScreenshot(
282289
this.windowHandle,
283290
ref this.currentScreenshot,
284291
failIfNotInForeground: !this.backgroundMode,
285-
fromScreen: !this.backgroundMode);
292+
fromScreen: fromScreen);
293+
294+
if (!fromScreen && !this.firstWindowScreenshotSuccessful)
295+
{
296+
// If we took the first screenshot from the window rather than the screen,
297+
// check whether it only contains black pixels. In that case, throw an
298+
// exception to inform the user that background mode won't work.
299+
if (this.currentScreenshot.ContainsOnlyBlackPixels())
300+
{
301+
// Don't allow to retry in this case since it would lead to the same
302+
// exception.
303+
this.canRetryOnException = false;
304+
throw new InvalidOperationException(
305+
"Couldn't capture screenshot from window. " +
306+
"Please disable background mode and try again.");
307+
}
308+
309+
this.firstWindowScreenshotSuccessful = true;
310+
}
286311

287312
return this.currentScreenshot;
288313
}
@@ -493,7 +518,7 @@ await Task.Delay(
493518

494519
private async ValueTask CheckRetryForExceptionAsync(Exception ex, bool reinitialize)
495520
{
496-
if (this.simulator.AsyncRetryHandler is null)
521+
if (!this.canRetryOnException || this.simulator.AsyncRetryHandler is null)
497522
{
498523
// Simply rethrow the exception.
499524
ExceptionDispatchInfo.Throw(ex);

0 commit comments

Comments
 (0)