diff options
author | Kacper Michajłow <kasper93@gmail.com> | 2015-09-24 01:31:21 +0300 |
---|---|---|
committer | Kacper Michajłow <kasper93@gmail.com> | 2015-09-24 22:34:54 +0300 |
commit | 19e47dff6c349eb030e1456241272e15c4d71245 (patch) | |
tree | da5e3073a5302fca9c5de4037f2cee9a055a8409 | |
parent | e5f6b2c79ce1a211b71fa713f686e7acf6422f37 (diff) |
Mouse: Adjust mouse behavior for Windows 10.
Mouse messages are dispatched to the focused window first, but if it
isn't interested message will be dispatched to the root window instead.
Closes #5248
-rw-r--r-- | docs/Changelog.txt | 1 | ||||
-rw-r--r-- | src/mpc-hc/MouseTouch.cpp | 14 | ||||
-rw-r--r-- | src/mpc-hc/MouseTouch.h | 75 |
3 files changed, 47 insertions, 43 deletions
diff --git a/docs/Changelog.txt b/docs/Changelog.txt index a86f5f5a3..4b0f02777 100644 --- a/docs/Changelog.txt +++ b/docs/Changelog.txt @@ -39,6 +39,7 @@ next version - not released yet ! QuickTime: Fix a crash when using system default renderer
! Fix "snap to desktop edge" and "autofit zoom" on Windows 10
! Ticket #4086, Logitech LCD: Correctly initialize the volume at start-up
+! Ticket #5248, Adjust mouse behavior for Windows 10
! Ticket #5454, Deleting an item from the playlist sometimes did not work when shuffle mode was enabled
! Ticket #5464, If the main window was minimized while the D3D Fullscreen window was displayed on another screen,
it was impossible to use the mouse buttons to play, pause, exit fullscreen, etc.
diff --git a/src/mpc-hc/MouseTouch.cpp b/src/mpc-hc/MouseTouch.cpp index 39f1d8b8f..9812dda23 100644 --- a/src/mpc-hc/MouseTouch.cpp +++ b/src/mpc-hc/MouseTouch.cpp @@ -1,5 +1,5 @@ /* - * (C) 2013-2014 see Authors.txt + * (C) 2013-2015 see Authors.txt * * This file is part of MPC-HC. * @@ -635,15 +635,15 @@ void CMouseWnd::OnDestroy() CWnd::OnDestroy(); } -std::vector<CWnd*> CMainFrameMouseHook::GetRoots() +std::unordered_set<const CWnd*> CMainFrameMouseHook::GetRoots() { - std::vector<CWnd*> ret; - ret.reserve(2); - CMainFrame* pMainFrame = AfxGetMainFrame(); + std::unordered_set<const CWnd*> ret; + const CMainFrame* pMainFrame = AfxGetMainFrame(); + ASSERT(pMainFrame); if (pMainFrame) { - ret.emplace_back(pMainFrame); + ret.emplace(pMainFrame); if (pMainFrame->IsD3DFullScreenMode()) { - ret.emplace_back(pMainFrame->m_pFullscreenWnd); + ret.emplace(pMainFrame->m_pFullscreenWnd); } } return ret; diff --git a/src/mpc-hc/MouseTouch.h b/src/mpc-hc/MouseTouch.h index 8e094fc2a..806bc2b82 100644 --- a/src/mpc-hc/MouseTouch.h +++ b/src/mpc-hc/MouseTouch.h @@ -21,9 +21,10 @@ #pragma once #include <map> -#include <vector> +#include <unordered_set> #include "EventDispatcher.h" +#include "SysVersion.h" // TODO: handle touch gestures @@ -169,45 +170,45 @@ private: template <class T> class CMouseWheelHook { - HHOOK m_hHook; + HHOOK m_hHook = NULL; static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode == HC_ACTION && wParam == WM_MOUSEWHEEL) { const auto& msex = *reinterpret_cast<MOUSEHOOKSTRUCTEX*>(lParam); - if (CWnd* pFocus = CWnd::FromHandlePermanent(msex.hwnd)) { - if (CWnd* pFocusRoot = pFocus->GetAncestor(GA_ROOT)) { - for (CWnd* pRoot : T::GetRoots()) { - ASSERT(pRoot); - // only intercept messages to focused windows that have white-listed root windows - if (pRoot && *pRoot == *pFocusRoot) { - if (CWnd* pUnder = CWnd::WindowFromPoint(msex.pt)) { - if (CWnd* pUnderRoot = pUnder->GetAncestor(GA_ROOT)) { - if (*pUnderRoot == *pFocusRoot && - GetCurrentThreadId() == GetWindowThreadProcessId(pUnder->m_hWnd, nullptr)) { - // prepare MSG struct - MSG msg = { - pUnder->m_hWnd, - wParam, - CMouse::GetMouseFlags() | msex.mouseData, - MAKELPARAM(msex.pt.x, msex.pt.y), - GetMessageTime(), - msex.pt - }; - - // walk through pre-translate - if (CWnd::WalkPreTranslateTree(pUnderRoot->m_hWnd, &msg)) { - // the message shouldn't be dispatched - return TRUE; - } - - // dispatch the message - if (msg.hwnd) { - DispatchMessage(&msg); - } + if (const CWnd* pFocus = CWnd::FromHandlePermanent(msex.hwnd)) { + if (const CWnd* pFocusRoot = pFocus->GetAncestor(GA_ROOT)) { + // only intercept messages to focused windows that have white-listed root windows + if (T::GetRoots().count(pFocusRoot)) { + if (const CWnd* pUnder = CWnd::WindowFromPoint(msex.pt)) { + if (pFocusRoot == pUnder->GetAncestor(GA_ROOT) && + GetCurrentThreadId() == GetWindowThreadProcessId(pUnder->m_hWnd, nullptr)) { + MSG msg = { + NULL, + static_cast<UINT>(wParam), + CMouse::GetMouseFlags() | msex.mouseData, + MAKELPARAM(msex.pt.x, msex.pt.y), + GetMessageTime(), + msex.pt + }; + + for (const CWnd* pTarget : { pUnder, pFocusRoot }) { + msg.hwnd = pTarget->m_hWnd; + if (!msg.hwnd) { + ASSERT(FALSE); + continue; + } + + // walk through pre-translate + if (CWnd::WalkPreTranslateTree(pFocusRoot->m_hWnd, &msg)) { + // the message shouldn't be dispatched + continue; + } + + if (DispatchMessage(&msg)) { + return TRUE; } } } - return TRUE; } } } @@ -218,8 +219,10 @@ class CMouseWheelHook public: CMouseWheelHook() { - m_hHook = SetWindowsHookEx(WH_MOUSE, MouseProc, nullptr, GetCurrentThreadId()); - ASSERT(m_hHook); + if (SysVersion::Is10OrLater()) { + m_hHook = SetWindowsHookEx(WH_MOUSE, MouseProc, nullptr, GetCurrentThreadId()); + ASSERT(m_hHook); + } } virtual ~CMouseWheelHook() { @@ -230,5 +233,5 @@ public: }; struct CMainFrameMouseHook : CMouseWheelHook<CMainFrameMouseHook> { - static std::vector<CWnd*> GetRoots(); + static std::unordered_set<const CWnd*> GetRoots(); }; |