Created
November 9, 2013 20:38
-
-
Save Jessidhia/7389712 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <chrono> | |
#include <thread> | |
#include <cmath> | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <xinput.h> | |
#define ENABLE_KEYPRESS_ON_GUIDE_BUTTON_HACK 1 | |
#define GUIDE_BUTTON_VK VK_RCONTROL | |
#define GUIDE_BUTTON_SC 0x1d | |
#define GUIDE_BUTTON_FLAGS KEYEVENTF_EXTENDEDKEY | |
/* NOTE: Steam detects if the guide button is held for 3+ seconds | |
and enters Big Picture mode. No idea how to turn it off or prevent | |
Steam from seeing it if this is active. Don't Do That. */ | |
void postFakeKeypress(bool state) { | |
#if ENABLE_KEYPRESS_ON_GUIDE_BUTTON_HACK | |
static bool lastState = false; | |
if (state == lastState) | |
return; | |
KEYBDINPUT fakeInput = { | |
GUIDE_BUTTON_VK, | |
GUIDE_BUTTON_SC, | |
GUIDE_BUTTON_FLAGS, | |
0, | |
0, | |
}; | |
if (!state) { | |
fakeInput.dwFlags |= KEYEVENTF_KEYUP; | |
} | |
INPUT input = {INPUT_KEYBOARD}; | |
input.ki = fakeInput; | |
if (SendInput(1, &input, sizeof(INPUT)) == 1) { | |
lastState = state; | |
} else { | |
std::cerr << "Could not post fake keypress" << std::endl; | |
} | |
#endif | |
} | |
#define MAX_AXIS_VALUE 32767 | |
float getNormalizedMagnitude(float X, float Y, int deadzone) { | |
float magnitude = std::sqrt(X*X + Y*Y); | |
float normX = X / magnitude; | |
float normY = Y / magnitude; | |
if (magnitude > deadzone) { | |
if (magnitude > MAX_AXIS_VALUE) magnitude = MAX_AXIS_VALUE; | |
magnitude -= deadzone; | |
return magnitude / (MAX_AXIS_VALUE - deadzone); | |
} else { | |
return 0; | |
} | |
} | |
struct ControllerStruct | |
{ | |
DWORD eventCount; | |
union { | |
struct { | |
WORD up:1, down:1, left:1, right:1, start:1, back:1, l3:1, r3:1, | |
lButton:1, rButton:1, guideButton:1, unknown:1, aButton:1, | |
bButton:1, xButton:1, yButton:1; | |
} button; | |
WORD wButtons; | |
}; | |
BYTE bLeftTrigger; | |
BYTE bRightTrigger; | |
SHORT sThumbLX; | |
SHORT sThumbLY; | |
SHORT sThumbRX; | |
SHORT sThumbRY; | |
}; | |
int main(int argc, char *argv[]) { | |
HINSTANCE hXinput = LoadLibraryA("xinput1_3.dll"); | |
if (!hXinput) { | |
std::cerr << "Failed to load xinput1_3.dll -- make sure DirectX9 is updated." << std::endl << | |
"Download it at http://www.microsoft.com/en-us/download/details.aspx?id=8109" << std::endl; | |
return 1; | |
} | |
typedef int(__stdcall * XInputSecretStateProc)(int, ControllerStruct &); | |
auto XInputSecretState = (XInputSecretStateProc) GetProcAddress(HMODULE(hXinput), (LPCSTR)100); | |
typedef void(__stdcall * XInputEnableProc)(BOOL); | |
auto XInputEnable = (XInputEnableProc) GetProcAddress(HMODULE(hXinput), "XInputEnable"); | |
if (!XInputSecretState || !XInputEnable) { | |
std::cerr << "Failed to load functions from xinput1_3.dll!" << std::endl; | |
return 2; | |
} | |
std::cout << "Listening for XInput events and keeping computer awake." << std::endl; | |
bool lastState = false; | |
for (int count = 0; ; count++) { | |
XInputEnable(TRUE); | |
DWORD dwResult; | |
bool active = false; | |
for (DWORD i = 0; i < XUSER_MAX_COUNT; i++) { | |
ControllerStruct state; | |
ZeroMemory(&state, sizeof(ControllerStruct)); | |
dwResult = XInputSecretState(i, state); | |
if (dwResult == ERROR_SUCCESS) { | |
postFakeKeypress(state.button.guideButton); | |
if (state.wButtons & 0xffff) { | |
active = true; | |
break; | |
} | |
if (state.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { | |
active = true; | |
break; | |
} | |
if (state.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { | |
active = true; | |
break; | |
} | |
float mag = getNormalizedMagnitude( | |
state.sThumbLX, state.sThumbLY, | |
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE); | |
if (mag > 0) { | |
active = true; | |
break; | |
} | |
mag = getNormalizedMagnitude( | |
state.sThumbRX, state.sThumbRY, | |
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE); | |
if (mag > 0) { | |
active = true; | |
break; | |
} | |
} | |
} | |
if (active) { | |
count = 0; | |
if (active != lastState) | |
std::cout << "Activity detected." << std::endl; | |
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED); | |
lastState = true; | |
} else if (lastState && count > 20 /* approx. 1 second */) { | |
std::cout << "Activity stopped." << std::endl; | |
lastState = false; | |
} | |
std::this_thread::sleep_for(std::chrono::milliseconds(50)); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment