<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Bindables;
using osu.Framework.Graphics.OpenGL;
using osu.Framework.Logging;
using osuTK.Graphics.ES30;

namespace osu.Framework.Platform.Windows
{
    internal class WindowsGLRenderer : GLRenderer, IWindowsRenderer
    {
        public IBindable<FullscreenCapability> FullscreenCapability => fullscreenCapability;
        private readonly Bindable<FullscreenCapability> fullscreenCapability = new Bindable<FullscreenCapability>();

        private readonly WindowsGameHost host;

        public WindowsGLRenderer(WindowsGameHost host)
        {
            this.host = host;
        }

        protected override void Initialise()
        {
            base.Initialise();

            WindowsWindow window = (WindowsWindow)host.Window;

            bool isIntel = GL.GetString(StringName.Vendor).Trim() == "Intel";

            if (isIntel)
            {
                // Exclusive fullscreen is always supported on Intel.
                fullscreenCapability.Value = Windows.FullscreenCapability.Capable;
            }
            else
            {
                // For all other vendors, support depends on the system setup - e.g. NVIDIA Optimus doesn't support exclusive fullscreen with OpenGL.
                window.IsActive.BindValueChanged(_ => detectFullscreenCapability(window));
                window.WindowStateChanged += _ => detectFullscreenCapability(window);
                detectFullscreenCapability(window);
            }
        }

        private CancellationTokenSource? fullscreenCapabilityDetectionCancellationSource;

        private void detectFullscreenCapability(IWindow window)
        {
            fullscreenCapabilityDetectionCancellationSource?.Cancel();
            fullscreenCapabilityDetectionCancellationSource?.Dispose();
            fullscreenCapabilityDetectionCancellationSource = null;

            if (window.WindowState != WindowState.Fullscreen || !window.IsActive.Value || fullscreenCapability.Value != Windows.FullscreenCapability.Unknown)
                return;

            var cancellationSource = fullscreenCapabilityDetectionCancellationSource = new CancellationTokenSource();

            // 50 attempts, 100ms apart = run the detection for a total of 5 seconds before yielding an incapable state.
            const int max_attempts = 50;
            const int time_per_attempt = 100;
            int attempts = 0;

            queueNextAttempt();

            void queueNextAttempt() => Task.Delay(time_per_attempt, cancellationSource.Token).ContinueWith(_ =>
            {
                if (cancellationSource.IsCancellationRequested || window.WindowState != WindowState.Fullscreen || !window.IsActive.Value)
                    return;

                attempts++;

                try
                {
                    SHQueryUserNotificationState(out var notificationState);

                    var capability = notificationState == QueryUserNotificationState.QUNS_RUNNING_D3D_FULL_SCREEN
                        ? Windows.FullscreenCapability.Capable
                        : Windows.FullscreenCapability.Incapable;

                    if (capability == Windows.FullscreenCapability.Incapable && attempts < max_attempts)
                    {
                        queueNextAttempt();
                        return;
                    }

                    fullscreenCapability.Value = capability;
                    Logger.Log($"Exclusive fullscreen capability: {fullscreenCapability.Value} ({notificationState})");
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Failed to detect fullscreen capabilities.");
                    fullscreenCapability.Value = Windows.FullscreenCapability.Capable;
                }
            }, cancellationSource.Token);
        }

        [DllImport("shell32.dll")]
        private static extern int SHQueryUserNotificationState(out QueryUserNotificationState state);

        private enum QueryUserNotificationState
        {
            QUNS_NOT_PRESENT = 1,
            QUNS_BUSY = 2,
            QUNS_RUNNING_D3D_FULL_SCREEN = 3,
            QUNS_PRESENTATION_MODE = 4,
            QUNS_ACCEPTS_NOTIFICATIONS = 5,
            QUNS_QUIET_TIME = 6
        }
    }
}<commit_msg>Fix potential exception due to disposed CTS<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Bindables;
using osu.Framework.Graphics.OpenGL;
using osu.Framework.Logging;
using osuTK.Graphics.ES30;

