Skip to content

Commit d6b3ff3

Browse files
authored
Store window events instead of handling them. (#43)
1 parent 267d216 commit d6b3ff3

File tree

3 files changed

+165
-12
lines changed

3 files changed

+165
-12
lines changed

src/Windows/WindowsHook.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -281,39 +281,44 @@ static bool IgnoreMsg(UINT uMsg)
281281
return false;
282282
}
283283

284+
void WindowsHook_t::_AppendEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
285+
{
286+
_WindowEvents.enqueue(WindowsHookEvent_t(hWnd, uMsg, wParam, lParam));
287+
}
288+
284289
void WindowsHook_t::_RawEvent(RAWINPUT& raw)
285290
{
286291
switch (raw.header.dwType)
287292
{
288293
case RIM_TYPEMOUSE:
289294
if (raw.data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
290-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_LBUTTONDOWN, 0, 0);
295+
_AppendEvent(_GameHwnd, WM_LBUTTONDOWN, 0, 0);
291296
if (raw.data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP)
292-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_LBUTTONUP, 0, 0);
297+
_AppendEvent(_GameHwnd, WM_LBUTTONUP, 0, 0);
293298
if (raw.data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
294-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_RBUTTONDOWN, 0, 0);
299+
_AppendEvent(_GameHwnd, WM_RBUTTONDOWN, 0, 0);
295300
if (raw.data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
296-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_RBUTTONUP, 0, 0);
301+
_AppendEvent(_GameHwnd, WM_RBUTTONUP, 0, 0);
297302
if (raw.data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
298-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MBUTTONDOWN, 0, 0);
303+
_AppendEvent(_GameHwnd, WM_MBUTTONDOWN, 0, 0);
299304
if (raw.data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
300-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MBUTTONUP, 0, 0);
305+
_AppendEvent(_GameHwnd, WM_MBUTTONUP, 0, 0);
301306
if (raw.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
302-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MOUSEWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
307+
_AppendEvent(_GameHwnd, WM_MOUSEWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
303308
if (raw.data.mouse.usButtonFlags & RI_MOUSE_HWHEEL)
304-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MOUSEHWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
309+
_AppendEvent(_GameHwnd, WM_MOUSEHWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
305310

306311
if (raw.data.mouse.lLastX != 0 || raw.data.mouse.lLastY != 0)
307312
{
308313
POINT p;
309314
_GetCursorPos(&p);
310315
::ScreenToClient(_GameHwnd, &p);
311-
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MOUSEMOVE, 0, MAKELPARAM(p.x, p.y));
316+
_AppendEvent(_GameHwnd, WM_MOUSEMOVE, 0, MAKELPARAM(p.x, p.y));
312317
}
313318
break;
314319

315320
//case RIM_TYPEKEYBOARD:
316-
//ImGui_ImplWin32_WndProcHandler(_GameHwnd, raw.data.keyboard.Message, raw.data.keyboard.VKey, 0);
321+
//_AppendEvent(_GameHwnd, raw.data.keyboard.Message, raw.data.keyboard.VKey, 0);
317322
//break;
318323
}
319324
}
@@ -367,10 +372,13 @@ bool WindowsHook_t::_HandleEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
367372
}
368373

369374
if (uMsg == WM_KILLFOCUS || uMsg == WM_SETFOCUS)
370-
{
371375
ImGui::GetIO().SetAppAcceptingEvents(uMsg == WM_SETFOCUS);
372-
}
373376

