wip xkbcommon

This commit is contained in:
jackun 2022-06-02 23:03:53 +03:00
parent c68c48c02f
commit db9a23eb5a
No known key found for this signature in database
GPG Key ID: 119DB3F1D05A9ED3
13 changed files with 350 additions and 126 deletions

View File

@ -84,6 +84,7 @@ vulkan_wsi_args = []
vulkan_wsi_deps = [] vulkan_wsi_deps = []
if is_unixy if is_unixy
dep_xkb = dependency('xkbcommon', required: true)
dep_x11 = dependency('x11', required: get_option('with_x11')) dep_x11 = dependency('x11', required: get_option('with_x11'))
dep_xcb = dependency('xcb', required: get_option('with_x11')) dep_xcb = dependency('xcb', required: get_option('with_x11'))
dep_wayland_client = dependency('wayland-client', dep_wayland_client = dependency('wayland-client',
@ -92,10 +93,15 @@ if is_unixy
else else
dep_x11 = null_dep dep_x11 = null_dep
dep_xcb = null_dep dep_xcb = null_dep
dep_xkb = null_dep
dep_wayland_client = null_dep dep_wayland_client = null_dep
dbus_dep = null_dep dbus_dep = null_dep
endif endif
if dep_xkb.found()
pre_args += '-DHAVE_XKBCOMMON'
endif
if dep_x11.found() if dep_x11.found()
vulkan_wsi_args += ['-DVK_USE_PLATFORM_XLIB_KHR'] vulkan_wsi_args += ['-DVK_USE_PLATFORM_XLIB_KHR']
vulkan_wsi_deps += dep_x11.partial_dependency(compile_args : true, includes : true) vulkan_wsi_deps += dep_x11.partial_dependency(compile_args : true, includes : true)
@ -104,9 +110,9 @@ if dep_xcb.found()
vulkan_wsi_args += ['-DVK_USE_PLATFORM_XCB_KHR'] vulkan_wsi_args += ['-DVK_USE_PLATFORM_XCB_KHR']
vulkan_wsi_deps += dep_xcb #.partial_dependency(compile_args : true, includes : true) vulkan_wsi_deps += dep_xcb #.partial_dependency(compile_args : true, includes : true)
endif endif
if dep_wayland_client.found() if dep_wayland_client.found() and dep_xkb.found()
vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR'] vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR']
vulkan_wsi_deps += dep_wayland_client vulkan_wsi_deps += [dep_wayland_client, dep_xkb]
endif endif
if is_unixy and not dep_x11.found() and not dep_wayland_client.found() if is_unixy and not dep_x11.found() and not dep_wayland_client.found()

View File

@ -14,6 +14,7 @@
#include "notify.h" #include "notify.h"
#include "blacklist.h" #include "blacklist.h"
#include "wsi_helpers.h" #include "wsi_helpers.h"
#include "keybinds.h"
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
#include "dbus_info.h" #include "dbus_info.h"
@ -115,7 +116,7 @@ void imgui_init()
} }
//static //static
void imgui_create(void *ctx) void imgui_create(void *ctx, GL_SESSION gl_session)
{ {
if (inited) if (inited)
return; return;
@ -172,6 +173,16 @@ void imgui_create(void *ctx)
sw_stats.font_params_hash = params.font_params_hash; sw_stats.font_params_hash = params.font_params_hash;
wsi_conn.focus_changed = focus_changed; wsi_conn.focus_changed = focus_changed;
if (gl_session == GL_SESSION_X11)
wsi_conn.keys_are_pressed = keys_are_pressed;
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
if (gl_session == GL_SESSION_WL)
{
wsi_conn.keys_are_pressed = wl_keys_are_pressed;
wsi_wayland_init(wsi_conn);
}
#endif
// Restore global context or ours might clash with apps that use Dear ImGui // Restore global context or ours might clash with apps that use Dear ImGui
ImGui::SetCurrentContext(saved_ctx); ImGui::SetCurrentContext(saved_ctx);
} }
@ -191,7 +202,7 @@ void imgui_set_context(void *ctx)
{ {
if (!ctx) if (!ctx)
return; return;
imgui_create(ctx); imgui_create(ctx, GL_SESSION_X11);
} }
void imgui_render(unsigned int width, unsigned int height) void imgui_render(unsigned int width, unsigned int height)
@ -205,7 +216,7 @@ void imgui_render(unsigned int width, unsigned int height)
process_control_socket(control_client, params); process_control_socket(control_client, params);
} }
check_keybinds(params, vendorID); check_keybinds(wsi_conn, params);
update_hud_info(sw_stats, params, vendorID); update_hud_info(sw_stats, params, vendorID);
ImGuiContext *saved_ctx = ImGui::GetCurrentContext(); ImGuiContext *saved_ctx = ImGui::GetCurrentContext();

