mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-01 14:10:53 +00:00
Flash console window on input request on Windows (#3158)
* Flash console window on input request * Use BELL character instead of Beep, fix flash struct, add support for minimizing and flashing with Windows Terminal * cross-platform minimization, use alert char instead of number, fix struct again * remove console window * formatting * use MainWindowHandle if it's set (fix flashing winterm if ASF is launched in conhost) * fix build * remove support for flashing winterm
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// _ _ _ ____ _ _____
|
||||
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// |
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
// |
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// |
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// |
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -26,6 +28,12 @@ using System.Runtime.Versioning;
|
||||
namespace ArchiSteamFarm.Core;
|
||||
|
||||
internal static partial class NativeMethods {
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
[SupportedOSPlatform("Windows")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[LibraryImport("user32.dll")]
|
||||
internal static partial void FlashWindowEx(ref FlashWindowInfo pwfi);
|
||||
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
[SupportedOSPlatform("Windows")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
@@ -77,6 +85,16 @@ internal static partial class NativeMethods {
|
||||
Awake = SystemRequired | AwayModeRequired | Continuous
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Windows")]
|
||||
[Flags]
|
||||
internal enum EFlashFlags : uint {
|
||||
Stop = 0,
|
||||
Caption = 1,
|
||||
Tray = 2,
|
||||
All = Caption | Tray,
|
||||
Timer = 4
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Windows")]
|
||||
internal enum EShowWindow : uint {
|
||||
Minimize = 6
|
||||
@@ -86,4 +104,13 @@ internal static partial class NativeMethods {
|
||||
internal enum EStandardHandle {
|
||||
Input = -10
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct FlashWindowInfo {
|
||||
public uint StructSize;
|
||||
public nint WindowHandle;
|
||||
public EFlashFlags Flags;
|
||||
public uint Count;
|
||||
public uint TimeoutBetweenFlashes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// _ _ _ ____ _ _____
|
||||
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// |
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
// |
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// |
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// |
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -84,11 +86,11 @@ internal static class OS {
|
||||
private static Mutex? SingleInstance;
|
||||
|
||||
internal static void CoreInit(bool minimized, bool systemRequired) {
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
if (minimized) {
|
||||
WindowsMinimizeConsoleWindow();
|
||||
}
|
||||
if (minimized) {
|
||||
MinimizeConsoleWindow();
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
if (systemRequired) {
|
||||
WindowsKeepSystemActive();
|
||||
}
|
||||
@@ -227,6 +229,67 @@ internal static class OS {
|
||||
return false;
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Windows")]
|
||||
internal static void WindowsStartFlashingConsoleWindow() {
|
||||
if (!OperatingSystem.IsWindows()) {
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
using Process currentProcess = Process.GetCurrentProcess();
|
||||
nint handle = currentProcess.MainWindowHandle;
|
||||
|
||||
if (handle == nint.Zero) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeMethods.FlashWindowInfo flashInfo = new() {
|
||||
StructSize = (uint) Marshal.SizeOf<NativeMethods.FlashWindowInfo>(),
|
||||
Flags = NativeMethods.EFlashFlags.All | NativeMethods.EFlashFlags.Timer,
|
||||
WindowHandle = handle,
|
||||
Count = uint.MaxValue
|
||||
};
|
||||
|
||||
NativeMethods.FlashWindowEx(ref flashInfo);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Windows")]
|
||||
internal static void WindowsStopFlashingConsoleWindow() {
|
||||
if (!OperatingSystem.IsWindows()) {
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
using Process currentProcess = Process.GetCurrentProcess();
|
||||
nint handle = currentProcess.MainWindowHandle;
|
||||
|
||||
if (handle == nint.Zero) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeMethods.FlashWindowInfo flashInfo = new() {
|
||||
StructSize = (uint) Marshal.SizeOf<NativeMethods.FlashWindowInfo>(),
|
||||
Flags = NativeMethods.EFlashFlags.Stop,
|
||||
WindowHandle = handle
|
||||
};
|
||||
|
||||
NativeMethods.FlashWindowEx(ref flashInfo);
|
||||
}
|
||||
|
||||
private static void MinimizeConsoleWindow() {
|
||||
// Will work if the terminal supports XTWINOPS sequences, reference: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
Console.Write('\x1b' + @"[2;2;2t\r");
|
||||
|
||||
// Fallback if we're using conhost on Windows
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
using Process process = Process.GetCurrentProcess();
|
||||
|
||||
nint windowHandle = process.MainWindowHandle;
|
||||
|
||||
if (windowHandle != nint.Zero) {
|
||||
NativeMethods.ShowWindow(windowHandle, NativeMethods.EShowWindow.Minimize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Windows")]
|
||||
private static void WindowsDisableQuickEditMode() {
|
||||
if (!OperatingSystem.IsWindows()) {
|
||||
@@ -264,15 +327,4 @@ internal static class OS {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, result));
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Windows")]
|
||||
private static void WindowsMinimizeConsoleWindow() {
|
||||
if (!OperatingSystem.IsWindows()) {
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
using Process process = Process.GetCurrentProcess();
|
||||
|
||||
NativeMethods.ShowWindow(process.MainWindowHandle, NativeMethods.EShowWindow.Minimize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// _ _ _ ____ _ _____
|
||||
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// |
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
// |
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// |
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// |
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -280,7 +282,7 @@ internal static class Logging {
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Beep();
|
||||
Console.Write('\a');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,9 +294,17 @@ internal static class Logging {
|
||||
|
||||
Utilities.InBackground(() => BeepUntilCanceled(token));
|
||||
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
OS.WindowsStartFlashingConsoleWindow();
|
||||
}
|
||||
|
||||
return Console.ReadLine();
|
||||
} finally {
|
||||
cts.Cancel();
|
||||
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
OS.WindowsStopFlashingConsoleWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,6 +316,10 @@ internal static class Logging {
|
||||
|
||||
Utilities.InBackground(() => BeepUntilCanceled(token));
|
||||
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
OS.WindowsStartFlashingConsoleWindow();
|
||||
}
|
||||
|
||||
StringBuilder result = new();
|
||||
|
||||
while (true) {
|
||||
@@ -341,6 +355,10 @@ internal static class Logging {
|
||||
}
|
||||
} finally {
|
||||
cts.Cancel();
|
||||
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
OS.WindowsStopFlashingConsoleWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user