Skip to content

Commit

Permalink
Store window events instead of handling them.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemirtingas committed Oct 13, 2024
1 parent 267d216 commit 9372aca
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 12 deletions.
33 changes: 21 additions & 12 deletions src/Windows/WindowsHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,39 +281,44 @@ static bool IgnoreMsg(UINT uMsg)
return false;
}

void WindowsHook_t::_AppendEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
_WindowEvents.enqueue(WindowsHookEvent_t(hWnd, uMsg, wParam, lParam));
}

void WindowsHook_t::_RawEvent(RAWINPUT& raw)
{
switch (raw.header.dwType)
{
case RIM_TYPEMOUSE:
if (raw.data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_LBUTTONDOWN, 0, 0);
_AppendEvent(_GameHwnd, WM_LBUTTONDOWN, 0, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_LBUTTONUP, 0, 0);
_AppendEvent(_GameHwnd, WM_LBUTTONUP, 0, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_RBUTTONDOWN, 0, 0);
_AppendEvent(_GameHwnd, WM_RBUTTONDOWN, 0, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_RBUTTONUP, 0, 0);
_AppendEvent(_GameHwnd, WM_RBUTTONUP, 0, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MBUTTONDOWN, 0, 0);
_AppendEvent(_GameHwnd, WM_MBUTTONDOWN, 0, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MBUTTONUP, 0, 0);
_AppendEvent(_GameHwnd, WM_MBUTTONUP, 0, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MOUSEWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
_AppendEvent(_GameHwnd, WM_MOUSEWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
if (raw.data.mouse.usButtonFlags & RI_MOUSE_HWHEEL)
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MOUSEHWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);
_AppendEvent(_GameHwnd, WM_MOUSEHWHEEL, ((WPARAM)raw.data.mouse.usButtonData) << 16, 0);

if (raw.data.mouse.lLastX != 0 || raw.data.mouse.lLastY != 0)
{
POINT p;
_GetCursorPos(&p);
::ScreenToClient(_GameHwnd, &p);
ImGui_ImplWin32_WndProcHandler(_GameHwnd, WM_MOUSEMOVE, 0, MAKELPARAM(p.x, p.y));
_AppendEvent(_GameHwnd, WM_MOUSEMOVE, 0, MAKELPARAM(p.x, p.y));
}
break;

//case RIM_TYPEKEYBOARD:
//ImGui_ImplWin32_WndProcHandler(_GameHwnd, raw.data.keyboard.Message, raw.data.keyboard.VKey, 0);
//_AppendEvent(_GameHwnd, raw.data.keyboard.Message, raw.data.keyboard.VKey, 0);
//break;
}
}
Expand Down Expand Up @@ -367,10 +372,13 @@ bool WindowsHook_t::_HandleEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
}

if (uMsg == WM_KILLFOCUS || uMsg == WM_SETFOCUS)
{
ImGui::GetIO().SetAppAcceptingEvents(uMsg == WM_SETFOCUS);
}

WindowsHookEvent_t rawEvent;
size_t eventCount = _WindowEvents.queue_size();
while (eventCount-- && _WindowEvents.dequeue(rawEvent))
ImGui_ImplWin32_WndProcHandler(rawEvent.hWnd, rawEvent.msg, rawEvent.wParam, rawEvent.lParam);