377+
WindowsHookEvent_t rawEvent;
378+
size_t eventCount = _WindowEvents.queue_size();
379+
while (eventCount-- && _WindowEvents.dequeue(rawEvent))
380+
ImGui_ImplWin32_WndProcHandler(rawEvent.hWnd, rawEvent.msg, rawEvent.wParam, rawEvent.lParam);
381+
374382
if (!hide_overlay_inputs || uMsg == WM_KILLFOCUS || uMsg == WM_SETFOCUS)
375383
{
376384
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
@@ -604,6 +612,7 @@ WindowsHook_t::WindowsHook_t() :
604612
_ApplicationInputsHidden(false),
605613
_OverlayInputsHidden(true),
606614
_KeyCombinationPushed(false),
615+
_WindowEvents(512),
607616
_TranslateMessage(nullptr),
608617
_DefWindowProcA(nullptr),
609618
_DefWindowProcW(nullptr),

src/Windows/WindowsHook.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,25 @@
2121

2222
#include "../RendererHookInternal.h"
2323

24+
#include "../mpmc_bounded_queue.h"
25+
2426
namespace InGameOverlay {
2527

28+
struct WindowsHookEvent_t
29+
{
30+
HWND hWnd;
31+
UINT msg;
32+
WPARAM wParam;
33+
LPARAM lParam;
34+
35+
inline WindowsHookEvent_t()
36+
{}
37+
38+
inline WindowsHookEvent_t(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) :
39+
hWnd(hWnd), msg(msg), wParam(wParam), lParam(lParam)
40+
{}
41+
};
42+
2643
class WindowsHook_t :
2744
public BaseHook_t
2845
{
@@ -47,9 +64,11 @@ class WindowsHook_t :
4764
std::function<void()> _KeyCombinationCallback;
4865
std::vector<int> _NativeKeyCombination;
4966
bool _KeyCombinationPushed;
67+
mpmc_bounded_queue<WindowsHookEvent_t> _WindowEvents;
5068

5169
// Functions
5270
WindowsHook_t();
71+
void _AppendEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
5372
void _RawEvent(RAWINPUT& raw);
5473
bool _HandleEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
5574
decltype(::TranslateMessage)* _TranslateMessage;

src/mpmc_bounded_queue.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (C) Nemirtingas
3+
* This file is part of the ingame overlay project
4+
*
5+
* The ingame overlay project is free software; you can redistribute it
6+
* and/or modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* The ingame overlay project is distributed in the hope that it will be
11+
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with the ingame overlay project; if not, see
17+
* <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#pragma once
21+
22+
#include <atomic>
23+
#include <cassert>
24+
25+
template<typename T>
26+
class mpmc_bounded_queue
27+
{
28+
public:
29+
mpmc_bounded_queue(size_t buffer_size)
30+
: buffer_(new cell_t[buffer_size])
31+
, buffer_mask_(buffer_size - 1)
32+
{
33+
assert((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0));
34+
for (size_t i = 0; i != buffer_size; i += 1)
35+
buffer_[i].sequence_.store(i, std::memory_order_relaxed);
36+
enqueue_pos_.store(0, std::memory_order_relaxed);
37+
dequeue_pos_.store(0, std::memory_order_relaxed);
38+
item_count_.store(0, std::memory_order_relaxed);
39+
}
40+
41+
~mpmc_bounded_queue()
42+
{
43+
delete[] buffer_;
44+
}
45+
46+
bool enqueue(T const& data)
47+
{
48+
cell_t* cell;
49+
size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
50+
51+
for (;;)
52+
{
53+
cell = &buffer_[pos & buffer_mask_];
54+
size_t seq = cell->sequence_.load(std::memory_order_acquire);
55+
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
56+
if (dif == 0)
57+
{
58+
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
59+
break;
60+
}
61+
else if (dif < 0)
62+
return false;
63+
else
64+
pos = enqueue_pos_.load(std::memory_order_relaxed);
65+
}
66+
cell->data_ = data;
67+
item_count_.fetch_sub(1, std::memory_order_relaxed);
68+
cell->sequence_.store(pos + 1, std::memory_order_release);
69+
return true;
70+
}
71+
72+
bool dequeue(T& data)
73+
{
74+
cell_t* cell;
75+
size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
76+
77+
for (;;)
78+
{
79+
cell = &buffer_[pos & buffer_mask_];
80+
size_t seq = cell->sequence_.load(std::memory_order_acquire);
81+
intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
82+
if (dif == 0)
83+
{
84+
if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
85+
break;
86+
}
87+
else if (dif < 0)
88+
return false;
89+
else
90+
pos = dequeue_pos_.load(std::memory_order_relaxed);
91+
}
92+
data = cell->data_;
93+
item_count_.fetch_sub(1, std::memory_order_relaxed);
94+
cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
95+
return true;
96+
}
97+
98+
size_t queue_size() const
99+
{
100+
return item_count_.load(std::memory_order_relaxed);
101+
}
102+
103+
private:
104+
struct cell_t
105+
{
106+
std::atomic<size_t> sequence_;
107+
T data_;
108+
};
109+
110+
static size_t const cacheline_size = 64;
111+
typedef char cacheline_pad_t[cacheline_size];
112+
cacheline_pad_t pad0_;
113+
cell_t* const buffer_;
114+
size_t const buffer_mask_;
115+
cacheline_pad_t pad1_;
116+
std::atomic<size_t> enqueue_pos_;
117+
cacheline_pad_t pad2_;
118+
std::atomic<size_t> dequeue_pos_;
119+
cacheline_pad_t pad3_;
120+
std::atomic<size_t> item_count_;
121+
cacheline_pad_t pad4_;
122+
123+
mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
124+
void operator=(mpmc_bounded_queue const&) = delete;
125+
};

0 commit comments

Comments
 (0)