View File

@ -7,9 +7,18 @@
namespace MangoHud { namespace GL { namespace MangoHud { namespace GL {
extern wsi_connection wsi_conn;
enum GL_SESSION
{
GL_SESSION_UNKNOWN,
GL_SESSION_X11,
GL_SESSION_WL,
};
extern overlay_params params; extern overlay_params params;
void imgui_init(); void imgui_init();
void imgui_create(void *ctx); void imgui_create(void *ctx, GL_SESSION);
void imgui_shutdown(); void imgui_shutdown();
void imgui_set_context(void *ctx); void imgui_set_context(void *ctx);
void imgui_render(unsigned int width, unsigned int height); void imgui_render(unsigned int width, unsigned int height);

View File

@ -10,10 +10,60 @@
#include "mesa/util/os_time.h" #include "mesa/util/os_time.h"
#include "blacklist.h" #include "blacklist.h"
#include "gl_hud.h" #include "gl_hud.h"
#include "wsi_helpers.h"
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <wayland-egl.h>
#endif
#include <sys/mman.h>
#include <unistd.h>
#define HAVE_MINCORE
using namespace MangoHud::GL; using namespace MangoHud::GL;
EXPORT_C_(void *) eglGetProcAddress(const char* procName); namespace MangoHud { namespace GL {
extern swapchain_stats sw_stats;
extern wsi_connection wsi_conn;
}}
EXPORT_C_(void*) eglGetProcAddress(const char* procName);
static GL_SESSION egl_session = GL_SESSION_UNKNOWN;
// mesa eglglobals.c
static bool pointer_is_dereferencable(void *p)
{
#ifdef HAVE_MINCORE
uintptr_t addr = (uintptr_t) p;
unsigned char valid = 0;
const long page_size = getpagesize();
if (p == NULL)
return false;
/* align addr to page_size */
addr &= ~(page_size - 1);
if (mincore((void *) addr, page_size, &valid) < 0) {
return false;
}
/* mincore() returns 0 on success, and -1 on failure. The last parameter
* is a vector of bytes with one entry for each page queried. mincore
* returns page residency information in the first bit of each byte in the
* vector.
*
* Residency doesn't actually matter when determining whether a pointer is
* dereferenceable, so the output vector can be ignored. What matters is
* whether mincore succeeds. See:
*
* http://man7.org/linux/man-pages/man2/mincore.2.html
*/
return true;
#else
return p != NULL;
#endif
}
void* get_egl_proc_address(const char* name) { void* get_egl_proc_address(const char* name) {
@ -48,6 +98,66 @@ EXPORT_C_(int) eglMakeCurrent_OFF(void *dpy, void *draw, void *read,void *ctx) {
return ret; return ret;
} }
EXPORT_C_(void*) eglGetDisplay(void* native_display)
{
static decltype(&eglGetDisplay) pfn_eglGetDisplay = nullptr;
if (!pfn_eglGetDisplay)
pfn_eglGetDisplay = reinterpret_cast<decltype(pfn_eglGetDisplay)>(get_egl_proc_address("eglGetDisplay"));
if (getenv("WAYLAND_DISPLAY"))
{
egl_session = GL_SESSION_WL;
wsi_conn.wl.display = reinterpret_cast<wl_display*> (native_display);
}
else if (getenv("DISPLAY"))
{
egl_session = GL_SESSION_X11;
wsi_conn.xlib.dpy = reinterpret_cast<Display*> (native_display);
}
if (pointer_is_dereferencable(native_display))
{
Dl_info info;
void *first_pointer = *(void **) native_display;
dladdr(first_pointer, &info);
if (info.dli_saddr)
fprintf(stderr, "dli_sname: %s\n", info.dli_sname);
}
return pfn_eglGetDisplay(native_display);
}
EXPORT_C_(void*) eglCreateWindowSurface(void *egl_display, void *egl_config, void *native_window, int const * attrib_list)
{
static decltype(&eglCreateWindowSurface) pfn_eglCreateWindowSurface = nullptr;
if (!pfn_eglCreateWindowSurface)
pfn_eglCreateWindowSurface = reinterpret_cast<decltype(pfn_eglCreateWindowSurface)>(get_egl_proc_address("eglCreateWindowSurface"));
if (egl_session == GL_SESSION_WL)
{
// wsi_conn.wl.surface = reinterpret_cast<wl_surface*>(native_window);
}
else if (egl_session == GL_SESSION_X11)
{
wsi_conn.xlib.window = reinterpret_cast<Window>(native_window);
}
return pfn_eglCreateWindowSurface(egl_display, egl_config, native_window, attrib_list);
}
EXPORT_C_(wl_egl_window*) wl_egl_window_create(wl_surface *surf, int w, int h)
{
static decltype(&wl_egl_window_create) pfn_wl_egl_window_create = nullptr;
if (!pfn_wl_egl_window_create)
{
void *hlib = dlopen("libwayland-egl.so.1", RTLD_LAZY);
pfn_wl_egl_window_create = reinterpret_cast<decltype(pfn_wl_egl_window_create)>(dlsym(hlib, "wl_egl_window_create"));
}
fprintf(stderr, "%s\n", __func__);
wsi_conn.wl.surface = surf;
return pfn_wl_egl_window_create(surf, w, h);
}
EXPORT_C_(unsigned int) eglSwapBuffers( void* dpy, void* surf) EXPORT_C_(unsigned int) eglSwapBuffers( void* dpy, void* surf)
{ {
static int (*pfn_eglSwapBuffers)(void*, void*) = nullptr; static int (*pfn_eglSwapBuffers)(void*, void*) = nullptr;
@ -59,7 +169,7 @@ EXPORT_C_(unsigned int) eglSwapBuffers( void* dpy, void* surf)
if (!pfn_eglQuerySurface) if (!pfn_eglQuerySurface)
pfn_eglQuerySurface = reinterpret_cast<decltype(pfn_eglQuerySurface)>(get_egl_proc_address("eglQuerySurface")); pfn_eglQuerySurface = reinterpret_cast<decltype(pfn_eglQuerySurface)>(get_egl_proc_address("eglQuerySurface"));
imgui_create(surf); imgui_create(surf, egl_session);
int width=0, height=0; int width=0, height=0;
if (pfn_eglQuerySurface(dpy, surf, 0x3056, &height) && if (pfn_eglQuerySurface(dpy, surf, 0x3056, &height) &&
@ -67,9 +177,9 @@ EXPORT_C_(unsigned int) eglSwapBuffers( void* dpy, void* surf)
imgui_render(width, height); imgui_render(width, height);
using namespace std::chrono_literals; using namespace std::chrono_literals;
if (fps_limit_stats.targetFrameTime > 0s){ if (fps_limit_stats.targetFrameTime > 0s || (sw_stats.lost_focus && fps_limit_stats.focusLossFrameTime > 0s)){
fps_limit_stats.frameStart = Clock::now(); fps_limit_stats.frameStart = Clock::now();
FpsLimiter(fps_limit_stats); FpsLimiter(fps_limit_stats, sw_stats.lost_focus);
fps_limit_stats.frameEnd = Clock::now(); fps_limit_stats.frameEnd = Clock::now();
} }
} }
@ -82,10 +192,12 @@ struct func_ptr {
void *ptr; void *ptr;
}; };
static std::array<const func_ptr, 2> name_to_funcptr_map = {{ static std::array<const func_ptr, 4> name_to_funcptr_map = {{
#define ADD_HOOK(fn) { #fn, (void *) fn } #define ADD_HOOK(fn) { #fn, (void *) fn }
ADD_HOOK(eglGetProcAddress), ADD_HOOK(eglGetProcAddress),
ADD_HOOK(eglSwapBuffers), ADD_HOOK(eglSwapBuffers),
ADD_HOOK(eglGetDisplay),
ADD_HOOK(wl_egl_window_create),
#undef ADD_HOOK #undef ADD_HOOK
}}; }};
@ -102,7 +214,8 @@ EXPORT_C_(void *) mangohud_find_egl_ptr(const char *name)
return nullptr; return nullptr;
} }
EXPORT_C_(void *) eglGetProcAddress(const char* procName) { void* eglGetProcAddress(const char* procName)
{
void* real_func = get_egl_proc_address(procName); void* real_func = get_egl_proc_address(procName);
void* func = mangohud_find_egl_ptr(procName); void* func = mangohud_find_egl_ptr(procName);
SPDLOG_TRACE("{}: proc: {}, real: {}, fun: {}", __func__, procName, real_func, func); SPDLOG_TRACE("{}: proc: {}, real: {}, fun: {}", __func__, procName, real_func, func);

View File

@ -132,10 +132,10 @@ static void do_imgui_swap(void *dpy, void *drawable)
{ {
GLint vp[4]; GLint vp[4];
if (!is_blacklisted()) { if (!is_blacklisted()) {
imgui_create(glx.GetCurrentContext());
wsi_conn.xlib.dpy = (Display*)dpy; wsi_conn.xlib.dpy = (Display*)dpy;
wsi_conn.xlib.window = (Window)drawable; wsi_conn.xlib.window = (Window)drawable;
imgui_create(glx.GetCurrentContext(), GL_SESSION_X11);
unsigned int width = -1, height = -1; unsigned int width = -1, height = -1;

View File

@ -1,10 +1,89 @@
#include <spdlog/spdlog.h>
#include <map>
#include "overlay.h" #include "overlay.h"
#include "timing.hpp" #include "timing.hpp"
#include "logging.h" #include "logging.h"
#include "keybinds.h" #include "keybinds.h"
#include <wayland-client.h> #include "wsi_helpers.h"
void check_keybinds(struct overlay_params& params, uint32_t vendorID){ #ifdef HAVE_X11
#include "shared_x11.h"
#include "loaders/loader_x11.h"
#endif
Clock::time_point last_f2_press, toggle_fps_limit_press , last_f12_press, reload_cfg_press, last_upload_press;
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
std::map<xkb_keysym_t, bool> xkb_state;
void wl_key_pressed(const xkb_keysym_t key, uint32_t state)
{
xkb_state[key] = !!state;
}
bool wl_keys_are_pressed(const std::vector<xkb_keysym_t>& keys) {
size_t pressed = 0;
for (KeySym ks : keys) {
if (xkb_state[ks])
pressed++;
}
if (pressed > 0 && pressed == keys.size()) {
return true;
}
return false;
}
#endif
#if defined(HAVE_X11)
bool keys_are_pressed(const std::vector<xkb_keysym_t>& keys) {
if (!init_x11())
return false;
char keys_return[32];
size_t pressed = 0;
g_x11->XQueryKeymap(get_xdisplay(), keys_return);
for (KeySym ks : keys) {
KeyCode kc2 = g_x11->XKeysymToKeycode(get_xdisplay(), ks);
bool isPressed = !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7)));
if (isPressed)
pressed++;
}
if (pressed > 0 && pressed == keys.size()) {
return true;
}
return false;
}
#elif defined(_WIN32)
#include <windows.h>
bool keys_are_pressed(const std::vector<xkb_keysym_t>& keys) {
size_t pressed = 0;
for (KeySym ks : keys) {
if (GetAsyncKeyState(ks) & 0x8000)
pressed++;
}
if (pressed > 0 && pressed == keys.size()) {
return true;
}
return false;
}
#else
bool keys_are_pressed(const std::vector<xkb_keysym_t>& keys) {
return false;
}
#endif
void check_keybinds(wsi_connection& wsi, struct overlay_params& params){
using namespace std::chrono_literals; using namespace std::chrono_literals;
auto now = Clock::now(); /* us */ auto now = Clock::now(); /* us */
auto elapsedF2 = now - last_f2_press; auto elapsedF2 = now - last_f2_press;
@ -20,8 +99,14 @@ void check_keybinds(struct overlay_params& params, uint32_t vendorID){
auto keyPressDelay = 400ms; auto keyPressDelay = 400ms;
if (!wsi.keys_are_pressed)
{
SPDLOG_DEBUG("wsi.keys_are_pressed is not set!");
return;
}
if (elapsedF2 >= keyPressDelay && if (elapsedF2 >= keyPressDelay &&
keys_are_pressed(params.toggle_logging)) { wsi.keys_are_pressed(params.toggle_logging)) {
last_f2_press = now; last_f2_press = now;
if (logger->is_active()) { if (logger->is_active()) {
logger->stop_logging(); logger->stop_logging();
@ -32,7 +117,7 @@ void check_keybinds(struct overlay_params& params, uint32_t vendorID){
} }
if (elapsedFpsLimitToggle >= keyPressDelay && if (elapsedFpsLimitToggle >= keyPressDelay &&
keys_are_pressed(params.toggle_fps_limit)) { wsi.keys_are_pressed(params.toggle_fps_limit)) {
toggle_fps_limit_press = now; toggle_fps_limit_press = now;
for (size_t i = 0; i < params.fps_limit.size(); i++){ for (size_t i = 0; i < params.fps_limit.size(); i++){
uint32_t fps_limit = params.fps_limit[i]; uint32_t fps_limit = params.fps_limit[i];
@ -51,26 +136,26 @@ void check_keybinds(struct overlay_params& params, uint32_t vendorID){
} }
if (elapsedF12 >= keyPressDelay && if (elapsedF12 >= keyPressDelay &&
keys_are_pressed(params.toggle_hud)) { wsi.keys_are_pressed(params.toggle_hud)) {
last_f12_press = now; last_f12_press = now;
params.no_display = !params.no_display; params.no_display = !params.no_display;
} }
if (elapsedReloadCfg >= keyPressDelay && if (elapsedReloadCfg >= keyPressDelay &&
keys_are_pressed(params.reload_cfg)) { wsi.keys_are_pressed(params.reload_cfg)) {
parse_overlay_config(&params, getenv("MANGOHUD_CONFIG")); parse_overlay_config(&params, getenv("MANGOHUD_CONFIG"));
_params = &params; _params = &params;
reload_cfg_press = now; reload_cfg_press = now;
} }
if (params.permit_upload && elapsedUpload >= keyPressDelay && if (params.permit_upload && elapsedUpload >= keyPressDelay &&
keys_are_pressed(params.upload_log)) { wsi.keys_are_pressed(params.upload_log)) {
last_upload_press = now; last_upload_press = now;
logger->upload_last_log(); logger->upload_last_log();
} }
if (params.permit_upload && elapsedUpload >= keyPressDelay && if (params.permit_upload && elapsedUpload >= keyPressDelay &&
keys_are_pressed(params.upload_logs)) { wsi.keys_are_pressed(params.upload_logs)) {
last_upload_press = now; last_upload_press = now;
logger->upload_last_logs(); logger->upload_last_logs();
} }

View File

@ -1,64 +1,21 @@
#pragma once #pragma once
#ifndef MANGOHUD_KEYBINDS_H #ifndef MANGOHUD_KEYBINDS_H
#define MANGOHUD_KEYBINDS_H #define MANGOHUD_KEYBINDS_H
#include <vector>
#ifdef HAVE_X11 #ifdef HAVE_XKBCOMMON
#include "shared_x11.h" #include <xkbcommon/xkbcommon.h>
#include "loaders/loader_x11.h" #else
typedef uint32_t xkb_keysym_t;
#endif #endif
#ifndef KeySym struct wsi_connection;
typedef unsigned long KeySym; struct overlay_params;
void check_keybinds(wsi_connection&, overlay_params& params);
bool keys_are_pressed(const std::vector<xkb_keysym_t>& keys);
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
bool wl_keys_are_pressed(const std::vector<xkb_keysym_t>& keys);
void wl_key_pressed(const xkb_keysym_t key, uint32_t state);
#endif #endif
Clock::time_point last_f2_press, toggle_fps_limit_press , last_f12_press, reload_cfg_press, last_upload_press;
#if defined(HAVE_X11)
bool keys_are_pressed(const std::vector<KeySym>& keys) {
if (!init_x11())
return false;
char keys_return[32];
size_t pressed = 0;
g_x11->XQueryKeymap(get_xdisplay(), keys_return);
for (KeySym ks : keys) {
KeyCode kc2 = g_x11->XKeysymToKeycode(get_xdisplay(), ks);
bool isPressed = !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7)));
if (isPressed)
pressed++;
}
if (pressed > 0 && pressed == keys.size()) {
return true;
}
return false;
}
#elif defined(_WIN32)
#include <windows.h>
bool keys_are_pressed(const std::vector<KeySym>& keys) {
size_t pressed = 0;
for (KeySym ks : keys) {
if (GetAsyncKeyState(ks) & 0x8000)
pressed++;
}
if (pressed > 0 && pressed == keys.size()) {
return true;
}
return false;
}
#else // XXX: Add wayland support
bool keys_are_pressed(const std::vector<KeySym>& keys) {
return false;
}
#endif
#endif //MANGOHUD_KEYBINDS_H #endif //MANGOHUD_KEYBINDS_H

View File

@ -108,7 +108,6 @@ void update_hud_info_with_frametime(struct swapchain_stats& sw_stats, const stru
void update_hw_info(const struct overlay_params& params, uint32_t vendorID); void update_hw_info(const struct overlay_params& params, uint32_t vendorID);
void init_gpu_stats(uint32_t& vendorID, uint32_t reported_deviceID, overlay_params& params); void init_gpu_stats(uint32_t& vendorID, uint32_t reported_deviceID, overlay_params& params);
void init_cpu_stats(overlay_params& params); void init_cpu_stats(overlay_params& params);
void check_keybinds(overlay_params& params, uint32_t vendorID);
void init_system_info(void); void init_system_info(void);
void FpsLimiter(struct fps_limit& stats, bool lost_focus = false); void FpsLimiter(struct fps_limit& stats, bool lost_focus = false);
std::string get_device_name(uint32_t vendorID, uint32_t deviceID); std::string get_device_name(uint32_t vendorID, uint32_t deviceID);

View File

@ -124,22 +124,19 @@ parse_float(const char *str)
return val; return val;
} }
#ifdef HAVE_X11 #ifdef HAVE_XKBCOMMON
static std::vector<KeySym> static std::vector<xkb_keysym_t>
parse_string_to_keysym_vec(const char *str) parse_string_to_keysym_vec(const char *str)
{ {
std::vector<KeySym> keys; std::vector<xkb_keysym_t> keys;
if(g_x11->IsLoaded()) auto keyStrings = str_tokenize(str);
{ for (auto& ks : keyStrings) {
auto keyStrings = str_tokenize(str); trim(ks);
for (auto& ks : keyStrings) { auto xk = xkb_keysym_from_name(ks.c_str(), XKB_KEYSYM_NO_FLAGS);
trim(ks); if (xk)
KeySym xk = g_x11->XStringToKeysym(ks.c_str()); keys.push_back(xk);
if (xk) else
keys.push_back(xk); SPDLOG_ERROR("Unrecognized key: '{}'", ks);
else
SPDLOG_ERROR("Unrecognized key: '{}'", ks);
}
} }
return keys; return keys;
} }

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <xkbcommon/xkbcommon.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -235,12 +236,12 @@ struct overlay_params {
float font_scale_media_player; float font_scale_media_player;
float background_alpha, alpha; float background_alpha, alpha;
float cellpadding_y; float cellpadding_y;
std::vector<KeySym> toggle_hud; std::vector<xkb_keysym_t> toggle_hud;
std::vector<KeySym> toggle_fps_limit; std::vector<xkb_keysym_t> toggle_fps_limit;
std::vector<KeySym> toggle_logging; std::vector<xkb_keysym_t> toggle_logging;
std::vector<KeySym> reload_cfg; std::vector<xkb_keysym_t> reload_cfg;
std::vector<KeySym> upload_log; std::vector<xkb_keysym_t> upload_log;
std::vector<KeySym> upload_logs; std::vector<xkb_keysym_t> upload_logs;
std::string time_format, output_folder, output_file; std::string time_format, output_folder, output_file;
std::string pci_dev; std::string pci_dev;
std::string media_player_name; std::string media_player_name;

View File

@ -50,6 +50,7 @@
#include "blacklist.h" #include "blacklist.h"
#include "pci_ids.h" #include "pci_ids.h"
#include "wsi_helpers.h" #include "wsi_helpers.h"
#include "keybinds.h"
using namespace std; using namespace std;
@ -430,6 +431,7 @@ static VkResult overlay_CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurf
struct surface_data *data = new_surface_data(*pSurface); struct surface_data *data = new_surface_data(*pSurface);
data->wsi.xcb.conn = pCreateInfo->connection; data->wsi.xcb.conn = pCreateInfo->connection;
data->wsi.xcb.window = pCreateInfo->window; data->wsi.xcb.window = pCreateInfo->window;
data->wsi.keys_are_pressed = keys_are_pressed;
} }
return result; return result;
@ -447,13 +449,14 @@ static VkResult overlay_CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSu
struct surface_data *data = new_surface_data(*pSurface); struct surface_data *data = new_surface_data(*pSurface);
data->wsi.xlib.dpy = pCreateInfo->dpy; data->wsi.xlib.dpy = pCreateInfo->dpy;
data->wsi.xlib.window = pCreateInfo->window; data->wsi.xlib.window = pCreateInfo->window;
data->wsi.keys_are_pressed = keys_are_pressed;
} }
return result; return result;
} }
#endif #endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR #ifdef VK_USE_PLATFORM_WAYLAND_KHR
extern void wayland_init(wsi_connection&); extern void wsi_wayland_init(wsi_connection&);
static VkResult overlay_CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) static VkResult overlay_CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface)
{ {
SPDLOG_DEBUG("{}", __func__); SPDLOG_DEBUG("{}", __func__);
@ -464,7 +467,9 @@ static VkResult overlay_CreateWaylandSurfaceKHR(VkInstance instance, const VkWay
struct surface_data *data = new_surface_data(*pSurface); struct surface_data *data = new_surface_data(*pSurface);
data->wsi.wl.display = pCreateInfo->display; data->wsi.wl.display = pCreateInfo->display;
data->wsi.wl.surface = pCreateInfo->surface; data->wsi.wl.surface = pCreateInfo->surface;
wayland_init(data->wsi); data->wsi.keys_are_pressed = wl_keys_are_pressed;
data->wsi.key_pressed = wl_key_pressed;
wsi_wayland_init(data->wsi);
} }
return result; return result;
} }
@ -531,7 +536,7 @@ static void snapshot_swapchain_frame(struct swapchain_data *data)
struct device_data *device_data = data->device; struct device_data *device_data = data->device;
struct instance_data *instance_data = device_data->instance; struct instance_data *instance_data = device_data->instance;
update_hud_info(data->sw_stats, instance_data->params, device_data->properties.vendorID); update_hud_info(data->sw_stats, instance_data->params, device_data->properties.vendorID);
check_keybinds(instance_data->params, device_data->properties.vendorID); check_keybinds(data->surface_data->wsi, instance_data->params);
#ifdef __linux__ #ifdef __linux__
if (instance_data->params.control >= 0) { if (instance_data->params.control >= 0) {
control_client_check(instance_data->params.control, instance_data->control_client, gpu.c_str()); control_client_check(instance_data->params.control, instance_data->control_client, gpu.c_str());

View File

@ -1,5 +1,11 @@
#include <unistd.h>
#include <sys/mman.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <cstring> #include <cstring>
#include <map>
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <xkbcommon/xkbcommon.h>
#endif
#include "wsi_helpers.h" #include "wsi_helpers.h"
#ifdef VK_USE_PLATFORM_XCB_KHR #ifdef VK_USE_PLATFORM_XCB_KHR
@ -9,10 +15,10 @@ static bool check_window_focus(xcb_connection_t * connection, xcb_window_t windo
auto reply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr); auto reply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr);
if (reply) if (reply)
{ {
SPDLOG_DEBUG("Window: {:08x} Focus WId: {:08x}", window, reply->focus); SPDLOG_DEBUG("Window: {:08x} Focus WId: {:08x}", window, reply->focus);
bool has_focus = (window == reply->focus); bool has_focus = (window == reply->focus);
free(reply); free(reply);
return has_focus; return has_focus;
} }
// xcb_query_tree_cookie_t cookie = xcb_query_tree(connection, reply->focus); // xcb_query_tree_cookie_t cookie = xcb_query_tree(connection, reply->focus);
@ -92,33 +98,56 @@ void window_has_focus(wsi_connection* conn)
#endif #endif
} }
struct interfaces_ struct wl_state
{ {
wl_shell *shell; // wl_shell *shell;
wl_seat *seat; // wl_seat *seat;
wsi_connection *wsi; wsi_connection *wsi;
}; xkb_context *ctx;
xkb_keymap *keymap;
struct xkb_state *state;
} g_wl_state {}; //TODO per surface etc instance?
static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) { static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) {
SPDLOG_DEBUG("{}", __func__); SPDLOG_DEBUG("{}", __func__);
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
char *map_shm = reinterpret_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0));
assert(map_shm != MAP_FAILED);
xkb_keymap_unref(g_wl_state.keymap);
g_wl_state.keymap = xkb_keymap_new_from_string(g_wl_state.ctx, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS); // FIXME probably leaking stuff
munmap(map_shm, size);
close(fd);
xkb_state_unref(g_wl_state.state);
g_wl_state.state = xkb_state_new(g_wl_state.keymap); // FIXME probably leaking stuff
} }
static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
SPDLOG_DEBUG("{}", __func__);
auto wsi = reinterpret_cast<wsi_connection*>(data); auto wsi = reinterpret_cast<wsi_connection*>(data);
SPDLOG_DEBUG("{}: {} == {}", __func__, (void*)wsi->wl.surface, (void*)surface);
if (wsi->focus_changed && surface == wsi->wl.surface) if (wsi->focus_changed && surface == wsi->wl.surface)
wsi->focus_changed(true); wsi->focus_changed(true);
} }
static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) {
SPDLOG_DEBUG("{}", __func__); SPDLOG_DEBUG("{}: {}", __func__, (void*)surface);
auto wsi = reinterpret_cast<wsi_connection*>(data); auto wsi = reinterpret_cast<wsi_connection*>(data);
if (wsi->focus_changed && surface == wsi->wl.surface) if (wsi->focus_changed && surface == wsi->wl.surface)
wsi->focus_changed(false); wsi->focus_changed(false);
} }
static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
SPDLOG_DEBUG("{}: key pressed: {}", __func__, key); auto wsi = reinterpret_cast<wsi_connection*>(data);
uint32_t keycode = key + 8;
xkb_keysym_t sym = xkb_state_key_get_one_sym(g_wl_state.state, keycode);
if (wsi->key_pressed)
wsi->key_pressed(sym, state);
SPDLOG_DEBUG("{}: key pressed: {}, {}, {:08x}", __func__, key, state, sym);
} }
static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
@ -130,7 +159,7 @@ static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keybo
static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) { static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) {
SPDLOG_DEBUG("{}", __func__); SPDLOG_DEBUG("{}", __func__);
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
SPDLOG_DEBUG("SEAT"); SPDLOG_DEBUG("Got usable seat");
struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat); struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat);
wl_keyboard_add_listener (keyboard, &keyboard_listener, data); wl_keyboard_add_listener (keyboard, &keyboard_listener, data);
} }
@ -139,7 +168,7 @@ static struct wl_seat_listener seat_listener = {&seat_capabilities};
static void registry_add_object (void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { static void registry_add_object (void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) {
SPDLOG_DEBUG("{}", __func__); SPDLOG_DEBUG("{}", __func__);
if (!strcmp(interface,"wl_seat")) { if (!strcmp(interface, "wl_seat")) {
//input_reader* ir = wl_registry_get_user_data(registry); //input_reader* ir = wl_registry_get_user_data(registry);
auto seat = (wl_seat*)wl_registry_bind (registry, name, &wl_seat_interface, 1); auto seat = (wl_seat*)wl_registry_bind (registry, name, &wl_seat_interface, 1);
// SPDLOG_DEBUG("wl_seat_add_listener {}", wl_proxy_get_listener((wl_proxy*)seat)); // SPDLOG_DEBUG("wl_seat_add_listener {}", wl_proxy_get_listener((wl_proxy*)seat));
@ -152,11 +181,11 @@ static void registry_remove_object (void *data, struct wl_registry *registry, ui
static struct wl_registry_listener registry_listener = {&registry_add_object, &registry_remove_object}; static struct wl_registry_listener registry_listener = {&registry_add_object, &registry_remove_object};
// interfaces_ g_interfaces {}; void wsi_wayland_init(wsi_connection& conn)
void wayland_init(wsi_connection& conn)
{ {
auto registry = wl_display_get_registry(conn.wl.display); auto registry = wl_display_get_registry(conn.wl.display);
wl_registry_add_listener(registry, &registry_listener, &conn); g_wl_state.ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); //FIXME probably leaking stuff
wl_display_roundtrip(conn.wl.display); g_wl_state.wsi = &conn; //TODO per surfacei nstance?
wl_registry_add_listener(registry, &registry_listener, &conn);
wl_display_roundtrip(conn.wl.display);
} }

View File

@ -1,5 +1,13 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <vector>
#ifdef HAVE_XKBCOMMON
#include <xkbcommon/xkbcommon.h>
#else
typedef uint32_t xkb_keysym_t;
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR #ifdef VK_USE_PLATFORM_XLIB_KHR
#include "loaders/loader_x11.h" #include "loaders/loader_x11.h"
#endif #endif
@ -16,28 +24,32 @@
struct wsi_connection struct wsi_connection
{ {
std::function<void(bool)> focus_changed; std::function<void(bool)> focus_changed;
std::function<void(xkb_keysym_t, uint32_t)> key_pressed;
std::function<bool(const std::vector<xkb_keysym_t>& keys)> keys_are_pressed;
#ifdef VK_USE_PLATFORM_XCB_KHR #ifdef VK_USE_PLATFORM_XCB_KHR
struct xcb { struct xcb {
xcb_connection_t *conn = nullptr; xcb_connection_t *conn;
xcb_window_t window = 0; xcb_window_t window;
} xcb; } xcb;
#endif #endif
#ifdef VK_USE_PLATFORM_XLIB_KHR #ifdef VK_USE_PLATFORM_XLIB_KHR
struct xlib { struct xlib {
Display *dpy = nullptr; Display *dpy;
Window window = 0; Window window;
int evmask = 0; int evmask;
} xlib; } xlib;
#endif #endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR #ifdef VK_USE_PLATFORM_WAYLAND_KHR
struct wl { struct wl {
wl_display *display; wl_display *display;
wl_surface *surface; wl_surface *surface;
bool has_focus;
} wl; } wl;
#endif #endif
}; };
// struct wsi_connection; // struct wsi_connection;
// bool check_window_focus(const wsi_connection&); // bool check_window_focus(const wsi_connection&);
void wsi_wayland_init(wsi_connection& conn);