if (!hide_overlay_inputs || uMsg == WM_KILLFOCUS || uMsg == WM_SETFOCUS)
{
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
Expand Down Expand Up @@ -604,6 +612,7 @@ WindowsHook_t::WindowsHook_t() :
_ApplicationInputsHidden(false),
_OverlayInputsHidden(true),
_KeyCombinationPushed(false),
_WindowEvents(512),
_TranslateMessage(nullptr),
_DefWindowProcA(nullptr),
_DefWindowProcW(nullptr),
Expand Down
19 changes: 19 additions & 0 deletions src/Windows/WindowsHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,25 @@

#include "../RendererHookInternal.h"

#include "../mpmc_bounded_queue.h"

namespace InGameOverlay {

struct WindowsHookEvent_t
{
HWND hWnd;
UINT msg;
WPARAM wParam;
LPARAM lParam;

inline WindowsHookEvent_t()
{}

inline WindowsHookEvent_t(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) :
hWnd(hWnd), msg(msg), wParam(wParam), lParam(lParam)
{}
};

class WindowsHook_t :
public BaseHook_t
{
Expand All @@ -47,9 +64,11 @@ class WindowsHook_t :
std::function<void()> _KeyCombinationCallback;
std::vector<int> _NativeKeyCombination;
bool _KeyCombinationPushed;
mpmc_bounded_queue<WindowsHookEvent_t> _WindowEvents;

// Functions
WindowsHook_t();
void _AppendEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void _RawEvent(RAWINPUT& raw);
bool _HandleEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
decltype(::TranslateMessage)* _TranslateMessage;
Expand Down
125 changes: 125 additions & 0 deletions src/mpmc_bounded_queue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (C) Nemirtingas
* This file is part of the ingame overlay project
*
* The ingame overlay project is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* The ingame overlay project is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the ingame overlay project; if not, see
* <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <atomic>
#include <cassert>

template<typename T>
class mpmc_bounded_queue
{
public:
mpmc_bounded_queue(size_t buffer_size)
: buffer_(new cell_t[buffer_size])
, buffer_mask_(buffer_size - 1)
{
assert((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0));
for (size_t i = 0; i != buffer_size; i += 1)
buffer_[i].sequence_.store(i, std::memory_order_relaxed);
enqueue_pos_.store(0, std::memory_order_relaxed);
dequeue_pos_.store(0, std::memory_order_relaxed);
item_count_.store(0, std::memory_order_relaxed);
}

~mpmc_bounded_queue()
{
delete[] buffer_;
}

bool enqueue(T const& data)
{
cell_t* cell;
size_t pos = enqueue_pos_.load(std::memory_order_relaxed);

for (;;)
{
cell = &buffer_[pos & buffer_mask_];
size_t seq = cell->sequence_.load(std::memory_order_acquire);
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
if (dif == 0)
{
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
break;
}
else if (dif < 0)
return false;
else
pos = enqueue_pos_.load(std::memory_order_relaxed);
}
cell->data_ = data;
item_count_.fetch_sub(1, std::memory_order_relaxed);
cell->sequence_.store(pos + 1, std::memory_order_release);
return true;
}

bool dequeue(T& data)
{
cell_t* cell;
size_t pos = dequeue_pos_.load(std::memory_order_relaxed);

for (;;)
{
cell = &buffer_[pos & buffer_mask_];
size_t seq = cell->sequence_.load(std::memory_order_acquire);
intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
if (dif == 0)
{
if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
break;
}
else if (dif < 0)
return false;
else
pos = dequeue_pos_.load(std::memory_order_relaxed);
}
data = cell->data_;
item_count_.fetch_sub(1, std::memory_order_relaxed);
cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
return true;
}

size_t queue_size() const
{
return item_count_.load(std::memory_order_relaxed);
}

private:
struct cell_t
{
std::atomic<size_t> sequence_;
T data_;
};

static size_t const cacheline_size = 64;
typedef char cacheline_pad_t[cacheline_size];
cacheline_pad_t pad0_;
cell_t* const buffer_;
size_t const buffer_mask_;
cacheline_pad_t pad1_;
std::atomic<size_t> enqueue_pos_;
cacheline_pad_t pad2_;
std::atomic<size_t> dequeue_pos_;
cacheline_pad_t pad3_;
std::atomic<size_t> item_count_;
cacheline_pad_t pad4_;

mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
void operator=(mpmc_bounded_queue const&) = delete;
};

0 comments on commit 9372aca

Please sign in to comment.