Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/ProtoInput/ProtoInputHooks/AdjustWindowRectHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ namespace Proto
void AdjustWindowRectHook::ShowGuiStatus()
{
int pos[2] = { posx, posy };
ImGui::SliderInt2("Position", &pos[0], -5000, 5000);
ImGui::InputInt2("Position", &pos[0]);
posx = pos[0];
posy = pos[1];

int size[2] = { width, height };
ImGui::SliderInt2("Size", &size[0], 0, 5000);
ImGui::InputInt2("Size", &size[0]);
width = size[0];
height = size[1];
}
Expand Down
125 changes: 105 additions & 20 deletions src/ProtoInput/ProtoInputHooks/FakeCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ namespace Proto
{

FakeCursor FakeCursor::state{};
#define WM_MOVE_pointerWindow (WM_APP + 1)

LRESULT WINAPI FakeCursorWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_MOVE_pointerWindow:
FakeCursor::state.GetWindowDimensions(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
Expand All @@ -40,6 +44,34 @@ BOOL CALLBACK EnumWindowsProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMoni
}
return true;
}

void FakeCursor::GetWindowDimensions(HWND pointerWindow)
{

HWND tHwnd = (HWND)HwndSelector::GetSelectedHwnd();
if (pointerWindow == tHwnd)
{
SetWindowPos(pointerWindow, /*HWND_TOP*/HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
return;
}

if (IsWindow(tHwnd))
{
RECT cRect;
GetClientRect(tHwnd, &cRect);

POINT topLeft = { cRect.left, cRect.top };
ClientToScreen(tHwnd, &topLeft);

SetWindowPos(pointerWindow, /*HWND_TOP*/HWND_TOPMOST,
topLeft.x,
topLeft.y,
cRect.right - cRect.left,
cRect.bottom - cRect.top,
SWP_NOACTIVATE);
}
}

void FakeCursor::DrawCursor()
{

Expand Down Expand Up @@ -139,6 +171,31 @@ DWORD WINAPI FakeCursorDrawLoopThread(LPVOID lpParameter)
return 0;
}

DWORD WINAPI PointerWindowLoopThread(LPVOID lpParameter)
{
printf("Pointer window loop thread start");
FakeCursor::state.UpdatePointerWindowLoopInternal();

return 0;
}

void FakeCursor::UpdatePointerWindowLoopInternal()
{
while (true)
{
HWND tHwnd = (HWND)HwndSelector::GetSelectedHwnd();
if (!IsWindow(tHwnd))
{
Sleep(2000);
continue;
}

PostMessage(pointerWindow, WM_MOVE_pointerWindow, 0, 0);

Sleep(5000);
}
}

void FakeCursor::StartDrawLoopInternal()
{
int tick = 0;
Expand All @@ -153,17 +210,20 @@ void FakeCursor::StartDrawLoopInternal()
//TODO: is this ok? (might eat cpu)
Sleep(drawingEnabled ? 12 : 500);

tick = (tick + 1) % 200;
if (!FakeMouseKeyboard::PutMouseInsideWindow)
{
tick = (tick + 1) % 200;

if (tick == 0)
// Nucleus can put the game window above the pointer without this
SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
if (tick == 0)
// Nucleus can put the game window above the pointer without this
SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
}
}
}

