2019-09-01 20:53:16 +02:00
|
|
|
#include "X11_Hook.h"
|
|
|
|
#include "../Renderer_Detector.h"
|
|
|
|
#include "../dll/dll.h"
|
|
|
|
|
|
|
|
#ifdef __LINUX__
|
|
|
|
#ifndef NO_OVERLAY
|
|
|
|
|
|
|
|
#include <imgui.h>
|
|
|
|
#include <impls/linux/imgui_impl_x11.h>
|
|
|
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
extern int ImGui_ImplX11_EventHandler(XEvent &event);
|
|
|
|
|
|
|
|
X11_Hook* X11_Hook::_inst = nullptr;
|
|
|
|
|
|
|
|
bool X11_Hook::start_hook()
|
|
|
|
{
|
|
|
|
bool res = true;
|
|
|
|
if (!hooked)
|
|
|
|
{
|
2019-09-03 10:32:32 +02:00
|
|
|
PRINT_DEBUG("Hooked X11\n");
|
|
|
|
hooked = true;
|
2019-09-01 20:53:16 +02:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void X11_Hook::resetRenderState()
|
|
|
|
{
|
|
|
|
if (initialized)
|
|
|
|
{
|
2019-09-03 10:32:32 +02:00
|
|
|
game_wnd = 0;
|
2019-09-01 20:53:16 +02:00
|
|
|
initialized = false;
|
|
|
|
ImGui_ImplX11_Shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-03 10:32:32 +02:00
|
|
|
void X11_Hook::prepareForOverlay(Display *display, Window wnd)
|
2019-09-01 20:53:16 +02:00
|
|
|
{
|
|
|
|
if (!initialized)
|
|
|
|
{
|
|
|
|
ImGui_ImplX11_Init(display);
|
|
|
|
|
2019-09-03 10:32:32 +02:00
|
|
|
game_wnd = wnd;
|
2019-09-01 20:53:16 +02:00
|
|
|
|
|
|
|
initialized = true;
|
|
|
|
}
|
|
|
|
|
2019-09-03 10:32:32 +02:00
|
|
|
ImGui_ImplX11_NewFrame((void*)wnd);
|
2019-09-01 20:53:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// X11 window hooks
|
|
|
|
bool IgnoreEvent(XEvent &event)
|
|
|
|
{
|
|
|
|
switch(event.type)
|
|
|
|
{
|
|
|
|
// Keyboard
|
|
|
|
case KeyPress: case KeyRelease:
|
|
|
|
// MouseButton
|
|
|
|
case ButtonPress: case ButtonRelease:
|
|
|
|
// Mouse move
|
|
|
|
case MotionNotify:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int X11_Hook::MyXEventsQueued(Display *display, int mode)
|
|
|
|
{
|
|
|
|
X11_Hook* inst = X11_Hook::Inst();
|
|
|
|
|
|
|
|
int res = inst->_XEventsQueued(display, mode);
|
|
|
|
|
2019-09-03 10:32:32 +02:00
|
|
|
if( res )
|
2019-09-01 20:53:16 +02:00
|
|
|
{
|
2019-09-03 10:32:32 +02:00
|
|
|
static Time prev_time = {};
|
|
|
|
|
|
|
|
XEvent event;
|
|
|
|
//inst->_XPeekEvent(display, &event);
|
|
|
|
XPeekEvent(display, &event);
|
|
|
|
|
2019-09-01 20:53:16 +02:00
|
|
|
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
|
2019-09-03 10:32:32 +02:00
|
|
|
//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)
|
2019-09-01 20:53:16 +02:00
|
|
|
{
|
2019-09-03 10:32:32 +02:00
|
|
|
// if key TAB is held, don't make the overlay flicker :p
|
2019-09-01 20:53:16 +02:00
|
|
|
if( event.xkey.time != prev_time)
|
|
|
|
{
|
|
|
|
overlay->ShowOverlay(!overlay->ShowOverlay());
|
|
|
|
|
|
|
|
if (overlay->ShowOverlay())
|
|
|
|
show = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-03 10:32:32 +02:00
|
|
|
//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))
|
2019-09-01 20:53:16 +02:00
|
|
|
{
|
|
|
|
prev_time = event.xkey.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (show)
|
|
|
|
{
|
|
|
|
ImGui_ImplX11_EventHandler(event);
|
|
|
|
|
|
|
|
if (IgnoreEvent(event))
|
|
|
|
{
|
2019-09-03 10:32:32 +02:00
|
|
|
//inst->_XNextEvent(display, &event);
|
|
|
|
XNextEvent(display, &event);
|
|
|
|
return 0;
|
2019-09-01 20:53:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-03 10:32:32 +02:00
|
|
|
|
2019-09-01 20:53:16 +02:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2019-09-03 10:32:32 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-09-01 20:53:16 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
X11_Hook::X11_Hook() :
|
|
|
|
initialized(false),
|
2019-09-03 10:32:32 +02:00
|
|
|
hooked(false),
|
|
|
|
game_wnd(0),
|
|
|
|
_XEventsQueued(nullptr),
|
|
|
|
_XPeekEvent(nullptr),
|
|
|
|
_XNextEvent(nullptr),
|
|
|
|
_XPending(nullptr)
|
2019-09-01 20:53:16 +02:00
|
|
|
{
|
|
|
|
//_library = dlopen(DLL_NAME, RTLD_NOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
X11_Hook::~X11_Hook()
|
|
|
|
{
|
|
|
|
PRINT_DEBUG("X11 Hook removed\n");
|
|
|
|
|
|
|
|
resetRenderState();
|
|
|
|
|
|
|
|
//dlclose(_library);
|
|
|
|
|
|
|
|
_inst = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
X11_Hook* X11_Hook::Inst()
|
|
|
|
{
|
|
|
|
if (_inst == nullptr)
|
|
|
|
_inst = new X11_Hook;
|
|
|
|
|
|
|
|
return _inst;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* X11_Hook::get_lib_name() const
|
|
|
|
{
|
|
|
|
return DLL_NAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif//NO_OVERLAY
|
|
|
|
#endif//#__LINUX__
|