mirror of
https://gitlab.com/Mr_Goldberg/goldberg_emulator.git
synced 2024-11-14 10:50:13 +01:00
Updated Linux X11 & OLGX hooks.
Use LD_PRELOAD=$PWD/libsteam_api.so app_name to load overlay.
This commit is contained in:
parent
d6f29ffffa
commit
ecd753422b
5 changed files with 232 additions and 139 deletions
|
@ -509,7 +509,13 @@ void Renderer_Detector::find_renderer_proc(Renderer_Detector* _this)
|
||||||
Hook_Manager& hm = Hook_Manager::Inst();
|
Hook_Manager& hm = Hook_Manager::Inst();
|
||||||
hm.AddHook(_this->rendererdetect_hook);
|
hm.AddHook(_this->rendererdetect_hook);
|
||||||
|
|
||||||
std::vector<std::string> const libraries = { "opengl32.dll", "d3d12.dll", "d3d11.dll", "d3d10.dll", "d3d9.dll" };
|
std::vector<std::string> const libraries = {
|
||||||
|
OpenGL_Hook::DLL_NAME,
|
||||||
|
DX12_Hook::DLL_NAME,
|
||||||
|
DX11_Hook::DLL_NAME,
|
||||||
|
DX10_Hook::DLL_NAME,
|
||||||
|
DX9_Hook::DLL_NAME
|
||||||
|
};
|
||||||
|
|
||||||
while (!_this->_renderer_found && !_this->stop_retry())
|
while (!_this->_renderer_found && !_this->stop_retry())
|
||||||
{
|
{
|
||||||
|
@ -615,8 +621,12 @@ Renderer_Detector::Renderer_Detector():
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
static decltype(glXSwapBuffers)* _glXSwapBuffers = nullptr;
|
extern "C" void *_dl_sym(void *, const char *, void *);
|
||||||
|
|
||||||
|
static decltype(glXGetProcAddress)* real_glXGetProcAddress = nullptr;
|
||||||
|
static decltype(glXGetProcAddressARB)* real_glXGetProcAddressARB = nullptr;
|
||||||
|
|
||||||
|
/*
|
||||||
void Renderer_Detector::MyglXSwapBuffers(Display *dpy, GLXDrawable drawable)
|
void Renderer_Detector::MyglXSwapBuffers(Display *dpy, GLXDrawable drawable)
|
||||||
{
|
{
|
||||||
Renderer_Detector& inst = Renderer_Detector::Inst();
|
Renderer_Detector& inst = Renderer_Detector::Inst();
|
||||||
|
@ -653,7 +663,7 @@ void Renderer_Detector::hook_openglx(const char* libname)
|
||||||
}
|
}
|
||||||
if (glXSwapBuffers != nullptr)
|
if (glXSwapBuffers != nullptr)
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("Hooked glXMakeCurrent to detect OpenGLX\n");
|
PRINT_DEBUG("Hooked glXSwapBuffers to detect OpenGLX\n");
|
||||||
|
|
||||||
_oglx_hooked = true;
|
_oglx_hooked = true;
|
||||||
auto h = OpenGLX_Hook::Inst();
|
auto h = OpenGLX_Hook::Inst();
|
||||||
|
@ -663,7 +673,7 @@ void Renderer_Detector::hook_openglx(const char* libname)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("Failed to Hook glXMakeCurrent to detect OpenGLX\n");
|
PRINT_DEBUG("Failed to Hook glXSwapBuffers to detect OpenGLX\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,54 +683,15 @@ void Renderer_Detector::create_hook(const char* libname)
|
||||||
if (strcasestr(libname, OpenGLX_Hook::DLL_NAME) != nullptr)
|
if (strcasestr(libname, OpenGLX_Hook::DLL_NAME) != nullptr)
|
||||||
hook_openglx(libname);
|
hook_openglx(libname);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void Renderer_Detector::find_renderer_proc(Renderer_Detector* _this)
|
void Renderer_Detector::find_renderer_proc(Renderer_Detector* _this)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
_this->rendererdetect_hook = new Base_Hook();
|
_this->rendererdetect_hook = new Base_Hook();
|
||||||
Hook_Manager& hm = Hook_Manager::Inst();
|
Hook_Manager& hm = Hook_Manager::Inst();
|
||||||
hm.AddHook(_this->rendererdetect_hook);
|
hm.AddHook(_this->rendererdetect_hook);
|
||||||
|
*/
|
||||||
|
|
||||||
std::vector<std::string> const libraries = { "libGLX.so" };
|
|
||||||
|
|
||||||
while (!_this->_renderer_found && !_this->stop_retry())
|
|
||||||
{
|
|
||||||
std::ifstream flibrary("/proc/self/maps");
|
|
||||||
std::string line;
|
|
||||||
while( std::getline(flibrary, line) )
|
|
||||||
{
|
|
||||||
std::for_each(libraries.begin(), libraries.end(), [&line, &_this]( std::string const& library )
|
|
||||||
{
|
|
||||||
if( std::search(line.begin(), line.end(), library.begin(), library.end()) != line.end() )
|
|
||||||
{
|
|
||||||
_this->create_hook(line.substr(line.find('/')).c_str());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this->game_renderer == nullptr) // Couldn't hook renderer
|
|
||||||
{
|
|
||||||
hm.RemoveHook(X11_Hook::Inst());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hm.AddHook(X11_Hook::Inst());
|
|
||||||
}
|
|
||||||
if (_this->_oglx_hooked)
|
|
||||||
{
|
|
||||||
auto h = OpenGLX_Hook::Inst();
|
|
||||||
if (h != _this->game_renderer)
|
|
||||||
{
|
|
||||||
_this->_oglx_hooked = false;
|
|
||||||
hm.RemoveHook(h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete _this->_hook_thread;
|
|
||||||
_this->_hook_thread = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer_Detector::Renderer_Detector():
|
Renderer_Detector::Renderer_Detector():
|
||||||
|
@ -732,6 +703,123 @@ Renderer_Detector::Renderer_Detector():
|
||||||
game_renderer(nullptr)
|
game_renderer(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
static decltype(dlsym)* real_dlsym = nullptr;
|
||||||
|
|
||||||
|
// hook library static loading
|
||||||
|
extern "C" int XEventsQueued(Display *display, int mode)
|
||||||
|
{
|
||||||
|
auto h = X11_Hook::Inst();
|
||||||
|
if( h->get_XEventsQueued() == nullptr )
|
||||||
|
h->loadXEventsQueued((decltype(XEventsQueued)*)real_dlsym(RTLD_NEXT, "XEventsQueued"));
|
||||||
|
|
||||||
|
return X11_Hook::MyXEventsQueued(display, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//extern "C" int XPeekEvent(Display *display, XEvent *event)
|
||||||
|
//{
|
||||||
|
// auto h = X11_Hook::Inst();
|
||||||
|
// if( h->get_XPeekEvent() == nullptr )
|
||||||
|
// h->loadXPeekEvent((decltype(XPeekEvent)*)real_dlsym(RTLD_NEXT, "XPeekEvent"));
|
||||||
|
//
|
||||||
|
// return X11_Hook::MyXPeekEvent(display, event);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//extern "C" int XNextEvent(Display *display, XEvent *event)
|
||||||
|
//{
|
||||||
|
// auto h = X11_Hook::Inst();
|
||||||
|
// if( h->get_XNextEvent() == nullptr )
|
||||||
|
// h->loadXNextEvent((decltype(XNextEvent)*)real_dlsym(RTLD_NEXT, "XNextEvent"));
|
||||||
|
//
|
||||||
|
// return X11_Hook::MyXNextEvent(display, event);
|
||||||
|
//}
|
||||||
|
|
||||||
|
extern "C" int XPending(Display *display)
|
||||||
|
{
|
||||||
|
auto h = X11_Hook::Inst();
|
||||||
|
if( h->get_XPending() == nullptr )
|
||||||
|
h->loadXPending((decltype(XPending)*)real_dlsym(RTLD_NEXT, "XPending"));
|
||||||
|
|
||||||
|
return X11_Hook::MyXPending(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void glXSwapBuffers(Display *display, GLXDrawable drawable)
|
||||||
|
{
|
||||||
|
OpenGLX_Hook::Inst()->start_hook();
|
||||||
|
OpenGLX_Hook::MyglXSwapBuffers(display, drawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __GLXextFuncPtr glXGetProcAddress(const GLubyte * procName)
|
||||||
|
{
|
||||||
|
if( strcmp((const char*)procName, "glXSwapBuffers") == 0 )
|
||||||
|
{
|
||||||
|
decltype(glXSwapBuffers)* real_glXSwapBuffers = (decltype(real_glXSwapBuffers))real_glXGetProcAddress(procName);
|
||||||
|
OpenGLX_Hook::Inst()->loadFunctions(real_glXSwapBuffers);
|
||||||
|
return (__GLXextFuncPtr)glXSwapBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
__GLXextFuncPtr func = (__GLXextFuncPtr)real_glXGetProcAddress(procName);
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __GLXextFuncPtr glXGetProcAddressARB (const GLubyte* procName)
|
||||||
|
{
|
||||||
|
if( strcmp((const char*)procName, "glXSwapBuffers") == 0 )
|
||||||
|
{
|
||||||
|
decltype(glXSwapBuffers)* real_glXSwapBuffers = (decltype(real_glXSwapBuffers))real_glXGetProcAddressARB(procName);
|
||||||
|
OpenGLX_Hook::Inst()->loadFunctions(real_glXSwapBuffers);
|
||||||
|
return (__GLXextFuncPtr)glXSwapBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
__GLXextFuncPtr func = (__GLXextFuncPtr)real_glXGetProcAddressARB(procName);
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* dlsym(void* handle, const char* name)
|
||||||
|
{
|
||||||
|
if (real_dlsym == nullptr)
|
||||||
|
real_dlsym = (decltype(dlsym)*)_dl_sym(RTLD_NEXT, "dlsym", reinterpret_cast<void*>(dlsym));
|
||||||
|
|
||||||
|
if ( strcmp(name,"dlsym") == 0 )
|
||||||
|
return (void*)dlsym;
|
||||||
|
|
||||||
|
if( strcmp(name, "glXGetProcAddress") == 0 )
|
||||||
|
{
|
||||||
|
if( real_glXGetProcAddress == nullptr )
|
||||||
|
{
|
||||||
|
real_glXGetProcAddress = (decltype(glXGetProcAddress)*)real_dlsym(RTLD_NEXT, "glXGetProcAddress");
|
||||||
|
}
|
||||||
|
return (void*)glXGetProcAddress;
|
||||||
|
}
|
||||||
|
if( strcmp(name, "glXGetProcAddressARB") == 0 )
|
||||||
|
{
|
||||||
|
if( real_glXGetProcAddressARB == nullptr )
|
||||||
|
{
|
||||||
|
real_glXGetProcAddressARB = (decltype(glXGetProcAddressARB)*)real_dlsym(RTLD_NEXT, "glXGetProcAddressARB");
|
||||||
|
}
|
||||||
|
return (void*)glXGetProcAddressARB;
|
||||||
|
}
|
||||||
|
if( strcmp(name, "XEventsQueued") == 0 )
|
||||||
|
{
|
||||||
|
return (void*)XEventsQueued;
|
||||||
|
}
|
||||||
|
//if( strcmp(name, "XNextEvent") == 0 )
|
||||||
|
//{
|
||||||
|
// return (void*)XNextEvent;
|
||||||
|
//}
|
||||||
|
//if( strcmp(name, "XPeekEvent") == 0 )
|
||||||
|
//{
|
||||||
|
// return (void*)XPeekEvent;
|
||||||
|
//}
|
||||||
|
if( strcmp(name, "XPending") == 0 )
|
||||||
|
{
|
||||||
|
return (void*)XPending;
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_dlsym(handle,name);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Renderer_Detector::renderer_found(Base_Hook* hook)
|
void Renderer_Detector::renderer_found(Base_Hook* hook)
|
||||||
|
|
|
@ -30,12 +30,14 @@ bool OpenGLX_Hook::start_hook()
|
||||||
hooked = true;
|
hooked = true;
|
||||||
Renderer_Detector::Inst().renderer_found(this);
|
Renderer_Detector::Inst().renderer_found(this);
|
||||||
|
|
||||||
|
/*
|
||||||
UnhookAll();
|
UnhookAll();
|
||||||
BeginHook();
|
BeginHook();
|
||||||
HookFuncs(
|
HookFuncs(
|
||||||
std::make_pair<void**, void*>(&(void*&)_glXSwapBuffers, (void*)&OpenGLX_Hook::MyglXSwapBuffers)
|
std::make_pair<void**, void*>(&(void*&)_glXSwapBuffers, (void*)&OpenGLX_Hook::MyglXSwapBuffers)
|
||||||
);
|
);
|
||||||
EndHook();
|
EndHook();
|
||||||
|
*/
|
||||||
|
|
||||||
get_steam_client()->steam_overlay->HookReady();
|
get_steam_client()->steam_overlay->HookReady();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +57,7 @@ void OpenGLX_Hook::resetRenderState()
|
||||||
if (initialized)
|
if (initialized)
|
||||||
{
|
{
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
//X11_Hook::Inst()->resetRenderState();
|
X11_Hook::Inst()->resetRenderState();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
@ -63,10 +65,13 @@ void OpenGLX_Hook::resetRenderState()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to make this function and overlay's proc as short as possible or it might affect game's fps.
|
// Try to make this function and overlay's proc as short as possible or it might affect game's fps.
|
||||||
void OpenGLX_Hook::prepareForOverlay(Display* display)
|
void OpenGLX_Hook::prepareForOverlay(Display* display, GLXDrawable drawable)
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("Called SwapBuffer hook");
|
PRINT_DEBUG("Called SwapBuffer hook");
|
||||||
|
|
||||||
|
if( (Window)drawable != X11_Hook::Inst()->get_game_wnd() )
|
||||||
|
resetRenderState();
|
||||||
|
|
||||||
if( ! initialized )
|
if( ! initialized )
|
||||||
{
|
{
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
|
@ -81,17 +86,12 @@ void OpenGLX_Hook::prepareForOverlay(Display* display)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
GLint m_viewport[4];
|
|
||||||
glGetIntegerv( GL_VIEWPORT, m_viewport );
|
|
||||||
int width = m_viewport[2];
|
|
||||||
int height = m_viewport[3];
|
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
X11_Hook::Inst()->prepareForOverlay(display);
|
X11_Hook::Inst()->prepareForOverlay(display, (Window)drawable);
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
get_steam_client()->steam_overlay->OverlayProc(width, height);
|
get_steam_client()->steam_overlay->OverlayProc(io.DisplaySize.x, io.DisplaySize.y);
|
||||||
|
|
||||||
ImGui::EndFrame();
|
ImGui::EndFrame();
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ void OpenGLX_Hook::prepareForOverlay(Display* display)
|
||||||
|
|
||||||
void OpenGLX_Hook::MyglXSwapBuffers(Display* display, GLXDrawable drawable)
|
void OpenGLX_Hook::MyglXSwapBuffers(Display* display, GLXDrawable drawable)
|
||||||
{
|
{
|
||||||
OpenGLX_Hook::Inst()->prepareForOverlay(display);
|
OpenGLX_Hook::Inst()->prepareForOverlay(display, drawable);
|
||||||
OpenGLX_Hook::Inst()->_glXSwapBuffers(display, drawable);
|
OpenGLX_Hook::Inst()->_glXSwapBuffers(display, drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,16 @@ private:
|
||||||
OpenGLX_Hook();
|
OpenGLX_Hook();
|
||||||
|
|
||||||
void resetRenderState();
|
void resetRenderState();
|
||||||
void prepareForOverlay(Display* display);
|
void prepareForOverlay(Display* display, GLXDrawable drawable);
|
||||||
|
|
||||||
// Hook to render functions
|
// Hook to render functions
|
||||||
static void MyglXSwapBuffers(Display* display, GLXDrawable drawable);
|
|
||||||
|
|
||||||
decltype(glXSwapBuffers)* _glXSwapBuffers;
|
decltype(glXSwapBuffers)* _glXSwapBuffers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static void MyglXSwapBuffers(Display* display, GLXDrawable drawable);
|
||||||
|
|
||||||
virtual ~OpenGLX_Hook();
|
virtual ~OpenGLX_Hook();
|
||||||
|
|
||||||
bool start_hook();
|
bool start_hook();
|
||||||
|
|
|
@ -21,44 +21,8 @@ bool X11_Hook::start_hook()
|
||||||
bool res = true;
|
bool res = true;
|
||||||
if (!hooked)
|
if (!hooked)
|
||||||
{
|
{
|
||||||
res = false;
|
PRINT_DEBUG("Hooked X11\n");
|
||||||
std::ifstream flibrary("/proc/self/maps");
|
hooked = true;
|
||||||
std::string line;
|
|
||||||
while( std::getline(flibrary, line) )
|
|
||||||
{
|
|
||||||
if( strcasestr(line.c_str(), DLL_NAME) != nullptr )
|
|
||||||
{
|
|
||||||
_library = dlopen(line.substr(line.find('/')).c_str(), RTLD_NOW);
|
|
||||||
|
|
||||||
if( _library != nullptr )
|
|
||||||
{
|
|
||||||
// Hook only this
|
|
||||||
_XEventsQueued = (decltype(_XEventsQueued))dlsym(_library, "XEventsQueued");
|
|
||||||
// Thoses are needed to ignore some events when overlay is on
|
|
||||||
_XPeekEvent = (decltype(_XPeekEvent))dlsym(_library, "XPeekEvent");
|
|
||||||
_XNextEvent = (decltype(_XNextEvent))dlsym(_library, "XNextEvent");
|
|
||||||
_XKeysymToKeycode = (decltype(_XKeysymToKeycode))dlsym(_library, "XKeysymToKeycode");
|
|
||||||
_XLookupKeysym = (decltype(_XLookupKeysym))dlsym(_library, "XLookupKeysym");
|
|
||||||
|
|
||||||
if( _XEventsQueued != nullptr && _XPeekEvent != nullptr
|
|
||||||
&& _XNextEvent != nullptr && _XKeysymToKeycode != nullptr
|
|
||||||
&& _XLookupKeysym != nullptr )
|
|
||||||
{
|
|
||||||
PRINT_DEBUG("Hooked X11\n");
|
|
||||||
hooked = true;
|
|
||||||
|
|
||||||
BeginHook();
|
|
||||||
HookFuncs(
|
|
||||||
std::make_pair<void**, void*>(&(void*&)_XEventsQueued, (void*)&X11_Hook::MyXEventsQueued)
|
|
||||||
);
|
|
||||||
|
|
||||||
EndHook();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dlclose(_library);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -67,44 +31,24 @@ void X11_Hook::resetRenderState()
|
||||||
{
|
{
|
||||||
if (initialized)
|
if (initialized)
|
||||||
{
|
{
|
||||||
|
game_wnd = 0;
|
||||||
initialized = false;
|
initialized = false;
|
||||||
ImGui_ImplX11_Shutdown();
|
ImGui_ImplX11_Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11_Hook::prepareForOverlay(Display *display)
|
void X11_Hook::prepareForOverlay(Display *display, Window wnd)
|
||||||
{
|
{
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
{
|
{
|
||||||
ImGui_ImplX11_Init(display);
|
ImGui_ImplX11_Init(display);
|
||||||
|
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
game_wnd = wnd;
|
||||||
io.KeyMap[ImGuiKey_Tab] = _XKeysymToKeycode(display, XK_Tab);
|
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = _XKeysymToKeycode(display, XK_Left);
|
|
||||||
io.KeyMap[ImGuiKey_RightArrow] = _XKeysymToKeycode(display, XK_Right);
|
|
||||||
io.KeyMap[ImGuiKey_UpArrow] = _XKeysymToKeycode(display, XK_Up);
|
|
||||||
io.KeyMap[ImGuiKey_DownArrow] = _XKeysymToKeycode(display, XK_Down);
|
|
||||||
io.KeyMap[ImGuiKey_PageUp] = _XKeysymToKeycode(display, XK_Prior);
|
|
||||||
io.KeyMap[ImGuiKey_PageDown] = _XKeysymToKeycode(display, XK_Next);
|
|
||||||
io.KeyMap[ImGuiKey_Home] = _XKeysymToKeycode(display, XK_Home);
|
|
||||||
io.KeyMap[ImGuiKey_End] = _XKeysymToKeycode(display, XK_End);
|
|
||||||
io.KeyMap[ImGuiKey_Insert] = _XKeysymToKeycode(display, XK_Insert);
|
|
||||||
io.KeyMap[ImGuiKey_Delete] = _XKeysymToKeycode(display, XK_Delete);
|
|
||||||
io.KeyMap[ImGuiKey_Backspace] = _XKeysymToKeycode(display, XK_BackSpace);
|
|
||||||
io.KeyMap[ImGuiKey_Space] = _XKeysymToKeycode(display, XK_space);
|
|
||||||
io.KeyMap[ImGuiKey_Enter] = _XKeysymToKeycode(display, XK_Return);
|
|
||||||
io.KeyMap[ImGuiKey_Escape] = _XKeysymToKeycode(display, XK_Escape);
|
|
||||||
io.KeyMap[ImGuiKey_A] = _XKeysymToKeycode(display, XK_A);
|
|
||||||
io.KeyMap[ImGuiKey_C] = _XKeysymToKeycode(display, XK_C);
|
|
||||||
io.KeyMap[ImGuiKey_V] = _XKeysymToKeycode(display, XK_V);
|
|
||||||
io.KeyMap[ImGuiKey_X] = _XKeysymToKeycode(display, XK_X);
|
|
||||||
io.KeyMap[ImGuiKey_Y] = _XKeysymToKeycode(display, XK_Y);
|
|
||||||
io.KeyMap[ImGuiKey_Z] = _XKeysymToKeycode(display, XK_Z);
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui_ImplX11_NewFrame();
|
ImGui_ImplX11_NewFrame((void*)wnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -126,28 +70,28 @@ bool IgnoreEvent(XEvent &event)
|
||||||
|
|
||||||
int X11_Hook::MyXEventsQueued(Display *display, int mode)
|
int X11_Hook::MyXEventsQueued(Display *display, int mode)
|
||||||
{
|
{
|
||||||
static Time prev_time = {};
|
|
||||||
X11_Hook* inst = X11_Hook::Inst();
|
X11_Hook* inst = X11_Hook::Inst();
|
||||||
XEvent event = {};
|
|
||||||
|
|
||||||
int res = inst->_XEventsQueued(display, mode);
|
int res = inst->_XEventsQueued(display, mode);
|
||||||
|
|
||||||
if( res > 0 )
|
if( res )
|
||||||
{
|
{
|
||||||
/// The XPeekEvent function returns the first event from the event queue,
|
static Time prev_time = {};
|
||||||
/// but it does not remove the event from the queue. If the queue is
|
|
||||||
/// empty, XPeekEvent flushes the output buffer and blocks until an event
|
XEvent event;
|
||||||
/// is received.
|
//inst->_XPeekEvent(display, &event);
|
||||||
inst->_XPeekEvent(display, &event);
|
XPeekEvent(display, &event);
|
||||||
|
|
||||||
Steam_Overlay* overlay = get_steam_client()->steam_overlay;
|
Steam_Overlay* overlay = get_steam_client()->steam_overlay;
|
||||||
bool show = overlay->ShowOverlay();
|
bool show = overlay->ShowOverlay();
|
||||||
// Is the event is a key press
|
// Is the event is a key press
|
||||||
if (event.type == KeyPress)
|
if (event.type == KeyPress)
|
||||||
{
|
{
|
||||||
// Tab is pressed and was not pressed before
|
// 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 == 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 help, don't make the overlay flicker :p
|
// if key TAB is held, don't make the overlay flicker :p
|
||||||
if( event.xkey.time != prev_time)
|
if( event.xkey.time != prev_time)
|
||||||
{
|
{
|
||||||
overlay->ShowOverlay(!overlay->ShowOverlay());
|
overlay->ShowOverlay(!overlay->ShowOverlay());
|
||||||
|
@ -157,7 +101,8 @@ int X11_Hook::MyXEventsQueued(Display *display, int mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(event.type == KeyRelease && event.xkey.keycode == inst->_XKeysymToKeycode(display, XK_Tab))
|
//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;
|
prev_time = event.xkey.time;
|
||||||
}
|
}
|
||||||
|
@ -168,22 +113,61 @@ int X11_Hook::MyXEventsQueued(Display *display, int mode)
|
||||||
|
|
||||||
if (IgnoreEvent(event))
|
if (IgnoreEvent(event))
|
||||||
{
|
{
|
||||||
inst->_XNextEvent(display, &event);
|
//inst->_XNextEvent(display, &event);
|
||||||
res = 0;
|
XNextEvent(display, &event);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XEventsQueued returns the num of events available.
|
// XEventsQueued returns the num of events available.
|
||||||
// Usually, games tend to read all events queued before calling again XEventsQueued
|
// Usually, games tend to read all events queued before calling again XEventsQueued
|
||||||
// making us unavailable to intercept undesired events
|
// making us unavailable to intercept undesired events
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int X11_Hook::MyXNextEvent(Display* display, XEvent *event)
|
||||||
|
{
|
||||||
|
return Inst()->_XNextEvent(display, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
int X11_Hook::MyXPeekEvent(Display* display, XEvent *event)
|
||||||
|
{
|
||||||
|
return Inst()->_XPeekEvent(display, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
int X11_Hook::MyXPending(Display* display)
|
||||||
|
{
|
||||||
|
int res = Inst()->_XPending(display);
|
||||||
|
|
||||||
|
if( res && get_steam_client()->steam_overlay->ShowOverlay() )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
X11_Hook::X11_Hook() :
|
X11_Hook::X11_Hook() :
|
||||||
initialized(false),
|
initialized(false),
|
||||||
hooked(false)
|
hooked(false),
|
||||||
|
game_wnd(0),
|
||||||
|
_XEventsQueued(nullptr),
|
||||||
|
_XPeekEvent(nullptr),
|
||||||
|
_XNextEvent(nullptr),
|
||||||
|
_XPending(nullptr)
|
||||||
{
|
{
|
||||||
//_library = dlopen(DLL_NAME, RTLD_NOW);
|
//_library = dlopen(DLL_NAME, RTLD_NOW);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,29 +20,48 @@ private:
|
||||||
// Variables
|
// Variables
|
||||||
bool hooked;
|
bool hooked;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
Window game_wnd;
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
X11_Hook();
|
X11_Hook();
|
||||||
|
|
||||||
// Hook to X11 window messages
|
// Hook to X11 window messages
|
||||||
static int MyXEventsQueued(Display * display, int mode);
|
|
||||||
|
|
||||||
decltype(XEventsQueued)* _XEventsQueued;
|
decltype(XEventsQueued)* _XEventsQueued;
|
||||||
|
|
||||||
decltype(XPeekEvent)* _XPeekEvent;
|
decltype(XPeekEvent)* _XPeekEvent;
|
||||||
decltype(XNextEvent)* _XNextEvent;
|
decltype(XNextEvent)* _XNextEvent;
|
||||||
decltype(XKeysymToKeycode)* _XKeysymToKeycode;
|
decltype(XPending)* _XPending;
|
||||||
decltype(XLookupKeysym)* _XLookupKeysym;
|
//decltype(XKeysymToKeycode)* _XKeysymToKeycode;
|
||||||
|
//decltype(XLookupKeysym)* _XLookupKeysym;
|
||||||
|
//decltype(XGetGeometry)* _XGetGeometry;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static int MyXEventsQueued(Display * display, int mode);
|
||||||
|
static int MyXNextEvent(Display* display, XEvent *event);
|
||||||
|
static int MyXPeekEvent(Display* display, XEvent *event);
|
||||||
|
static int MyXPending(Display* display);
|
||||||
|
|
||||||
virtual ~X11_Hook();
|
virtual ~X11_Hook();
|
||||||
|
|
||||||
void resetRenderState();
|
void resetRenderState();
|
||||||
void prepareForOverlay(Display *display);
|
void prepareForOverlay(Display *display, Window wnd);
|
||||||
|
|
||||||
|
Window get_game_wnd() const{ return game_wnd; }
|
||||||
|
|
||||||
bool start_hook();
|
bool start_hook();
|
||||||
static X11_Hook* Inst();
|
static X11_Hook* Inst();
|
||||||
virtual const char* get_lib_name() const;
|
virtual const char* get_lib_name() const;
|
||||||
|
|
||||||
|
inline decltype(XEventsQueued)* get_XEventsQueued() const { return _XEventsQueued; }
|
||||||
|
inline decltype(XPeekEvent)* get_XPeekEvent() const { return _XPeekEvent; }
|
||||||
|
inline decltype(XNextEvent)* get_XNextEvent() const { return _XNextEvent; }
|
||||||
|
inline decltype(XPending)* get_XPending() const { return _XPending; }
|
||||||
|
|
||||||
|
inline void loadXEventsQueued(decltype(XEventsQueued)* pfnXEventsQueued) { _XEventsQueued = pfnXEventsQueued; }
|
||||||
|
inline void loadXPeekEvent(decltype(XPeekEvent)* pfnXPeekEvent) { _XPeekEvent = pfnXPeekEvent; }
|
||||||
|
inline void loadXNextEvent(decltype(XNextEvent)* pfnXNextEvent) { _XNextEvent = pfnXNextEvent; }
|
||||||
|
inline void loadXPending(decltype(XPending)* pfnXPending) { _XPending = pfnXPending; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif//NO_OVERLAY
|
#endif//NO_OVERLAY
|
||||||
|
|
Loading…
Reference in a new issue