void FakeCursor::StartInternal()
{
Proto::AddThreadToACL(GetCurrentThreadId());
Sleep(1000);

const auto hInstance = GetModuleHandle(NULL);

Expand All @@ -182,6 +242,13 @@ void FakeCursor::StartInternal()
wc.lpszClassName = className;
wc.style = CS_OWNDC | CS_NOCLOSE;

DWORD ws_POPUP;

if (FakeMouseKeyboard::PutMouseInsideWindow)
ws_POPUP = WS_POPUP;
else
ws_POPUP = 0;

if (!RegisterClass(&wc))
{
fprintf(stderr, "Failed to open fake cursor window\n");
Expand All @@ -190,35 +257,52 @@ void FakeCursor::StartInternal()
{
pointerWindow = CreateWindowExW(WS_EX_NOACTIVATE | WS_EX_NOINHERITLAYOUT | WS_EX_NOPARENTNOTIFY |
WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_LAYERED,
wc.lpszClassName, classNameStr.c_str(), 0,
0, 0, 200, 200,
nullptr, nullptr, hInstance, nullptr);
wc.lpszClassName, classNameStr.c_str(), ws_POPUP,
0, 0, 200, 200,
nullptr, nullptr, hInstance, nullptr);

if (!FakeMouseKeyboard::PutMouseInsideWindow)
SetWindowLongW(pointerWindow, GWL_STYLE, WS_VISIBLE | WS_DISABLED);

SetWindowLongW(pointerWindow, GWL_STYLE, WS_VISIBLE | WS_DISABLED);
SetLayeredWindowAttributes(pointerWindow, transparencyKey, 0, LWA_COLORKEY);

// Nucleus can put the game window above the pointer without this
SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
if (!FakeMouseKeyboard::PutMouseInsideWindow)
{
// Nucleus can put the game window above the pointer without this
SetWindowPos(pointerWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);

// ShowWindow(pointerWindow, SW_SHOWDEFAULT);
// UpdateWindow(pointerWindow);
EnableDisableFakeCursor(drawingEnabled);
// ShowWindow(pointerWindow, SW_SHOWDEFAULT);
// UpdateWindow(pointerWindow);
EnableDisableFakeCursor(drawingEnabled);

// Over every screen
EnumDisplayMonitors(nullptr, nullptr, &EnumWindowsProc, 0);
MoveWindow(pointerWindow, fakeCursorMinX, fakeCursorMinY, fakeCursorMaxX - fakeCursorMinX, fakeCursorMaxY - fakeCursorMinY, TRUE);
// Over every screen
EnumDisplayMonitors(nullptr, nullptr, &EnumWindowsProc, 0);
MoveWindow(pointerWindow, fakeCursorMinX, fakeCursorMinY, fakeCursorMaxX - fakeCursorMinX, fakeCursorMaxY - fakeCursorMinY, TRUE);
}

hdc = GetDC(pointerWindow);

//TODO: configurable cursor
hCursor = LoadCursorW(NULL, IDC_ARROW);
if (FakeMouseKeyboard::PutMouseInsideWindow)
hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(32512));
else
hCursor = LoadCursorW(NULL, IDC_ARROW); //TODO: configurable cursor

const auto threadHandle = CreateThread(nullptr, 0,
(LPTHREAD_START_ROUTINE)FakeCursorDrawLoopThread, GetModuleHandle(0), 0, 0);

if (threadHandle != nullptr)
CloseHandle(threadHandle);

if (FakeMouseKeyboard::PutMouseInsideWindow)
{
const auto pointerThreadHandle = CreateThread(nullptr, 0,
(LPTHREAD_START_ROUTINE)PointerWindowLoopThread, GetModuleHandle(0), 0, 0);

if (pointerThreadHandle != nullptr)
CloseHandle(pointerThreadHandle);
FakeCursor::EnableDisableFakeCursor(true);
}

// Want to avoid doing anything in the message loop that might cause it to not respond, as the entire screen will say not responding...
MSG msg;
ZeroMemory(&msg, sizeof(msg));
Expand Down Expand Up @@ -246,7 +330,8 @@ void FakeCursor::EnableDisableFakeCursor(bool enable)
{
state.drawingEnabled = enable;

ShowWindow(state.pointerWindow, enable ? SW_SHOWDEFAULT : SW_HIDE);
auto showWindow = FakeMouseKeyboard::PutMouseInsideWindow ? SW_SHOWNOACTIVATE : SW_SHOWDEFAULT;
ShowWindow(state.pointerWindow, enable ? showWindow : SW_HIDE);
UpdateWindow(state.pointerWindow);
}

Expand Down
2 changes: 2 additions & 0 deletions src/ProtoInput/ProtoInputHooks/FakeCursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class FakeCursor
bool DrawFakeCursorFix;
void StartInternal();
void StartDrawLoopInternal();
void UpdatePointerWindowLoopInternal(); // Checks the selected window dimensions.
void GetWindowDimensions(HWND hWnd); // For pointerWindow

static bool& GetToggleVisilbityShorcutEnabled()
{
Expand Down
31 changes: 27 additions & 4 deletions src/ProtoInput/ProtoInputHooks/FakeMouseKeyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ void FakeMouseKeyboard::AddMouseDelta(int dx, int dy)
{
if (!DefaultBottomRightMouseBounds)
{
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowWidth * 2 : HwndSelector::windowWidth; mouseState.x > max)
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowWidth * 2 : HwndSelector::windowWidth; mouseState.x >= max)
mouseState.x = max - 1;

if (int max = mouseState.extendMouseBounds ? HwndSelector::windowHeight * 2 : HwndSelector::windowHeight; mouseState.y > max)
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowHeight * 2 : HwndSelector::windowHeight; mouseState.y >= max)
mouseState.y = max - 1;
}
else if (DefaultBottomRightMouseBounds)
Expand Down Expand Up @@ -137,9 +137,9 @@ void FakeMouseKeyboard::SetMousePos(int x, int y)
{
if (!DefaultBottomRightMouseBounds)
{
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowWidth * 2 : HwndSelector::windowWidth; mouseState.x > max)
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowWidth * 2 : HwndSelector::windowWidth; mouseState.x >= max)
mouseState.x = max - 1;
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowHeight * 2 : HwndSelector::windowHeight; mouseState.y > max)
if (int max = mouseState.extendMouseBounds ? HwndSelector::windowHeight * 2 : HwndSelector::windowHeight; mouseState.y >= max)
mouseState.y = max - 1;
}
else if (DefaultBottomRightMouseBounds)
Expand Down Expand Up @@ -255,4 +255,27 @@ bool FakeMouseKeyboard::IsAsyncKeyStatePressed(int vkey)
return false;
}

