Created
February 17, 2024 04:08
-
-
Save arpruss/026e9c06562adaeb094f07960dbff8e4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
//x86_64-w64-mingw32-gcc -o disable-two-finger-click -mwindows -O99 disable-two-finger-click.cpp | |
#include <thread> | |
#include <Windows.h> | |
#include <stdio.h> | |
#include <time.h> | |
HHOOK miHook; | |
const bool ALLOW_DOUBLE_TAP_RIGHT_CLICK = true; | |
const unsigned TWOFINGER_DETECT_DELAY_CLOCKS = CLOCKS_PER_SEC * 50 / 1000; | |
const unsigned CLICK_DETECT_DELAY_CLOCKS = CLOCKS_PER_SEC * 50 / 1000; | |
const unsigned OUT_BUFFER_SIZE = 2048; | |
const unsigned MAX_HID = 512; | |
unsigned num_fingers = 0; | |
clock_t last_click = 0; | |
clock_t last_two_finger_time = 0; | |
unsigned char outBuffer[OUT_BUFFER_SIZE]; | |
unsigned outBufferHead; | |
unsigned outBufferTail; | |
HANDLE queueReady; | |
bool running = true; | |
int popBuffer() { | |
if (outBufferHead == outBufferTail) | |
return -1; | |
unsigned char c = outBuffer[outBufferHead]; | |
outBufferHead = (outBufferHead+1) % OUT_BUFFER_SIZE; | |
return c; | |
} | |
int pushBuffer(unsigned char c) { | |
unsigned newTail = (outBufferTail+1) % OUT_BUFFER_SIZE; | |
if (newTail == outBufferHead) | |
return -1; | |
outBuffer[outBufferTail] = c; | |
outBufferTail = newTail; | |
return 0; | |
} | |
DWORD WINAPI handleQueue(void* arg) { | |
INPUT ip; | |
ip.type = INPUT_MOUSE; | |
ip.mi.dx = 0; | |
ip.mi.dy = 0; | |
ip.mi.mouseData = 0; | |
ip.mi.time = 0; | |
while(running) { | |
WaitForSingleObject(queueReady, INFINITE); | |
int c; | |
while (running && (c = popBuffer()) >= 0) { | |
if (c) | |
ip.mi.dwFlags = WM_RBUTTONDOWN; | |
else | |
ip.mi.dwFlags = WM_RBUTTONUP; | |
SendInput(1,&ip,sizeof(INPUT)); | |
} | |
} | |
ExitThread(0); | |
return 0; | |
} | |
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { | |
static bool remapped_down = false; | |
if(nCode == HC_ACTION) { | |
if(wParam == WM_RBUTTONDOWN) { | |
clock_t t = clock(); | |
if ( (num_fingers > 1 && t-last_two_finger_time<TWOFINGER_DETECT_DELAY_CLOCKS) && | |
(ALLOW_DOUBLE_TAP_RIGHT_CLICK || t-last_click<CLICK_DETECT_DELAY_CLOCKS) ) { | |
pushBuffer(1); | |
SetEvent(queueReady); | |
remapped_down = true; | |
return 1; | |
} | |
} | |
else if (wParam == WM_RBUTTONUP && remapped_down) { | |
pushBuffer(0); | |
SetEvent(queueReady); | |
remapped_down = false; | |
return 1; | |
} | |
} | |
return CallNextHookEx(miHook, nCode, wParam, lParam); // Important! Otherwise other mouse hooks may misbehave | |
} | |
// https://gist.github.com/luluco250/ac79d72a734295f167851ffdb36d77ee | |
LRESULT CALLBACK EventHandler( | |
HWND hwnd, | |
unsigned event, | |
WPARAM wparam, | |
LPARAM lparam | |
) { | |
static RAWINPUT buffer[sizeof(RAWINPUT)+MAX_HID]; | |
switch (event) { | |
case WM_DESTROY: | |
PostQuitMessage(0); | |
return 0; | |
case WM_INPUT: { | |
unsigned size = sizeof(buffer); | |
int res = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)); | |
if (res < 0 || size == 0) { | |
return 0; | |
} | |
if (buffer->header.dwType == RIM_TYPEHID && buffer->data.hid.dwSizeHid > 28) { | |
BYTE* data = buffer->data.hid.bRawData; | |
num_fingers = data[28]; | |
clock_t t = clock(); | |
if (num_fingers>=2) | |
last_two_finger_time = t; | |
if(buffer->data.hid.dwSizeHid > 29 && data[29]) | |
last_click = t; | |
} | |
} return 0; | |
} | |
return DefWindowProc(hwnd, event, wparam, lparam); | |
} | |
//main() | |
int WINAPI WinMain(HINSTANCE instance, HINSTANCE hPrevInstance, | |
PSTR lpCmdLine, int nCmdShow) | |
{ | |
const char* class_name = "fix-touchpad-right-click-class"; | |
//HINSTANCE instance = GetModuleHandle(0); | |
WNDCLASS window_class = {}; | |
window_class.lpfnWndProc = EventHandler; | |
window_class.hInstance = instance; | |
window_class.lpszClassName = class_name; | |
if (!RegisterClass(&window_class)) | |
return -1; | |
HWND window = CreateWindow(class_name, "fix-touchpad-right-click", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0); | |
if (window == nullptr) | |
return -1; | |
RAWINPUTDEVICE rid[1]; | |
rid[0].usUsagePage = 0x0D; | |
rid[0].usUsage = 0x05; | |
rid[0].dwFlags = RIDEV_INPUTSINK; | |
rid[0].hwndTarget = window; | |
RegisterRawInputDevices(rid, 1, sizeof(rid[0])); | |
miHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)(&LowLevelMouseProc), 0, 0); | |
queueReady = CreateEvent(NULL, FALSE, FALSE, (LPTSTR)("queueReady")); | |
HANDLE queueThread = CreateThread(NULL, 0, handleQueue, NULL, 0, NULL); | |
MSG message; | |
while(GetMessage(&message, NULL, 0, 0)) { | |
TranslateMessage(&message); | |
DispatchMessage(&message); | |
} | |
running = 0; | |
SetEvent(queueReady); | |
UnhookWindowsHookEx(miHook); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment