From 1016e7f47ff525c5bb4fe1c0ad50725ffd06c628 Mon Sep 17 00:00:00 2001 From: Nemirtingas Date: Tue, 3 Sep 2019 17:24:34 +0200 Subject: [PATCH] Fix lag on events Found on sanctum2, returning 0 in XPending & XEventsQueued make the SDL do something else than polling events and makes lag the event loop. Now the event loop returns 0 when there are no more events. --- ImGui/impls/linux/imgui_impl_x11.cpp | 19 ++-- ImGui/impls/linux/imgui_impl_x11.h | 4 +- overlay_experimental/linux/X11_Hook.cpp | 123 ++++++++++++------------ overlay_experimental/linux/X11_Hook.h | 1 + 4 files changed, 78 insertions(+), 69 deletions(-) diff --git a/ImGui/impls/linux/imgui_impl_x11.cpp b/ImGui/impls/linux/imgui_impl_x11.cpp index 2268309..f5f3666 100644 --- a/ImGui/impls/linux/imgui_impl_x11.cpp +++ b/ImGui/impls/linux/imgui_impl_x11.cpp @@ -23,8 +23,9 @@ // X11 Data static Display* g_Display = nullptr; -static uint64_t g_Time = 0; -static uint64_t g_TicksPerSecond = 0; +static Window g_Window = 0; +static uint64_t g_Time = 0; +static uint64_t g_TicksPerSecond = 0; static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; static bool g_HasGamepad = false; static bool g_WantUpdateHasGamepad = true; @@ -56,7 +57,7 @@ bool IsKeySys(int key) } // Functions -bool ImGui_ImplX11_Init(void *display) +bool ImGui_ImplX11_Init(void *display, void *window) { timespec ts, tsres; clock_getres(CLOCK_MONOTONIC_RAW, &tsres); @@ -72,6 +73,7 @@ bool ImGui_ImplX11_Init(void *display) // Setup back-end capabilities flags g_Display = reinterpret_cast(display); + g_Window = reinterpret_cast(window); ImGuiIO& io = ImGui::GetIO(); io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) @@ -107,6 +109,7 @@ bool ImGui_ImplX11_Init(void *display) void ImGui_ImplX11_Shutdown() { g_Display = nullptr; + g_Window = 0; } static bool ImGui_ImplX11_UpdateMouseCursor() @@ -143,7 +146,7 @@ static bool ImGui_ImplX11_UpdateMouseCursor() return true; } -static void ImGui_ImplX11_UpdateMousePos(Window window) +static void ImGui_ImplX11_UpdateMousePos() { ImGuiIO& io = ImGui::GetIO(); @@ -160,7 +163,7 @@ static void ImGui_ImplX11_UpdateMousePos(Window window) int rx, ry, x, y; unsigned int mask; - XQueryPointer(g_Display, window, &unused_window, &unused_window, &rx, &ry, &x, &y, &mask); + XQueryPointer(g_Display, g_Window, &unused_window, &unused_window, &rx, &ry, &x, &y, &mask); io.MousePos.x = x; io.MousePos.y = y; @@ -215,7 +218,7 @@ static void ImGui_ImplX11_UpdateGamepads() */ } -void ImGui_ImplX11_NewFrame(void* window) +void ImGui_ImplX11_NewFrame() { ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); @@ -225,7 +228,7 @@ void ImGui_ImplX11_NewFrame(void* window) int unused_int; unsigned int unused_unsigned_int; - XGetGeometry(g_Display, (Window)window, &unused_window, &unused_int, &unused_int, &width, &height, &unused_unsigned_int, &unused_unsigned_int); + XGetGeometry(g_Display, (Window)g_Window, &unused_window, &unused_int, &unused_int, &width, &height, &unused_unsigned_int, &unused_unsigned_int); io.DisplaySize.x = width; io.DisplaySize.y = height; @@ -249,7 +252,7 @@ void ImGui_ImplX11_NewFrame(void* window) // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. // Update OS mouse position - ImGui_ImplX11_UpdateMousePos((Window)window); + ImGui_ImplX11_UpdateMousePos(); /* // Update OS mouse cursor with the cursor requested by imgui ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); diff --git a/ImGui/impls/linux/imgui_impl_x11.h b/ImGui/impls/linux/imgui_impl_x11.h index 2d05551..3022f05 100644 --- a/ImGui/impls/linux/imgui_impl_x11.h +++ b/ImGui/impls/linux/imgui_impl_x11.h @@ -9,9 +9,9 @@ #pragma once -IMGUI_IMPL_API bool ImGui_ImplX11_Init(void* display); +IMGUI_IMPL_API bool ImGui_ImplX11_Init(void* display, void* window); IMGUI_IMPL_API void ImGui_ImplX11_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplX11_NewFrame(void* window); +IMGUI_IMPL_API void ImGui_ImplX11_NewFrame(); // Handler for Win32 messages, update mouse/keyboard data. // You may or not need this for your implementation, but it can serve as reference for handling inputs. diff --git a/overlay_experimental/linux/X11_Hook.cpp b/overlay_experimental/linux/X11_Hook.cpp index 65d755d..f3dee1e 100644 --- a/overlay_experimental/linux/X11_Hook.cpp +++ b/overlay_experimental/linux/X11_Hook.cpp @@ -41,14 +41,14 @@ void X11_Hook::prepareForOverlay(Display *display, Window wnd) { if (!initialized) { - ImGui_ImplX11_Init(display); + ImGui_ImplX11_Init(display, (void*)wnd); game_wnd = wnd; initialized = true; } - ImGui_ImplX11_NewFrame((void*)wnd); + ImGui_ImplX11_NewFrame(); } ///////////////////////////////////////////////////////////////////////////////////// @@ -68,6 +68,65 @@ bool IgnoreEvent(XEvent &event) return false; } +int X11_Hook::check_for_overlay(Display *d, int num_events) +{ + static Time prev_time = {}; + + X11_Hook* inst = Inst(); + + if( inst->initialized ) + { + XEvent event; + while(num_events) + { + //inst->_XPeekEvent(d, &event); + XPeekEvent(d, &event); + + Steam_Overlay* overlay = get_steam_client()->steam_overlay; + bool show = overlay->ShowOverlay(); + // Is the event is a key press + if (event.type == KeyPress) + { + // Tab is pressed and was not pressed before + //if (event.xkey.keycode == inst->_XKeysymToKeycode(d, XK_Tab) && event.xkey.state & ShiftMask) + if (event.xkey.keycode == XKeysymToKeycode(d, XK_Tab) && event.xkey.state & ShiftMask) + { + // if key TAB is held, don't make the overlay flicker :p + if( event.xkey.time != prev_time) + { + overlay->ShowOverlay(!overlay->ShowOverlay()); + + if (overlay->ShowOverlay()) + show = true; + } + } + } + //else if(event.type == KeyRelease && event.xkey.keycode == inst->_XKeysymToKeycode(d, XK_Tab)) + else if(event.type == KeyRelease && event.xkey.keycode == XKeysymToKeycode(d, XK_Tab)) + { + prev_time = event.xkey.time; + } + + if (show) + { + ImGui_ImplX11_EventHandler(event); + + if (IgnoreEvent(event)) + { + //inst->_XNextEvent(d, &event); + XNextEvent(d, &event); + --num_events; + } + else + break; + } + else + break; + } + } + return num_events; +} + int X11_Hook::MyXEventsQueued(Display *display, int mode) { X11_Hook* inst = X11_Hook::Inst(); @@ -76,53 +135,9 @@ int X11_Hook::MyXEventsQueued(Display *display, int mode) if( res ) { - static Time prev_time = {}; - - XEvent event; - //inst->_XPeekEvent(display, &event); - XPeekEvent(display, &event); - - Steam_Overlay* overlay = get_steam_client()->steam_overlay; - bool show = overlay->ShowOverlay(); - // Is the event is a key press - if (event.type == KeyPress) - { - // Tab is pressed and was not pressed before - //if (event.xkey.keycode == inst->_XKeysymToKeycode(display, XK_Tab) && event.xkey.state & ShiftMask) - if (event.xkey.keycode == XKeysymToKeycode(display, XK_Tab) && event.xkey.state & ShiftMask) - { - // if key TAB is held, don't make the overlay flicker :p - if( event.xkey.time != prev_time) - { - overlay->ShowOverlay(!overlay->ShowOverlay()); - - if (overlay->ShowOverlay()) - show = true; - } - } - } - //else if(event.type == KeyRelease && event.xkey.keycode == inst->_XKeysymToKeycode(display, XK_Tab)) - else if(event.type == KeyRelease && event.xkey.keycode == XKeysymToKeycode(display, XK_Tab)) - { - prev_time = event.xkey.time; - } - - if (show) - { - ImGui_ImplX11_EventHandler(event); - - if (IgnoreEvent(event)) - { - //inst->_XNextEvent(display, &event); - XNextEvent(display, &event); - return 0; - } - } + res = inst->check_for_overlay(display, res); } - // XEventsQueued returns the num of events available. - // Usually, games tend to read all events queued before calling again XEventsQueued - // making us unavailable to intercept undesired events return res; } @@ -140,19 +155,9 @@ int X11_Hook::MyXPending(Display* display) { int res = Inst()->_XPending(display); - if( res && get_steam_client()->steam_overlay->ShowOverlay() ) + if( res ) { - XEvent event; - //Inst()->_XPeekEvent(display, &event); - XPeekEvent(display, &event); - if( IgnoreEvent(event) ) - { - ImGui_ImplX11_EventHandler(event); - - //Inst()->_XNextEvent(display, &event); - XNextEvent(display, &event); - res = 0; - } + res = Inst()->check_for_overlay(display, res); } return res; diff --git a/overlay_experimental/linux/X11_Hook.h b/overlay_experimental/linux/X11_Hook.h index 13161aa..5282466 100644 --- a/overlay_experimental/linux/X11_Hook.h +++ b/overlay_experimental/linux/X11_Hook.h @@ -24,6 +24,7 @@ private: // Functions X11_Hook(); + int check_for_overlay(Display *d, int num_events); // Hook to X11 window messages