namespace osu.Framework.Platform.Windows
{
    internal class WindowsGLRenderer : GLRenderer, IWindowsRenderer
    {
        public IBindable<FullscreenCapability> FullscreenCapability => fullscreenCapability;
        private readonly Bindable<FullscreenCapability> fullscreenCapability = new Bindable<FullscreenCapability>();

        private readonly WindowsGameHost host;

        public WindowsGLRenderer(WindowsGameHost host)
        {
            this.host = host;
        }

        protected override void Initialise()
        {
            base.Initialise();

            WindowsWindow window = (WindowsWindow)host.Window;

            bool isIntel = GL.GetString(StringName.Vendor).Trim() == "Intel";

            if (isIntel)
            {
                // Exclusive fullscreen is always supported on Intel.
                fullscreenCapability.Value = Windows.FullscreenCapability.Capable;
            }
            else
            {
                // For all other vendors, support depends on the system setup - e.g. NVIDIA Optimus doesn't support exclusive fullscreen with OpenGL.
                window.IsActive.BindValueChanged(_ => detectFullscreenCapability(window));
                window.WindowStateChanged += _ => detectFullscreenCapability(window);
                detectFullscreenCapability(window);
            }
        }

        private CancellationTokenSource? fullscreenCapabilityDetectionCancellationSource;

        private void detectFullscreenCapability(IWindow window)
        {
            fullscreenCapabilityDetectionCancellationSource?.Cancel();
            fullscreenCapabilityDetectionCancellationSource?.Dispose();
            fullscreenCapabilityDetectionCancellationSource = null;

            if (window.WindowState != WindowState.Fullscreen || !window.IsActive.Value || fullscreenCapability.Value != Windows.FullscreenCapability.Unknown)
                return;

            var cancellationSource = fullscreenCapabilityDetectionCancellationSource = new CancellationTokenSource();
            var cancellationToken = cancellationSource.Token;

            // 50 attempts, 100ms apart = run the detection for a total of 5 seconds before yielding an incapable state.
            const int max_attempts = 50;
            const int time_per_attempt = 100;
            int attempts = 0;

            queueNextAttempt();

            void queueNextAttempt() => Task.Delay(time_per_attempt, cancellationToken).ContinueWith(_ =>
            {
                if (cancellationToken.IsCancellationRequested || window.WindowState != WindowState.Fullscreen || !window.IsActive.Value)
                    return;

                attempts++;

                try
                {
                    SHQueryUserNotificationState(out var notificationState);

                    var capability = notificationState == QueryUserNotificationState.QUNS_RUNNING_D3D_FULL_SCREEN
                        ? Windows.FullscreenCapability.Capable
                        : Windows.FullscreenCapability.Incapable;

                    if (capability == Windows.FullscreenCapability.Incapable && attempts < max_attempts)
                    {
                        queueNextAttempt();
                        return;
                    }

                    fullscreenCapability.Value = capability;
                    Logger.Log($"Exclusive fullscreen capability: {fullscreenCapability.Value} ({notificationState})");
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Failed to detect fullscreen capabilities.");
                    fullscreenCapability.Value = Windows.FullscreenCapability.Capable;
                }
            }, cancellationToken);
        }

        [DllImport("shell32.dll")]
        private static extern int SHQueryUserNotificationState(out QueryUserNotificationState state);

        private enum QueryUserNotificationState
        {
            QUNS_NOT_PRESENT = 1,
            QUNS_BUSY = 2,
            QUNS_RUNNING_D3D_FULL_SCREEN = 3,
            QUNS_PRESENTATION_MODE = 4,
            QUNS_ACCEPTS_NOTIFICATIONS = 5,
            QUNS_QUIET_TIME = 6
        }
    }
}
{'fraction_non_alphanumeric': 0.06950354609929078, 'fraction_numerical': 0.005237315875613748, 'mean_word_length': 2.1326042378673957, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5825670', 'n_tokens_mistral': 2308, 'n_tokens_neox': 2161, 'n_words': 483}