-
Notifications
You must be signed in to change notification settings - Fork 31
feat(windows): add touch input local option #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -44,6 +44,12 @@ static BYTE g_keyState[256] = {0}; | |||||||||||||||||||||||||||||||||||||
| static DWORD g_hookThread = 0; | ||||||||||||||||||||||||||||||||||||||
| static bool g_fakeServerInput = false; | ||||||||||||||||||||||||||||||||||||||
| static BOOL g_isPrimary = TRUE; | ||||||||||||||||||||||||||||||||||||||
| static bool g_touchInputLocal = false; | ||||||||||||||||||||||||||||||||||||||
| static bool g_isOnScreen = true; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Touch input signature in dwExtraInfo (bit 7 set indicates touch/pen) | ||||||||||||||||||||||||||||||||||||||
| #define TOUCH_SIGNATURE_MASK 0xFFFFFF00 | ||||||||||||||||||||||||||||||||||||||
| #define TOUCH_SIGNATURE 0xFF515700 | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+52
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Why static const instead of #define: You'll see #define all over older code - it's a habit from C, where it was the only option. But C++ has better tools now. Think of #define like a dumb find-and-replace - it just swaps the name for the value everywhere, with no understanding of what it means. If something goes wrong, error messages are confusing and debuggers won't show you the name. Using static const creates something the compiler actually understands, so you get clearer errors and can see the name when troubleshooting. New code should use the better approach, even if older code doesn't. Why mouseFromTouchInput instead of something vague: "Touch signature" makes you think "touch what?" But "mouse from touch input" tells you right away it's about mouse events generated by touchscreen/touchpad input. Good names mean you don't have to hunt through surrounding code to figure out what something means. |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| MSWindowsHook::MSWindowsHook() | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -148,6 +154,17 @@ void MSWindowsHook::setMode(EHookMode mode) | |||||||||||||||||||||||||||||||||||||
| g_mode = mode; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| void MSWindowsHook::setTouchInputLocal(bool enable) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| g_touchInputLocal = enable; | ||||||||||||||||||||||||||||||||||||||
| LOG((CLOG_DEBUG "hook: touchInputLocal = %s", enable ? "true" : "false")); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| void MSWindowsHook::setIsOnScreen(bool onScreen) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| g_isOnScreen = onScreen; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| static void keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| // we have to use GetAsyncKeyState() rather than GetKeyState() because | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -585,6 +602,19 @@ static LRESULT CALLBACK mouseLLHook(int code, WPARAM wParam, LPARAM lParam) | |||||||||||||||||||||||||||||||||||||
| return CallNextHookEx(g_mouseLL, code, wParam, lParam); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Check if this mouse event was generated from touch input | ||||||||||||||||||||||||||||||||||||||
| // Touch input has a specific signature in dwExtraInfo | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
| // Touch input has a specific signature in dwExtraInfo | |
| // Touch input has a specific signature in dwExtraInfo | |
| // NOTE: The TOUCH_SIGNATURE* values are based on an undocumented Windows | |
| // implementation detail (dwExtraInfo signature 0xFF515700) that is commonly | |
| // used to identify touch-generated mouse events. This heuristic may not work | |
| // reliably across all hardware or future Windows versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Check if this mouse event was generated from touch input | |
| // Touch input has a specific signature in dwExtraInfo | |
| bool isTouchGenerated = ((info->dwExtraInfo & TOUCH_SIGNATURE_MASK) == TOUCH_SIGNATURE); | |
| // If touchInputLocal is enabled and cursor is on client screen, | |
| // let the touch event work locally but don't forward it to the client | |
| if (g_touchInputLocal && !g_isOnScreen && isTouchGenerated) { | |
| LOG((CLOG_DEBUG "touch event - processing locally, not forwarding to client")); | |
| // Don't call mouseHookHandler - this skips forwarding to client | |
| // Don't return 1 - this lets the event proceed to local applications | |
| return CallNextHookEx(g_mouseLL, code, wParam, lParam); | |
| } | |
| // touch gestures don't translate well to remote clients, so optionally keep them local | |
| bool const mouseFromTouchInput = (info->dwExtraInfo & TOUCH_SIGNATURE_MASK) == TOUCH_SIGNATURE; | |
| if (g_touchInputLocal && !g_isOnScreen && mouseFromTouchInput) { | |
| LOG((CLOG_DEBUG1 "touch-generated mouse event, keeping input on server")); | |
| return CallNextHookEx(g_mouseLL, code, wParam, lParam); | |
| } |
When you pick descriptive variable names like mouseFromTouchInput, the code starts to read like a sentence - so you don't need a comment above it saying the same thing. That frees you up to use comments for the stuff that isn't obvious from the code, like why this feature exists in the first place. It's a handy trick that makes code easier to follow and means fewer comments to keep up to date.
Also, log level CLOG_DEBUG1 might be better. I noticed that this long line is very noisy as it happens on every mouse event and for those kinds of noisy log lines we push them to the higher log levels.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |||||||||||||||||||||||||||||||||||
| #include "platform/MSWindowsScreen.h" | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| #include "arch/Arch.h" | ||||||||||||||||||||||||||||||||||||
| #include "deskflow/option_types.h" | ||||||||||||||||||||||||||||||||||||
| #include "arch/win32/ArchMiscWindows.h" | ||||||||||||||||||||||||||||||||||||
| #include "base/IEventQueue.h" | ||||||||||||||||||||||||||||||||||||
| #include "base/Log.h" | ||||||||||||||||||||||||||||||||||||
|
|
@@ -83,6 +84,28 @@ | |||||||||||||||||||||||||||||||||||
| #define PBT_APMRESUMEAUTOMATIC 0x0012 | ||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // WM_POINTER stuff (Windows 8+) | ||||||||||||||||||||||||||||||||||||
| #if !defined(WM_POINTERDOWN) | ||||||||||||||||||||||||||||||||||||
| #define WM_POINTERDOWN 0x0246 | ||||||||||||||||||||||||||||||||||||
| #define WM_POINTERUP 0x0247 | ||||||||||||||||||||||||||||||||||||
| #define WM_POINTERUPDATE 0x0245 | ||||||||||||||||||||||||||||||||||||
| #define WM_POINTERENTER 0x0249 | ||||||||||||||||||||||||||||||||||||
| #define WM_POINTERLEAVE 0x024A | ||||||||||||||||||||||||||||||||||||
| #define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) | ||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| #if !defined(PT_POINTER) | ||||||||||||||||||||||||||||||||||||
| #define PT_POINTER 1 | ||||||||||||||||||||||||||||||||||||
| #define PT_TOUCH 2 | ||||||||||||||||||||||||||||||||||||
| #define PT_PEN 3 | ||||||||||||||||||||||||||||||||||||
| #define PT_MOUSE 4 | ||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+87
to
+102
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
These #if !defined guards aren't needed because we only target Windows 10+ with a modern SDK. These constants (WM_POINTERDOWN, PT_TOUCH, etc.) are already defined in the SDK. If added by an LLM, it's because they tend to be overly defensive. LLMs are trained on lots of older code that needed these compatibility shims, so they often add them "just in case" without considering the actual build environment. It's a common pattern: the LLM doesn't know your minimum SDK version, so it hedges by including fallbacks that were necessary 10 years ago but are now just noise. When using an LLM to generate code, watch for this kind of unnecessary defensiveness; legacy patterns copied without understanding the current context. |
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Function pointer type for GetPointerType (loaded dynamically for Win7 compat) | ||||||||||||||||||||||||||||||||||||
| typedef BOOL(WINAPI *GetPointerTypeFunc)(UINT32 pointerId, DWORD *pointerType); | ||||||||||||||||||||||||||||||||||||
| static GetPointerTypeFunc s_getPointerType = NULL; | ||||||||||||||||||||||||||||||||||||
| static bool s_pointerApiChecked = false; | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+104
to
+107
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This backward compatibility for Windows 8 is likely redundant. |
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||
| // MSWindowsScreen | ||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||
|
|
@@ -124,7 +147,9 @@ MSWindowsScreen::MSWindowsScreen( | |||||||||||||||||||||||||||||||||||
| m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0), | ||||||||||||||||||||||||||||||||||||
| m_events(events), | ||||||||||||||||||||||||||||||||||||
| m_dropWindow(NULL), | ||||||||||||||||||||||||||||||||||||
| m_dropWindowSize(20) | ||||||||||||||||||||||||||||||||||||
| m_dropWindowSize(20), | ||||||||||||||||||||||||||||||||||||
| m_touchInputLocal(false), | ||||||||||||||||||||||||||||||||||||
| m_lastInputWasTouch(false) | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| LOG_DEBUG("settting up %s screen", m_isPrimary ? "primary" : "secondary"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
@@ -313,6 +338,7 @@ void MSWindowsScreen::enter() | |||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // now on screen | ||||||||||||||||||||||||||||||||||||
| m_isOnScreen = true; | ||||||||||||||||||||||||||||||||||||
| m_hook.setIsOnScreen(true); | ||||||||||||||||||||||||||||||||||||
| setupMouseKeys(); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
@@ -369,6 +395,7 @@ void MSWindowsScreen::leave() | |||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // now off screen | ||||||||||||||||||||||||||||||||||||
| m_isOnScreen = false; | ||||||||||||||||||||||||||||||||||||
| m_hook.setIsOnScreen(false); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (isDraggingStarted() && !m_isPrimary) { | ||||||||||||||||||||||||||||||||||||
| m_sendDragThread = new Thread(new TMethodJob<MSWindowsScreen>(this, &MSWindowsScreen::sendDragThread)); | ||||||||||||||||||||||||||||||||||||
|
|
@@ -475,6 +502,16 @@ void MSWindowsScreen::resetOptions() | |||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| void MSWindowsScreen::setOptions(const OptionsList &options) | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| // Handle touch input local option | ||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
| for (UInt32 i = 0, n = (UInt32)options.size(); i < n; i += 2) { | ||||||||||||||||||||||||||||||||||||
| if (options[i] == kOptionTouchInputLocal) { | ||||||||||||||||||||||||||||||||||||
| m_touchInputLocal = (options[i + 1] != 0); | ||||||||||||||||||||||||||||||||||||
| LOG((CLOG_DEBUG1 "touchInputLocal = %s", m_touchInputLocal ? "true" : "false")); | ||||||||||||||||||||||||||||||||||||
| // Update the hook so it can block touch-generated mouse events | ||||||||||||||||||||||||||||||||||||
| m_hook.setTouchInputLocal(m_touchInputLocal); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| m_desks->setOptions(options); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
@@ -1043,6 +1080,19 @@ bool MSWindowsScreen::onEvent(HWND, UINT msg, WPARAM wParam, LPARAM lParam, LRES | |||||||||||||||||||||||||||||||||||
| case WM_DISPLAYCHANGE: | ||||||||||||||||||||||||||||||||||||
| return onDisplayChange(); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Handle pointer input (touch/pen) - Windows 8+ | ||||||||||||||||||||||||||||||||||||
| // This allows us to detect touch vs mouse input and optionally keep touch local | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1083
to
+1084
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
| case WM_POINTERDOWN: | ||||||||||||||||||||||||||||||||||||
| case WM_POINTERUP: | ||||||||||||||||||||||||||||||||||||
| case WM_POINTERUPDATE: | ||||||||||||||||||||||||||||||||||||
| if (m_isPrimary && onPointerInput(wParam, lParam)) { | ||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Perhaps I'm missing something, but I tried just using |
||||||||||||||||||||||||||||||||||||
| // Touch input was consumed (kept local) | ||||||||||||||||||||||||||||||||||||
| *result = 0; | ||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| // Fall through to let DefWindowProc convert to mouse messages | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /* On windows 10 we don't receive WM_POWERBROADCAST after sleep. | ||||||||||||||||||||||||||||||||||||
| We receive only WM_TIMECHANGE hence this message is used to resume.*/ | ||||||||||||||||||||||||||||||||||||
| case WM_TIMECHANGE: | ||||||||||||||||||||||||||||||||||||
|
|
@@ -1378,6 +1428,58 @@ bool MSWindowsScreen::onMouseWheel(SInt32 xDelta, SInt32 yDelta) | |||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| bool MSWindowsScreen::isPointerTypeTouch(UINT32 pointerId) const | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| // Dynamically load GetPointerType for Windows 7 compatibility | ||||||||||||||||||||||||||||||||||||
| if (!s_pointerApiChecked) { | ||||||||||||||||||||||||||||||||||||
| s_pointerApiChecked = true; | ||||||||||||||||||||||||||||||||||||
| HMODULE user32 = GetModuleHandle("user32.dll"); | ||||||||||||||||||||||||||||||||||||
| if (user32 != NULL) { | ||||||||||||||||||||||||||||||||||||
| s_getPointerType = (GetPointerTypeFunc)GetProcAddress(user32, "GetPointerType"); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (s_getPointerType == NULL) { | ||||||||||||||||||||||||||||||||||||
| // API not available (Windows 7 or earlier) | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| DWORD pointerType = PT_POINTER; | ||||||||||||||||||||||||||||||||||||
| if (s_getPointerType(pointerId, &pointerType)) { | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1433
to
+1448
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
We can probably just call the function directly. |
||||||||||||||||||||||||||||||||||||
| return (pointerType == PT_TOUCH || pointerType == PT_PEN); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| bool MSWindowsScreen::onPointerInput(WPARAM wParam, LPARAM lParam) | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| UINT32 pointerId = GET_POINTERID_WPARAM(wParam); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| LOG((CLOG_DEBUG "onPointerInput: pointerId=%d, touchInputLocal=%s, isOnScreen=%s", | ||||||||||||||||||||||||||||||||||||
| pointerId, m_touchInputLocal ? "true" : "false", m_isOnScreen ? "true" : "false")); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Check if this is touch/pen input | ||||||||||||||||||||||||||||||||||||
| if (isPointerTypeTouch(pointerId)) { | ||||||||||||||||||||||||||||||||||||
| m_lastInputWasTouch = true; | ||||||||||||||||||||||||||||||||||||
| LOG((CLOG_DEBUG "pointer is touch input")); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // If touchInputLocal is enabled and cursor is on another screen, | ||||||||||||||||||||||||||||||||||||
| // consume the event so it stays local | ||||||||||||||||||||||||||||||||||||
| if (m_touchInputLocal && !m_isOnScreen) { | ||||||||||||||||||||||||||||||||||||
| LOG((CLOG_INFO "touch input kept local (cursor on client screen)")); | ||||||||||||||||||||||||||||||||||||
| // Return true to indicate we handled it - this prevents | ||||||||||||||||||||||||||||||||||||
| // DefWindowProc from converting it to mouse input | ||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||
| m_lastInputWasTouch = false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Let the system handle the pointer input normally | ||||||||||||||||||||||||||||||||||||
| // It will be converted to mouse messages and caught by our hook | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| bool MSWindowsScreen::onScreensaver(bool activated) | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| // ignore this message if there are any other screen saver | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -187,6 +187,8 @@ class MSWindowsScreen : public PlatformScreen | |||
| bool onMouseButton(WPARAM, LPARAM); | ||||
| bool onMouseMove(SInt32 x, SInt32 y); | ||||
| bool onMouseWheel(SInt32 xDelta, SInt32 yDelta); | ||||
| bool onPointerInput(WPARAM wParam, LPARAM lParam); | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| bool isPointerTypeTouch(UINT32 pointerId) const; | ||||
| bool onScreensaver(bool activated); | ||||
| bool onDisplayChange(); | ||||
| bool onClipboardChange(); | ||||
|
|
@@ -343,6 +345,10 @@ class MSWindowsScreen : public PlatformScreen | |||
|
|
||||
| MSWindowsHook m_hook; | ||||
|
|
||||
| // Touch input local policy - when true, touch stays on primary screen | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| bool m_touchInputLocal; | ||||
| bool m_lastInputWasTouch; | ||||
|
|
||||
| static MSWindowsScreen *s_screen; | ||||
|
|
||||
| IEventQueue *m_events; | ||||
|
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checkbox has two signal connections (stateChanged at line 150 and checkStateChanged at line 204) that both call setTouchInputLocal. This will cause the setting to be updated twice for each user interaction. Remove one of these duplicate connections.