Skip to content

Instantly share code, notes, and snippets.

@Jessidhia
Created November 9, 2013 20:38
Show Gist options
  • Save Jessidhia/7389712 to your computer and use it in GitHub Desktop.
Save Jessidhia/7389712 to your computer and use it in GitHub Desktop.
#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