From cbdf381b314f90107d47aef8df2675b67d66fc05 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Nov 2022 12:29:29 +0100 Subject: [PATCH] Fix gamepad hotkey and game profile setting (#510) --- CMakeLists.txt | 1 + cmake/FindGTK3.cmake | 16 +++++ src/Cafe/CafeSystem.cpp | 3 +- src/Cafe/HW/Latte/Core/Latte.h | 3 +- src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 9 +-- src/config/ActiveSettings.cpp | 3 - src/gui/CMakeLists.txt | 5 ++ src/gui/CemuApp.cpp | 6 +- src/gui/guiWrapper.cpp | 63 ++++++------------- src/gui/guiWrapper.h | 25 +++++++- src/input/api/Keyboard/KeyboardController.cpp | 9 +-- 11 files changed, 79 insertions(+), 64 deletions(-) create mode 100644 cmake/FindGTK3.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 3615c65a..28ac8760 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ endif() if (UNIX AND NOT APPLE) find_package(X11 REQUIRED) + find_package(GTK3 REQUIRED) endif() if (ENABLE_VULKAN) diff --git a/cmake/FindGTK3.cmake b/cmake/FindGTK3.cmake new file mode 100644 index 00000000..06f6c18e --- /dev/null +++ b/cmake/FindGTK3.cmake @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2022 Andrea Pappacoda +# SPDX-License-Identifier: ISC + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig) +if (PKG_CONFIG_FOUND) + pkg_search_module(GTK3 IMPORTED_TARGET gtk+-3.0) + if (GTK3_FOUND) + add_library(GTK3::gtk ALIAS PkgConfig::GTK3) + endif() + find_package_handle_standard_args(GTK3 + REQUIRED_VARS GTK3_LINK_LIBRARIES + VERSION_VAR GTK3_VERSION + ) +endif() diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index a0a3094a..cb58284d 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -394,6 +394,7 @@ void cemu_initForGame() // replace any known function signatures with our HLE implementations and patch bugs in the games GamePatch_scan(); } + LatteGPUState.alwaysDisplayDRC = ActiveSettings::DisplayDRCEnabled(); InfoLog_PrintActiveSettings(); Latte_Start(); // check for debugger entrypoint bp @@ -864,4 +865,4 @@ namespace CafeSystem return currentUpdatedApplicationHash; } -} \ No newline at end of file +} diff --git a/src/Cafe/HW/Latte/Core/Latte.h b/src/Cafe/HW/Latte/Core/Latte.h index 04abf510..36268645 100644 --- a/src/Cafe/HW/Latte/Core/Latte.h +++ b/src/Cafe/HW/Latte/Core/Latte.h @@ -50,6 +50,7 @@ struct LatteGPUState_t uint32 gx2InitCalled; // incremented every time GX2Init() is called // OpenGL control uint32 glVendor; // GLVENDOR_* + bool alwaysDisplayDRC = false; // temporary (replace with proper solution later) bool tvBufferUsesSRGB; bool drcBufferUsesSRGB; @@ -172,4 +173,4 @@ void LatteRenderTarget_updateViewport(); // Latte emulation control void Latte_Start(); void Latte_Stop(); -bool Latte_IsActive(); \ No newline at end of file +bool Latte_IsActive(); diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp index 18d715d8..092c859d 100644 --- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp +++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp @@ -1004,7 +1004,6 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa g_renderer->ImguiEnd(); } -bool alwaysDisplayDRC = false; bool ctrlTabHotkeyPressed = false; void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferSliceIndex, uint32 colorBufferFormat, uint32 colorBufferPitch, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferSwizzle, uint32 renderTarget) @@ -1016,9 +1015,11 @@ void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uin return; } - const bool tabPressed = gui_isKeyDown(WXK_TAB); - const bool ctrlPressed = gui_isKeyDown(0xA2); // VK_LCONTROL + const bool tabPressed = gui_isKeyDown(PlatformKeyCodes::TAB); + const bool ctrlPressed = gui_isKeyDown(PlatformKeyCodes::LCONTROL); + bool showDRC = swkbd_hasKeyboardInputHook() == false && tabPressed; + bool& alwaysDisplayDRC = LatteGPUState.alwaysDisplayDRC; if (ctrlPressed && tabPressed) { @@ -1131,4 +1132,4 @@ void LatteRenderTarget_unloadAll() LatteMRT::DeleteCachedFBO(g_emptyFBO); g_emptyFBO = nullptr; } -} \ No newline at end of file +} diff --git a/src/config/ActiveSettings.cpp b/src/config/ActiveSettings.cpp index bef9cf0b..f469c5e3 100644 --- a/src/config/ActiveSettings.cpp +++ b/src/config/ActiveSettings.cpp @@ -11,8 +11,6 @@ #include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h" #include "Cafe/CafeSystem.h" -extern bool alwaysDisplayDRC; - std::set ActiveSettings::LoadOnce(const fs::path& user_data_path, const fs::path& config_path, @@ -57,7 +55,6 @@ bool ActiveSettings::LoadSharedLibrariesEnabled() bool ActiveSettings::DisplayDRCEnabled() { - alwaysDisplayDRC = g_current_game_profile->StartWithGamepadView(); return g_current_game_profile->StartWithGamepadView(); } diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 0a2ecc7b..a08891db 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -147,6 +147,11 @@ target_link_libraries(CemuGui PRIVATE ZArchive::zarchive ) +if(ENABLE_WXWIDGETS AND UNIX AND NOT APPLE) + # PUBLIC because gdk/gdkkeysyms.h is included in guiWrapper.h + target_link_libraries(CemuGui PUBLIC GTK3::gtk) +endif() + if(ENABLE_CUBEB) target_link_libraries(CemuGui PRIVATE cubeb::cubeb) endif() diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index 1de007fb..02a360a9 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -218,9 +218,11 @@ int CemuApp::FilterEvent(wxEvent& event) const auto& key_event = (wxKeyEvent&)event; g_window_info.set_keystate(fix_raw_keycode(key_event.GetRawKeyCode(), key_event.GetRawKeyFlags()), false); } - else if(event.GetEventType() == wxEVT_KILL_FOCUS) + else if(event.GetEventType() == wxEVT_ACTIVATE_APP) { - g_window_info.set_keystatesdown(); + const auto& activate_event = (wxActivateEvent&)event; + if(!activate_event.GetActive()) + g_window_info.set_keystatesup(); } return wxApp::FilterEvent(event); diff --git a/src/gui/guiWrapper.cpp b/src/gui/guiWrapper.cpp index 4d840cf4..0f1b6df8 100644 --- a/src/gui/guiWrapper.cpp +++ b/src/gui/guiWrapper.cpp @@ -1,3 +1,10 @@ +#if BOOST_OS_LINUX +#include +#include +#include +#include +#endif + #include "gui/wxgui.h" #include "gui/guiWrapper.h" #include "gui/CemuApp.h" @@ -156,19 +163,10 @@ bool gui_isPadWindowOpen() } #if BOOST_OS_LINUX -#include -#include - -typedef void GdkDisplay; -namespace -{ -const char* (*gdk_keyval_name)(unsigned int keyval); -} std::string gui_gtkRawKeyCodeToString(uint32 keyCode) { return gdk_keyval_name(keyCode); } - #endif void gui_initHandleContextFromWxWidgetsWindow(WindowHandleInfo& handleInfoOut, class wxWindow* wxw) @@ -176,43 +174,15 @@ void gui_initHandleContextFromWxWidgetsWindow(WindowHandleInfo& handleInfoOut, c #if BOOST_OS_WINDOWS handleInfoOut.hwnd = wxw->GetHWND(); #elif BOOST_OS_LINUX - /* dynamically retrieve GTK imports so we dont have to include and link the whole lib */ - void (*dyn_gtk_widget_realize)(GtkWidget *widget); - dyn_gtk_widget_realize = (void(*)(GtkWidget* widget))dlsym(RTLD_NEXT, "gtk_widget_realize"); - - GdkWindow* (*dyn_gtk_widget_get_window)(GtkWidget *widget); - dyn_gtk_widget_get_window = (GdkWindow*(*)(GtkWidget* widget))dlsym(RTLD_NEXT, "gtk_widget_get_window"); - - GdkDisplay* (*dyn_gdk_window_get_display)(GdkWindow *widget); - dyn_gdk_window_get_display = (GdkDisplay*(*)(GdkWindow* window))dlsym(RTLD_NEXT, "gdk_window_get_display"); - - Display* (*dyn_gdk_x11_display_get_xdisplay)(GdkDisplay *display); - dyn_gdk_x11_display_get_xdisplay = (Display*(*)(GdkDisplay* display))dlsym(RTLD_NEXT, "gdk_x11_display_get_xdisplay"); - - Window (*dyn_gdk_x11_window_get_xid)(GdkWindow *window); - dyn_gdk_x11_window_get_xid = (Window(*)(GdkWindow *window))dlsym(RTLD_NEXT, "gdk_x11_window_get_xid"); - - gdk_keyval_name = (const char* (*)(unsigned int))dlsym(RTLD_NEXT, "gdk_keyval_name"); - - if(!dyn_gtk_widget_realize || !dyn_gtk_widget_get_window || - !dyn_gdk_window_get_display || !dyn_gdk_x11_display_get_xdisplay || - !dyn_gdk_x11_window_get_xid || !gdk_keyval_name) - { - cemuLog_log(LogType::Force, "Unable to load GDK symbols"); - return; - } - - /* end of imports */ - // get window GtkWidget* gtkWidget = (GtkWidget*)wxw->GetHandle(); // returns GtkWidget - dyn_gtk_widget_realize(gtkWidget); - GdkWindow* gdkWindow = dyn_gtk_widget_get_window(gtkWidget); - handleInfoOut.xlib_window = dyn_gdk_x11_window_get_xid(gdkWindow); + gtk_widget_realize(gtkWidget); + GdkWindow* gdkWindow = gtk_widget_get_window(gtkWidget); + handleInfoOut.xlib_window = gdk_x11_window_get_xid(gdkWindow); // get display - GdkDisplay* gdkDisplay = dyn_gdk_window_get_display(gdkWindow); - handleInfoOut.xlib_display = dyn_gdk_x11_display_get_xdisplay(gdkDisplay); + GdkDisplay* gdkDisplay = gdk_window_get_display(gdkWindow); + handleInfoOut.xlib_display = gdk_x11_display_get_xdisplay(gdkDisplay); if(!handleInfoOut.xlib_display) { cemuLog_log(LogType::Force, "Unable to get xlib display"); @@ -222,11 +192,16 @@ void gui_initHandleContextFromWxWidgetsWindow(WindowHandleInfo& handleInfoOut, c #endif } -bool gui_isKeyDown(int key) +bool gui_isKeyDown(uint32 key) { return g_window_info.get_keystate(key); } +bool gui_isKeyDown(PlatformKeyCodes key) +{ + return gui_isKeyDown((std::underlying_type_t)key); +} + void gui_notifyGameLoaded() { std::shared_lock lock(g_mutex); @@ -311,4 +286,4 @@ void debuggerWindow_notifyModuleUnloaded(void* module) evt->SetClientData(module); wxQueueEvent(g_debugger_window, evt); } -} \ No newline at end of file +} diff --git a/src/gui/guiWrapper.h b/src/gui/guiWrapper.h index 4f46f8b4..e57e52fe 100644 --- a/src/gui/guiWrapper.h +++ b/src/gui/guiWrapper.h @@ -4,6 +4,7 @@ #if BOOST_OS_LINUX #include "xcb/xproto.h" +#include #endif struct WindowHandleInfo @@ -25,6 +26,23 @@ struct WindowHandleInfo #endif }; +enum struct PlatformKeyCodes : uint32 +{ +#if BOOST_OS_WINDOWS + LCONTROL = VK_LCONTROL, + RCONTROL = VK_RCONTROL, + TAB = VK_TAB, +#elif BOOST_OS_LINUX + LCONTROL = GDK_KEY_Control_L, + RCONTROL = GDK_KEY_Control_R, + TAB = GDK_KEY_Tab, +#else + LCONTROL = 0, + RCONTROL = 0, + TAB = 0, +#endif +}; + struct WindowInfo { std::atomic_bool app_active; // our app is active/has focus @@ -56,7 +74,7 @@ struct WindowInfo return result->second; } - void set_keystatesdown() + void set_keystatesup() { const std::lock_guard lock(keycode_mutex); std::for_each(m_keydown.begin(), m_keydown.end(), [](std::pair& el){ el.second = false; }); @@ -89,7 +107,8 @@ void gui_updateWindowTitles(bool isIdle, bool isLoading, double fps); void gui_getWindowSize(int* w, int* h); void gui_getPadWindowSize(int* w, int* h); bool gui_isPadWindowOpen(); -bool gui_isKeyDown(int key); +bool gui_isKeyDown(uint32 key); +bool gui_isKeyDown(PlatformKeyCodes key); void gui_notifyGameLoaded(); void gui_notifyGameExited(); @@ -114,4 +133,4 @@ void debuggerWindow_notifyDebugBreakpointHit2(); void debuggerWindow_notifyRun(); void debuggerWindow_moveIP(); void debuggerWindow_notifyModuleLoaded(void* module); -void debuggerWindow_notifyModuleUnloaded(void* module); \ No newline at end of file +void debuggerWindow_notifyModuleUnloaded(void* module); diff --git a/src/input/api/Keyboard/KeyboardController.cpp b/src/input/api/Keyboard/KeyboardController.cpp index 9cd31b4b..1f5458fa 100644 --- a/src/input/api/Keyboard/KeyboardController.cpp +++ b/src/input/api/Keyboard/KeyboardController.cpp @@ -50,11 +50,8 @@ extern WindowInfo g_window_info; ControllerState KeyboardController::raw_state() { ControllerState result{}; - if (g_window_info.app_active) - { - boost::container::small_vector pressedKeys; - g_window_info.iter_keystates([&pressedKeys](const std::pair& keyState) { if (keyState.second) pressedKeys.emplace_back(keyState.first); }); - result.buttons.SetPressedButtons(pressedKeys); - } + boost::container::small_vector pressedKeys; + g_window_info.iter_keystates([&pressedKeys](const std::pair& keyState) { if (keyState.second) pressedKeys.emplace_back(keyState.first); }); + result.buttons.SetPressedButtons(pressedKeys); return result; }