<commit_before>/*
Copyright 2016 <NAME> - FlatspotSoftware

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.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "SteamTargetRenderer.h"



SteamTargetRenderer::SteamTargetRenderer()
{
	getSteamOverlay();

	QSettings settings(".\\TargetConfig.ini", QSettings::IniFormat);
	settings.beginGroup("BaseConf");
	const QStringList childKeys = settings.childKeys();
	for (auto &childkey : childKeys)
	{
		if (childkey == "bDrawDebugEdges")
		{
			bDrawDebugEdges = settings.value(childkey).toBool();
		} else if (childkey == "bEnableOverlay") {
			bDrawOverlay = settings.value(childkey).toBool();
		} else if (childkey == "bEnableControllers") {
			bEnableControllers = settings.value(childkey).toBool();
		}else if (childkey == "bHookSteam") {
			bHookSteam = settings.value(childkey).toBool();
		}
	}
	settings.endGroup();

#ifndef NDEBUG
	bDrawDebugEdges = true;
#endif // NDEBUG
	sfCshape = sf::CircleShape(100.f);
	sfCshape.setFillColor(sf::Color(128, 128, 128, 128));
	sfCshape.setOrigin(sf::Vector2f(100, 100));
	sf::VideoMode mode = sf::VideoMode::getDesktopMode();
	sfWindow.create(sf::VideoMode(mode.width-16, mode.height-32), "GloSC_OverlayWindow"); //Window is too large ; always 16 and 32 pixels?  - sf::Style::None breaks transparency!
	sfWindow.setVerticalSyncEnabled(bVsync);
	sfWindow.setFramerateLimit(iRefreshRate);
	sfWindow.setPosition(sf::Vector2i(0, 0));
	makeSfWindowTransparent(sfWindow);

	sfWindow.setActive(false);
	consoleHwnd = GetConsoleWindow(); //We need a console for a dirty hack to make sure we stay in game bindings - Also useful for debugging

	if (bEnableControllers)
		controllerThread.run();

	QTimer::singleShot(2000, this, &SteamTargetRenderer::launchApp); // lets steam do its thing

}

SteamTargetRenderer::~SteamTargetRenderer()
{	
	bRunLoop = false;
	renderThread.join();
	if (controllerThread.isRunning())
		controllerThread.stop();
}

void SteamTargetRenderer::run()
{
	renderThread = std::thread(&SteamTargetRenderer::RunSfWindowLoop, this);
}

void SteamTargetRenderer::RunSfWindowLoop()
{
	if (!bRunLoop)
		return;
	sfWindow.setActive(true);

	sf::Clock reCheckControllerTimer;
	bool focusSwitchNeeded = true;
	if (!bDrawOverlay)
	{
		ShowWindow(consoleHwnd, SW_HIDE);
	}

	if (bDrawOverlay)
	{
		SetWindowPos(sfWindow.getSystemHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
	} else {
		ShowWindow(consoleHwnd, SW_HIDE);
	}
	

	while (sfWindow.isOpen() && bRunLoop)
	{

		sf::Event event;
		while (sfWindow.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				sfWindow.close();
		}

		sfWindow.clear(sf::Color::Transparent);

		if (bDrawDebugEdges)
			drawDebugEdges();

		sfWindow.display();

		//This ensures that we stay in game binding, even if focused application changes! (Why does this work? Well, i dunno... ask Valve...)
		//Only works with a console window
		//Causes trouble as soon as there is more than the consoleWindow and the overlayWindow
		//This is trying to avoid hooking Steam.exe
		//----
		//alternatively, we can just hook steam and make our lives so much easier
		//we inject and hook here to spare IPC and let the dll grab the steam appID of the launched process when the config switches (config switches w/ focus)
		if (focusSwitchNeeded)
		{

			if (bHookSteam)
				hookBindings(); //cleanup - unhooking / unloading of dll is managed by the GloSC gamelauncher rather than here

			focusSwitchNeeded = false;
			SetFocus(consoleHwnd);
			sf::Clock clock;
			while (!SetForegroundWindow(consoleHwnd) && clock.getElapsedTime().asMilliseconds() < 1000) //try to forcefully set foreground window
			{
				Sleep(1);
			}
		}

		//Dirty hack to make the steamoverlay work properly and still keep Apps Controllerconfig when closing overlay.
		//even if hooking steam, this ensures the overlay stays working
		if (overlayPtr != NULL)
		{
			char overlayOpen = *(char*)overlayPtr;
			if (overlayOpen)
			{
				if (!bNeedFocusSwitch)
				{
					bNeedFocusSwitch = true;

					hwForeGroundWindow = GetForegroundWindow();

					std::cout << "Saving current ForegorundWindow HWND: " << hwForeGroundWindow << std::endl;
					std::cout << "Activating OverlayWindow" << std::endl;

					SetWindowLong(sfWindow.getSystemHandle(), GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TOOLWINDOW); //make overlay window clickable

					//Actually activate the overlaywindow
					SetFocus(sfWindow.getSystemHandle());

					//Move the mouse cursor inside the overlaywindow
					//this is neccessary because steam doesn't want to switch to big picture bindings if mouse isn't inside
					SetCursorPos(16, 16);

					//by activating the consolewindow **and bringing it to the foreground** we can trick steam so the controller stays in game bindings
					SetFocus(consoleHwnd);
					sf::Clock clock;
					while (!SetForegroundWindow(consoleHwnd) && clock.getElapsedTime().asMilliseconds() < 1000) //try to forcefully set foreground window
					{
						Sleep(1);
					}
				}
			} else {
				if (bNeedFocusSwitch)
				{
					std::cout << "Deactivating OverlayWindow" << std::endl;

					//make overlaywindow clickthrough - WS_EX_TRANSPARENT - again
					SetWindowLong(sfWindow.getSystemHandle(), GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW);

					std::cout << "Switching to previously focused window" << std::endl;<commit_msg>SteamTarget: Move mousecursor inside the overlay after console has got focus again<commit_after>/*
Copyright 2016 <NAME> - FlatspotSoftware

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.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "SteamTargetRenderer.h"



SteamTargetRenderer::SteamTargetRenderer()
{
	getSteamOverlay();

	QSettings settings(".\\TargetConfig.ini", QSettings::IniFormat);
	settings.beginGroup("BaseConf");
	const QStringList childKeys = settings.childKeys();
	for (auto &childkey : childKeys)
	{
		if (childkey == "bDrawDebugEdges")
		{
			bDrawDebugEdges = settings.value(childkey).toBool();
		} else if (childkey == "bEnableOverlay") {
			bDrawOverlay = settings.value(childkey).toBool();
		} else if (childkey == "bEnableControllers") {
			bEnableControllers = settings.value(childkey).toBool();
		}else if (childkey == "bHookSteam") {
			bHookSteam = settings.value(childkey).toBool();
		}
	}
	settings.endGroup();

#ifndef NDEBUG
	bDrawDebugEdges = true;
#endif // NDEBUG
	sfCshape = sf::CircleShape(100.f);
	sfCshape.setFillColor(sf::Color(128, 128, 128, 128));
	sfCshape.setOrigin(sf::Vector2f(100, 100));
	sf::VideoMode mode = sf::VideoMode::getDesktopMode();
	sfWindow.create(sf::VideoMode(mode.width-16, mode.height-32), "GloSC_OverlayWindow"); //Window is too large ; always 16 and 32 pixels?  - sf::Style::None breaks transparency!
	sfWindow.setVerticalSyncEnabled(bVsync);
	sfWindow.setFramerateLimit(iRefreshRate);
	sfWindow.setPosition(sf::Vector2i(0, 0));
	makeSfWindowTransparent(sfWindow);

	sfWindow.setActive(false);
	consoleHwnd = GetConsoleWindow(); //We need a console for a dirty hack to make sure we stay in game bindings - Also useful for debugging

	if (bEnableControllers)
		controllerThread.run();

	QTimer::singleShot(2000, this, &SteamTargetRenderer::launchApp); // lets steam do its thing

}

SteamTargetRenderer::~SteamTargetRenderer()
{	
	bRunLoop = false;
	renderThread.join();
	if (controllerThread.isRunning())
		controllerThread.stop();
}

void SteamTargetRenderer::run()
{
	renderThread = std::thread(&SteamTargetRenderer::RunSfWindowLoop, this);
}

void SteamTargetRenderer::RunSfWindowLoop()
{
	if (!bRunLoop)
		return;
	sfWindow.setActive(true);

	sf::Clock reCheckControllerTimer;
	bool focusSwitchNeeded = true;
	if (!bDrawOverlay)
	{
		ShowWindow(consoleHwnd, SW_HIDE);
	}

	if (bDrawOverlay)
	{
		SetWindowPos(sfWindow.getSystemHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
	} else {
		ShowWindow(consoleHwnd, SW_HIDE);
	}
	

	while (sfWindow.isOpen() && bRunLoop)
	{

		sf::Event event;
		while (sfWindow.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				sfWindow.close();
		}

		sfWindow.clear(sf::Color::Transparent);

		if (bDrawDebugEdges)
			drawDebugEdges();

		sfWindow.display();

		//This ensures that we stay in game binding, even if focused application changes! (Why does this work? Well, i dunno... ask Valve...)
		//Only works with a console window
		//Causes trouble as soon as there is more than the consoleWindow and the overlayWindow
		//This is trying to avoid hooking Steam.exe
		//----
		//alternatively, we can just hook steam and make our lives so much easier
		//we inject and hook here to spare IPC and let the dll grab the steam appID of the launched process when the config switches (config switches w/ focus)
		if (focusSwitchNeeded)
		{

			if (bHookSteam)
				hookBindings(); //cleanup - unhooking / unloading of dll is managed by the GloSC gamelauncher rather than here

			focusSwitchNeeded = false;
			SetFocus(consoleHwnd);
			sf::Clock clock;
			while (!SetForegroundWindow(consoleHwnd) && clock.getElapsedTime().asMilliseconds() < 1000) //try to forcefully set foreground window
			{
				Sleep(1);
			}
		}

		//Dirty hack to make the steamoverlay work properly and still keep Apps Controllerconfig when closing overlay.
		//even if hooking steam, this ensures the overlay stays working
		if (overlayPtr != NULL)
		{
			char overlayOpen = *(char*)overlayPtr;
			if (overlayOpen)
			{
				if (!bNeedFocusSwitch)
				{
					bNeedFocusSwitch = true;

					hwForeGroundWindow = GetForegroundWindow();

					std::cout << "Saving current ForegorundWindow HWND: " << hwForeGroundWindow << std::endl;
					std::cout << "Activating OverlayWindow" << std::endl;

					SetWindowLong(sfWindow.getSystemHandle(), GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TOOLWINDOW); //make overlay window clickable

					//Actually activate the overlaywindow
					SetFocus(sfWindow.getSystemHandle());
					//by activating the consolewindow **and bringing it to the foreground** we can trick steam so the controller stays in game bindings
					SetFocus(consoleHwnd);
					sf::Clock clock;
					while (!SetForegroundWindow(consoleHwnd) && clock.getElapsedTime().asMilliseconds() < 1000) //try to forcefully set foreground window
					{
						Sleep(1);
					}

					//Move the mouse cursor inside the overlaywindow
					//this is neccessary because steam doesn't want to switch to big picture bindings if mouse isn't inside
					SetCursorPos(16, 16);

				}
			} else {
				if (bNeedFocusSwitch)
				{
					std::cout << "Deactivating OverlayWindow" << std::endl;

					//make overlaywindow clickthrough - WS_EX_TRANSPARENT - again
					SetWindowLong(sfWindow.getSystemHandle(), GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW);

					std::cout << "Switching to previously focused window" << std::endl;
{'fraction_non_alphanumeric': 0.10877192982456141, 'fraction_numerical': 0.010783055198973043, 'mean_word_length': 4.410185185185185, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '4313864', 'n_tokens_mistral': 4157, 'n_tokens_neox': 3580, 'n_words': 1060}