Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Marsev <alex.marsev@gmail.com>2014-01-08 14:01:42 +0400
committerKacper Michajłow <kasper93@gmail.com>2015-09-24 22:31:32 +0300
commite5f6b2c79ce1a211b71fa713f686e7acf6422f37 (patch)
tree80519bdc81818d1c149bd382f9904ee1ba26d6fa
parent799e2712e652429374e7e8c14d0d3eb2e45bc178 (diff)
Mouse: send wheel messages to hovered windows
-rw-r--r--src/mpc-hc/MainFrm.h2
-rw-r--r--src/mpc-hc/MouseTouch.cpp14
-rw-r--r--src/mpc-hc/MouseTouch.h68
3 files changed, 84 insertions, 0 deletions
diff --git a/src/mpc-hc/MainFrm.h b/src/mpc-hc/MainFrm.h
index 4f7750936..fa3977749 100644
--- a/src/mpc-hc/MainFrm.h
+++ b/src/mpc-hc/MainFrm.h
@@ -188,6 +188,8 @@ private:
EventClient m_eventc;
void EventCallback(MpcEvent ev);
+ CMainFrameMouseHook m_mouseHook;
+
enum {
TIMER_STREAMPOSPOLLER = 1,
TIMER_STREAMPOSPOLLER2,
diff --git a/src/mpc-hc/MouseTouch.cpp b/src/mpc-hc/MouseTouch.cpp
index 1bb216088..39f1d8b8f 100644
--- a/src/mpc-hc/MouseTouch.cpp
+++ b/src/mpc-hc/MouseTouch.cpp
@@ -634,3 +634,17 @@ void CMouseWnd::OnDestroy()
CMouse::InternalOnDestroy();
CWnd::OnDestroy();
}
+
+std::vector<CWnd*> CMainFrameMouseHook::GetRoots()
+{
+ std::vector<CWnd*> ret;
+ ret.reserve(2);
+ CMainFrame* pMainFrame = AfxGetMainFrame();
+ if (pMainFrame) {
+ ret.emplace_back(pMainFrame);
+ if (pMainFrame->IsD3DFullScreenMode()) {
+ ret.emplace_back(pMainFrame->m_pFullscreenWnd);
+ }
+ }
+ return ret;
+}
diff --git a/src/mpc-hc/MouseTouch.h b/src/mpc-hc/MouseTouch.h
index 0651330ec..8e094fc2a 100644
--- a/src/mpc-hc/MouseTouch.h
+++ b/src/mpc-hc/MouseTouch.h
@@ -21,6 +21,7 @@
#pragma once
#include <map>
+#include <vector>
#include "EventDispatcher.h"
@@ -164,3 +165,70 @@ private:
return m_bD3DFS ? TABLET_DISABLE_PRESSANDHOLD : 0;
}
};
+
+template <class T>
+class CMouseWheelHook
+{
+ HHOOK m_hHook;
+
+ 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);
+ }
+ }
+ }
+ }
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ return CallNextHookEx(nullptr, nCode, wParam, lParam);
+ }
+
+public:
+ CMouseWheelHook() {
+ m_hHook = SetWindowsHookEx(WH_MOUSE, MouseProc, nullptr, GetCurrentThreadId());
+ ASSERT(m_hHook);
+ }
+
+ virtual ~CMouseWheelHook() {
+ if (m_hHook) {
+ VERIFY(UnhookWindowsHookEx(m_hHook));
+ }
+ }
+};
+
+struct CMainFrameMouseHook : CMouseWheelHook<CMainFrameMouseHook> {
+ static std::vector<CWnd*> GetRoots();
+};