bool FakeMouseKeyboard::IsExtendedKeyStatePressed(int vkey)
{
switch (vkey)
{
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
case VK_HOME:
case VK_END:
case VK_PRIOR:
case VK_NEXT:
case VK_INSERT:
case VK_DELETE:
case VK_RCONTROL:
case VK_RMENU:
case VK_SEPARATOR:
return true;
default:
return false;
}
}

}
1 change: 1 addition & 0 deletions src/ProtoInput/ProtoInputHooks/FakeMouseKeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class FakeMouseKeyboard
static void ClearAsyncKeyState(int vkey);
static bool IsKeyStatePressed(int vkey);
static bool IsAsyncKeyStatePressed(int vkey);
static bool IsExtendedKeyStatePressed(int vkey); //To use the exteended key flag (like arrow keys)

// Some games must use the exact window rect to determine the edge of the window.
static bool PutMouseInsideWindow;
Expand Down
22 changes: 19 additions & 3 deletions src/ProtoInput/ProtoInputHooks/FocusHook.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
#include "FocusHook.h"
#include <imgui.h>
#include "HwndSelector.h"
#include "INISettings.h"

namespace Proto
{

inline HWND GetHwnd()
{
if (HwndSelector::GetSelectedHwnd() == 0)
HwndSelector::UpdateMainHwnd();
if (Proto::fixWindowFocus)
{
HWND current = (HWND)HwndSelector::GetSelectedHwnd();

// Check if the handle is 0 OR if the window no longer exists (e.g. after resolution change)
if (current == 0 || !IsWindow(current))
{
HwndSelector::UpdateMainHwnd();
current = (HWND)HwndSelector::GetSelectedHwnd();
}
return current;
}
else // Default
{
if (HwndSelector::GetSelectedHwnd() == 0)
HwndSelector::UpdateMainHwnd();

return (HWND)HwndSelector::GetSelectedHwnd();
return (HWND)HwndSelector::GetSelectedHwnd();
}
}

HWND WINAPI Hook_GetForegroundWindow()
Expand Down
4 changes: 4 additions & 0 deletions src/ProtoInput/ProtoInputHooks/GuiImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "RawInput.h"
#include "FontData.h"
#include "Cleanup.h"
#include "INISettings.h"

//TODO: default to hidden
constexpr bool defaultGuiToHidden = true;
Expand Down Expand Up @@ -139,6 +140,9 @@ void Proto::SetConsoleVisible(bool visible)

int Proto::ShowGuiImpl()
{
if (Proto::DisableGuiWindow)
return 0;

auto hInstance = GetModuleHandle(NULL);

WNDCLASS wc = { 0 };
Expand Down
Loading