mirror of
https://github.com/rt64/rt64.git
synced 2024-12-26 21:18:31 +00:00
Add inspector with hooks for SDL2. (#75)
* Add inspector with hooks for SDL2. * Fix build errors. * Add the remaining SDL2 implementation that was required.
This commit is contained in:
parent
1812bc03c3
commit
88c618c1f8
@ -333,6 +333,7 @@ set (SOURCES
|
|||||||
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/imgui_draw.cpp"
|
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/imgui_draw.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/imgui_tables.cpp"
|
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/imgui_tables.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/imgui_widgets.cpp"
|
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/imgui_widgets.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/backends/imgui_impl_sdl2.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/backends/imgui_impl_vulkan.cpp"
|
"${PROJECT_SOURCE_DIR}/src/contrib/imgui/backends/imgui_impl_vulkan.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/src/contrib/im3d/im3d.cpp"
|
"${PROJECT_SOURCE_DIR}/src/contrib/im3d/im3d.cpp"
|
||||||
"${PROJECT_SOURCE_DIR}/src/contrib/implot/implot.cpp"
|
"${PROJECT_SOURCE_DIR}/src/contrib/implot/implot.cpp"
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
#include "implot/implot.h"
|
#include "implot/implot.h"
|
||||||
|
|
||||||
|
// Volk must be included before the ImGui Vulkan backend.
|
||||||
|
#include "vulkan/rt64_vulkan.h"
|
||||||
|
|
||||||
|
#include "imgui/backends/imgui_impl_sdl2.h"
|
||||||
|
#include "imgui/backends/imgui_impl_vulkan.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
# include "imgui/backends/imgui_impl_dx12.h"
|
# include "imgui/backends/imgui_impl_dx12.h"
|
||||||
# include "imgui/backends/imgui_impl_win32.h"
|
# include "imgui/backends/imgui_impl_win32.h"
|
||||||
@ -22,10 +28,6 @@
|
|||||||
# include "d3d12/rt64_d3d12.h"
|
# include "d3d12/rt64_d3d12.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Volk must be included before the ImGui Vulkan backend.
|
|
||||||
#include "vulkan/rt64_vulkan.h"
|
|
||||||
#include "imgui/backends/imgui_impl_vulkan.h"
|
|
||||||
|
|
||||||
static std::string IniFilenameUTF8;
|
static std::string IniFilenameUTF8;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -59,13 +61,14 @@ namespace RT64 {
|
|||||||
|
|
||||||
// Inspector
|
// Inspector
|
||||||
|
|
||||||
Inspector::Inspector(RenderDevice *device, const RenderSwapChain *swapChain, UserConfiguration::GraphicsAPI graphicsAPI) {
|
Inspector::Inspector(RenderDevice *device, const RenderSwapChain *swapChain, UserConfiguration::GraphicsAPI graphicsAPI, SDL_Window *sdlWindow) {
|
||||||
assert(device != nullptr);
|
assert(device != nullptr);
|
||||||
assert(swapChain != nullptr);
|
assert(swapChain != nullptr);
|
||||||
|
|
||||||
this->device = device;
|
this->device = device;
|
||||||
this->swapChain = swapChain;
|
this->swapChain = swapChain;
|
||||||
this->graphicsAPI = graphicsAPI;
|
this->graphicsAPI = graphicsAPI;
|
||||||
|
this->sdlWindow = sdlWindow;
|
||||||
|
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
|
|
||||||
@ -73,10 +76,15 @@ namespace RT64 {
|
|||||||
ImPlot::CreateContext();
|
ImPlot::CreateContext();
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
# ifdef _WIN32
|
if (sdlWindow != nullptr) {
|
||||||
RenderWindow renderWindow = swapChain->getWindow();
|
ImGui_ImplSDL2_InitForOther(sdlWindow);
|
||||||
ImGui_ImplWin32_Init(renderWindow);
|
}
|
||||||
# endif
|
else {
|
||||||
|
# ifdef _WIN32
|
||||||
|
RenderWindow renderWindow = swapChain->getWindow();
|
||||||
|
ImGui_ImplWin32_Init(renderWindow);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
switch (graphicsAPI) {
|
switch (graphicsAPI) {
|
||||||
case UserConfiguration::GraphicsAPI::D3D12: {
|
case UserConfiguration::GraphicsAPI::D3D12: {
|
||||||
@ -153,11 +161,14 @@ namespace RT64 {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef _WIN32
|
if (sdlWindow != nullptr) {
|
||||||
ImGui_ImplWin32_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
# else
|
}
|
||||||
assert(false && "Unimplemented.");
|
else {
|
||||||
# endif
|
# ifdef _WIN32
|
||||||
|
ImGui_ImplWin32_Shutdown();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
ImPlot::DestroyContext();
|
ImPlot::DestroyContext();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
@ -173,12 +184,15 @@ namespace RT64 {
|
|||||||
assert(worker != nullptr);
|
assert(worker != nullptr);
|
||||||
|
|
||||||
frameMutex.lock();
|
frameMutex.lock();
|
||||||
|
|
||||||
# ifdef _WIN32
|
if (sdlWindow != nullptr) {
|
||||||
ImGui_ImplWin32_NewFrame();
|
ImGui_ImplSDL2_NewFrame();
|
||||||
# else
|
}
|
||||||
assert(false && "Unimplemented.");
|
else {
|
||||||
# endif
|
# ifdef _WIN32
|
||||||
|
ImGui_ImplWin32_NewFrame();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
switch (graphicsAPI) {
|
switch (graphicsAPI) {
|
||||||
case UserConfiguration::GraphicsAPI::D3D12: {
|
case UserConfiguration::GraphicsAPI::D3D12: {
|
||||||
@ -240,4 +254,20 @@ namespace RT64 {
|
|||||||
return ImGui_ImplWin32_WndProcHandler(swapChain->getWindow(), msg, wParam, lParam);
|
return ImGui_ImplWin32_WndProcHandler(swapChain->getWindow(), msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool Inspector::handleSdlEvent(SDL_Event *event) {
|
||||||
|
assert((sdlWindow != nullptr) && "SDL Events shouldn't be handled if SDL was not used.");
|
||||||
|
|
||||||
|
bool processed = ImGui_ImplSDL2_ProcessEvent(event);
|
||||||
|
if (processed) {
|
||||||
|
if ((event->type == SDL_KEYDOWN) || (event->type == SDL_KEYUP)) {
|
||||||
|
return ImGui::GetIO().WantCaptureKeyboard;
|
||||||
|
}
|
||||||
|
else if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_MOUSEBUTTONDOWN) || (event->type == SDL_MOUSEBUTTONUP) || (event->type == SDL_MOUSEWHEEL)) {
|
||||||
|
return ImGui::GetIO().WantCaptureMouse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
@ -14,6 +14,7 @@
|
|||||||
#include "common/rt64_common.h"
|
#include "common/rt64_common.h"
|
||||||
#include "common/rt64_user_configuration.h"
|
#include "common/rt64_user_configuration.h"
|
||||||
#include "render/rt64_render_worker.h"
|
#include "render/rt64_render_worker.h"
|
||||||
|
#include "hle/rt64_application_window.h"
|
||||||
#include "rhi/rt64_render_interface.h"
|
#include "rhi/rt64_render_interface.h"
|
||||||
|
|
||||||
namespace RT64 {
|
namespace RT64 {
|
||||||
@ -22,12 +23,13 @@ namespace RT64 {
|
|||||||
struct Inspector {
|
struct Inspector {
|
||||||
RenderDevice *device = nullptr;
|
RenderDevice *device = nullptr;
|
||||||
const RenderSwapChain *swapChain = nullptr;
|
const RenderSwapChain *swapChain = nullptr;
|
||||||
|
UserConfiguration::GraphicsAPI graphicsAPI;
|
||||||
|
SDL_Window *sdlWindow = nullptr;
|
||||||
std::unique_ptr<RenderDescriptorSet> descriptorSet;
|
std::unique_ptr<RenderDescriptorSet> descriptorSet;
|
||||||
std::unique_ptr<VulkanContext> vulkanContext;
|
std::unique_ptr<VulkanContext> vulkanContext;
|
||||||
UserConfiguration::GraphicsAPI graphicsAPI;
|
|
||||||
std::mutex frameMutex;
|
std::mutex frameMutex;
|
||||||
|
|
||||||
Inspector(RenderDevice *device, const RenderSwapChain *swapChain, UserConfiguration::GraphicsAPI graphicsAPI);
|
Inspector(RenderDevice *device, const RenderSwapChain *swapChain, UserConfiguration::GraphicsAPI graphicsAPI, SDL_Window *sdlWindow);
|
||||||
~Inspector();
|
~Inspector();
|
||||||
void setIniPath(const std::filesystem::path &path);
|
void setIniPath(const std::filesystem::path &path);
|
||||||
void newFrame(RenderWorker *worker);
|
void newFrame(RenderWorker *worker);
|
||||||
@ -36,5 +38,6 @@ namespace RT64 {
|
|||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
bool handleMessage(UINT msg, WPARAM wParam, LPARAM lParam);
|
bool handleMessage(UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
# endif
|
# endif
|
||||||
|
bool handleSdlEvent(SDL_Event *event);
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -390,6 +390,7 @@ namespace RT64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateScreen() {
|
void Application::updateScreen() {
|
||||||
|
appWindow->sdlCheckFilterInstallation();
|
||||||
screenApiProfiler.logAndRestart();
|
screenApiProfiler.logAndRestart();
|
||||||
state->updateScreen(core.decodeVI(), false);
|
state->updateScreen(core.decodeVI(), false);
|
||||||
}
|
}
|
||||||
@ -448,43 +449,20 @@ namespace RT64 {
|
|||||||
switch (message) {
|
switch (message) {
|
||||||
case WM_KEYDOWN: {
|
case WM_KEYDOWN: {
|
||||||
switch (wParam) {
|
switch (wParam) {
|
||||||
case VK_F1: {
|
case VK_F1:
|
||||||
if (userConfig.developerMode) {
|
processDeveloperShortcut(DeveloperShortcut::Inspector);
|
||||||
const std::lock_guard<std::mutex> lock(presentQueue->inspectorMutex);
|
|
||||||
if (presentQueue->inspector == nullptr) {
|
|
||||||
presentQueue->inspector = std::make_unique<Inspector>(device.get(), swapChain.get(), createdGraphicsAPI);
|
|
||||||
if (!userPaths.isEmpty()) {
|
|
||||||
presentQueue->inspector->setIniPath(userPaths.imguiPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
freeCamClearQueued = true;
|
|
||||||
appWindow->blockSdlKeyboard();
|
|
||||||
}
|
|
||||||
else if (presentQueue->inspector != nullptr) {
|
|
||||||
presentQueue->inspector.reset(nullptr);
|
|
||||||
appWindow->unblockSdlKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stdout, "Inspector is not available: developer mode is not enabled in the configuration.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
case VK_F2:
|
||||||
case VK_F2: {
|
processDeveloperShortcut(DeveloperShortcut::RayTracing);
|
||||||
workloadQueue->rtEnabled = !workloadQueue->rtEnabled;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
case VK_F3:
|
||||||
case VK_F3: {
|
processDeveloperShortcut(DeveloperShortcut::ViewRDRAM);
|
||||||
presentQueue->viewRDRAM = !presentQueue->viewRDRAM;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
case VK_F4:
|
||||||
case VK_F4: {
|
processDeveloperShortcut(DeveloperShortcut::Replacements);
|
||||||
textureCache->textureMap.replacementMapEnabled = !textureCache->textureMap.replacementMapEnabled;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
// Ignore key.
|
// Unknown shortcut.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,11 +470,82 @@ namespace RT64 {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Application::sdlEventFilter(SDL_Event *event) {
|
||||||
|
if (userConfig.developerMode && (presentQueue != nullptr) && (state != nullptr) && !FileDialog::isOpen) {
|
||||||
|
const std::lock_guard<std::mutex> lock(presentQueue->inspectorMutex);
|
||||||
|
if ((presentQueue->inspector != nullptr) && presentQueue->inspector->handleSdlEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->type == SDL_KEYDOWN) {
|
||||||
|
switch (event->key.keysym.scancode) {
|
||||||
|
case SDL_SCANCODE_F1:
|
||||||
|
processDeveloperShortcut(DeveloperShortcut::Inspector);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_F2:
|
||||||
|
processDeveloperShortcut(DeveloperShortcut::RayTracing);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_F3:
|
||||||
|
processDeveloperShortcut(DeveloperShortcut::ViewRDRAM);
|
||||||
|
return true;
|
||||||
|
case SDL_SCANCODE_F4:
|
||||||
|
processDeveloperShortcut(DeveloperShortcut::Replacements);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
// Don't filter the key event.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::usesWindowMessageFilter() {
|
bool Application::usesWindowMessageFilter() {
|
||||||
return userConfig.developerMode;
|
return userConfig.developerMode;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
void Application::processDeveloperShortcut(DeveloperShortcut developerShortcut) {
|
||||||
|
switch (developerShortcut) {
|
||||||
|
case DeveloperShortcut::Inspector: {
|
||||||
|
if (userConfig.developerMode) {
|
||||||
|
const std::lock_guard<std::mutex> lock(presentQueue->inspectorMutex);
|
||||||
|
if (presentQueue->inspector == nullptr) {
|
||||||
|
presentQueue->inspector = std::make_unique<Inspector>(device.get(), swapChain.get(), createdGraphicsAPI, appWindow->sdlWindow);
|
||||||
|
if (!userPaths.isEmpty()) {
|
||||||
|
presentQueue->inspector->setIniPath(userPaths.imguiPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeCamClearQueued = true;
|
||||||
|
}
|
||||||
|
else if (presentQueue->inspector != nullptr) {
|
||||||
|
presentQueue->inspector.reset(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stdout, "Inspector is not available: developer mode is not enabled in the configuration.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DeveloperShortcut::RayTracing: {
|
||||||
|
workloadQueue->rtEnabled = !workloadQueue->rtEnabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DeveloperShortcut::ViewRDRAM: {
|
||||||
|
presentQueue->viewRDRAM = !presentQueue->viewRDRAM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DeveloperShortcut::Replacements: {
|
||||||
|
textureCache->textureMap.replacementMapEnabled = !textureCache->textureMap.replacementMapEnabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void Application::end() {
|
void Application::end() {
|
||||||
# if SCRIPT_ENABLED
|
# if SCRIPT_ENABLED
|
||||||
|
@ -51,6 +51,13 @@ namespace RT64 {
|
|||||||
GraphicsDeviceNotFound
|
GraphicsDeviceNotFound
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DeveloperShortcut {
|
||||||
|
Inspector,
|
||||||
|
RayTracing,
|
||||||
|
ViewRDRAM,
|
||||||
|
Replacements
|
||||||
|
};
|
||||||
|
|
||||||
struct Core {
|
struct Core {
|
||||||
RenderWindow window;
|
RenderWindow window;
|
||||||
uint8_t *HEADER;
|
uint8_t *HEADER;
|
||||||
@ -159,8 +166,10 @@ namespace RT64 {
|
|||||||
bool checkDirectoryCreated(const std::filesystem::path &path);
|
bool checkDirectoryCreated(const std::filesystem::path &path);
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
bool windowMessageFilter(unsigned int message, WPARAM wParam, LPARAM lParam) override;
|
bool windowMessageFilter(unsigned int message, WPARAM wParam, LPARAM lParam) override;
|
||||||
bool usesWindowMessageFilter() override;
|
|
||||||
# endif
|
# endif
|
||||||
|
bool sdlEventFilter(SDL_Event *event) override;
|
||||||
|
bool usesWindowMessageFilter() override;
|
||||||
|
void processDeveloperShortcut(DeveloperShortcut developerShortcut);
|
||||||
void updateUserConfig(bool discardFBs);
|
void updateUserConfig(bool discardFBs);
|
||||||
void updateEmulatorConfig();
|
void updateEmulatorConfig();
|
||||||
void updateEnhancementConfig();
|
void updateEnhancementConfig();
|
||||||
|
@ -23,16 +23,7 @@ namespace RT64 {
|
|||||||
ApplicationWindow *ApplicationWindow::HookedApplicationWindow = nullptr;
|
ApplicationWindow *ApplicationWindow::HookedApplicationWindow = nullptr;
|
||||||
|
|
||||||
ApplicationWindow::ApplicationWindow() {
|
ApplicationWindow::ApplicationWindow() {
|
||||||
windowHandle = {};
|
// Empty.
|
||||||
sdlEventFilterUserdata = nullptr;
|
|
||||||
sdlEventFilterStored = false;
|
|
||||||
fullScreen = false;
|
|
||||||
lastMaximizedState = false;
|
|
||||||
# ifdef _WIN32
|
|
||||||
windowHook = nullptr;
|
|
||||||
windowMenu = nullptr;
|
|
||||||
# endif
|
|
||||||
usingSdl = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationWindow::~ApplicationWindow() {
|
ApplicationWindow::~ApplicationWindow() {
|
||||||
@ -51,16 +42,27 @@ namespace RT64 {
|
|||||||
assert(listener != nullptr);
|
assert(listener != nullptr);
|
||||||
|
|
||||||
this->listener = listener;
|
this->listener = listener;
|
||||||
windowHandle = window;
|
|
||||||
|
|
||||||
# ifdef _WIN32
|
windowHandle = window;
|
||||||
|
|
||||||
if (listener->usesWindowMessageFilter()) {
|
if (listener->usesWindowMessageFilter()) {
|
||||||
assert(HookedApplicationWindow == nullptr);
|
if ((sdlWindow == nullptr) && SDL_WasInit(SDL_INIT_VIDEO)) {
|
||||||
assert(threadId != 0);
|
// We'd normally install the event filter here, but Mupen does not set its own event filter
|
||||||
windowHook = SetWindowsHookEx(WH_GETMESSAGE, &windowHookCallback, NULL, threadId);
|
// until much later. Instead, we delegate this to the first time a screen update is sent.
|
||||||
HookedApplicationWindow = this;
|
// FIXME: We attempt to get the first window created by SDL2. This can be improved later
|
||||||
|
// by actually passing the SDL_Window handle through as a parameter.
|
||||||
|
sdlWindow = SDL_GetWindowFromID(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdlWindow == nullptr) {
|
||||||
|
# ifdef _WIN32
|
||||||
|
assert(HookedApplicationWindow == nullptr);
|
||||||
|
assert(threadId != 0);
|
||||||
|
windowHook = SetWindowsHookEx(WH_GETMESSAGE, &windowHookCallback, NULL, threadId);
|
||||||
|
HookedApplicationWindow = this;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationWindow::setup(const char *windowTitle, Listener *listener) {
|
void ApplicationWindow::setup(const char *windowTitle, Listener *listener) {
|
||||||
@ -71,7 +73,7 @@ namespace RT64 {
|
|||||||
const int Height = 720;
|
const int Height = 720;
|
||||||
struct {
|
struct {
|
||||||
uint32_t left, top, width, height;
|
uint32_t left, top, width, height;
|
||||||
} bounds {};
|
} bounds{};
|
||||||
|
|
||||||
# if defined(_WIN32)
|
# if defined(_WIN32)
|
||||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
@ -108,12 +110,13 @@ namespace RT64 {
|
|||||||
# else
|
# else
|
||||||
static_assert(false && "Unimplemented");
|
static_assert(false && "Unimplemented");
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// Create window.
|
// Create window.
|
||||||
#ifdef RT64_SDL_WINDOW
|
sdlWindow = SDL_CreateWindow(windowTitle, bounds.left, bounds.top, bounds.width, bounds.height, SDL_WINDOW_RESIZABLE);
|
||||||
SDL_Window *sdlWindow = SDL_CreateWindow(windowTitle, bounds.left, bounds.top, bounds.width, bounds.height, SDL_WINDOW_RESIZABLE);
|
assert((sdlWindow != nullptr) && "Failed to open window with SDL");
|
||||||
|
|
||||||
|
// Get native window handles from the window.
|
||||||
SDL_SysWMinfo wmInfo;
|
SDL_SysWMinfo wmInfo;
|
||||||
assert(sdlWindow && "Failed to open window with SDL");
|
|
||||||
SDL_VERSION(&wmInfo.version);
|
SDL_VERSION(&wmInfo.version);
|
||||||
SDL_GetWindowWMInfo(sdlWindow, &wmInfo);
|
SDL_GetWindowWMInfo(sdlWindow, &wmInfo);
|
||||||
# if defined(_WIN32)
|
# if defined(_WIN32)
|
||||||
@ -128,10 +131,6 @@ namespace RT64 {
|
|||||||
# else
|
# else
|
||||||
static_assert(false && "Unimplemented");
|
static_assert(false && "Unimplemented");
|
||||||
# endif
|
# endif
|
||||||
usingSdl = true;
|
|
||||||
#else
|
|
||||||
static_assert(false && "Unimplemented");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
setup(windowHandle, listener, GetCurrentThreadId());
|
setup(windowHandle, listener, GetCurrentThreadId());
|
||||||
@ -305,7 +304,7 @@ namespace RT64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void ApplicationWindow::windowMessage(UINT message, WPARAM wParam, LPARAM lParam) {
|
void ApplicationWindow::windowMessage(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
if (listener->windowMessageFilter(message, wParam, lParam)) {
|
if (listener->windowMessageFilter(message, wParam, lParam)) {
|
||||||
return;
|
return;
|
||||||
@ -326,47 +325,34 @@ namespace RT64 {
|
|||||||
|
|
||||||
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
}
|
}
|
||||||
# endif
|
|
||||||
|
|
||||||
#ifdef RT64_SDL_WINDOW
|
|
||||||
void ApplicationWindow::blockSdlKeyboard() {
|
|
||||||
if (!usingSdl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sdlEventFilterStored = SDL_GetEventFilter(&sdlEventFilter, &sdlEventFilterUserdata);
|
|
||||||
if (sdlEventFilterStored) {
|
|
||||||
SDL_SetEventFilter(&ApplicationWindow::sdlEventKeyboardFilter, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplicationWindow::unblockSdlKeyboard() {
|
|
||||||
if (!usingSdl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sdlEventFilterStored) {
|
|
||||||
SDL_SetEventFilter(sdlEventFilter, sdlEventFilterUserdata);
|
|
||||||
sdlEventFilterStored = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ApplicationWindow::sdlEventKeyboardFilter(void *userdata, SDL_Event *event) {
|
|
||||||
ApplicationWindow *appWindow = reinterpret_cast<ApplicationWindow *>(userdata);
|
|
||||||
|
|
||||||
switch (event->type) {
|
|
||||||
// Ignore all keyboard events.
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
case SDL_KEYUP:
|
|
||||||
return 0;
|
|
||||||
// Pass through to the original event filter.
|
|
||||||
default:
|
|
||||||
return appWindow->sdlEventFilter(userdata, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
static_assert(false && "Unimplemented");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void ApplicationWindow::sdlCheckFilterInstallation() {
|
||||||
|
if (!sdlEventFilterInstalled && (sdlWindow != nullptr)) {
|
||||||
|
if (!SDL_GetEventFilter(&sdlEventFilterStored, &sdlEventFilterUserdata)) {
|
||||||
|
sdlEventFilterStored = nullptr;
|
||||||
|
sdlEventFilterUserdata = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetEventFilter(&ApplicationWindow::sdlEventFilter, this);
|
||||||
|
sdlEventFilterInstalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ApplicationWindow::sdlEventFilter(void *userdata, SDL_Event *event) {
|
||||||
|
// Run it through the listener's event filter. If it's processed by the listener, the event should be filtered.
|
||||||
|
ApplicationWindow *appWindow = reinterpret_cast<ApplicationWindow *>(userdata);
|
||||||
|
if (appWindow->listener->sdlEventFilter(event)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass to the event filter that was stored if it exists. Let the original filter determine the result.
|
||||||
|
if (appWindow->sdlEventFilterStored != nullptr) {
|
||||||
|
return appWindow->sdlEventFilterStored(appWindow->sdlEventFilterUserdata, event);
|
||||||
|
}
|
||||||
|
// The event should not be filtered.
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -9,41 +9,45 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RT64_SDL_WINDOW
|
#include "SDL.h"
|
||||||
|
#include "SDL_events.h"
|
||||||
#ifdef RT64_SDL_WINDOW
|
#include "SDL_system.h"
|
||||||
# include "SDL_events.h"
|
#include "SDL_syswm.h"
|
||||||
# include "SDL_system.h"
|
#include "SDL_video.h"
|
||||||
# include "SDL_syswm.h"
|
|
||||||
# include "SDL_video.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace RT64 {
|
namespace RT64 {
|
||||||
struct ApplicationWindow {
|
struct ApplicationWindow {
|
||||||
static ApplicationWindow *HookedApplicationWindow;
|
static ApplicationWindow *HookedApplicationWindow;
|
||||||
|
|
||||||
struct Listener {
|
struct Listener {
|
||||||
|
virtual bool usesWindowMessageFilter() = 0;
|
||||||
|
|
||||||
// Return true if the listener should accept and handle the message.
|
// Return true if the listener should accept and handle the message.
|
||||||
// Return false otherwise for the default message handler to take over.
|
// Return false otherwise for the default message handler to take over.
|
||||||
|
virtual bool sdlEventFilter(SDL_Event *event) = 0;
|
||||||
|
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
virtual bool windowMessageFilter(unsigned int message, WPARAM wParam, LPARAM lParam) = 0;
|
virtual bool windowMessageFilter(unsigned int message, WPARAM wParam, LPARAM lParam) = 0;
|
||||||
virtual bool usesWindowMessageFilter() = 0;
|
|
||||||
# endif
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderWindow windowHandle;
|
RenderWindow windowHandle = {};
|
||||||
# ifdef _WIN32
|
|
||||||
HHOOK windowHook;
|
|
||||||
HMENU windowMenu;
|
|
||||||
RECT lastWindowRect;
|
|
||||||
# endif
|
|
||||||
Listener *listener;
|
Listener *listener;
|
||||||
uint32_t refreshRate = 0;
|
uint32_t refreshRate = 0;
|
||||||
bool fullScreen;
|
bool fullScreen = false;
|
||||||
bool lastMaximizedState;
|
bool lastMaximizedState = false;
|
||||||
bool usingSdl;
|
|
||||||
int32_t windowLeft = INT32_MAX;
|
int32_t windowLeft = INT32_MAX;
|
||||||
int32_t windowTop = INT32_MAX;
|
int32_t windowTop = INT32_MAX;
|
||||||
|
SDL_Window *sdlWindow = nullptr;
|
||||||
|
SDL_EventFilter sdlEventFilterStored = nullptr;
|
||||||
|
void *sdlEventFilterUserdata = nullptr;
|
||||||
|
bool sdlEventFilterInstalled = false;
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
HHOOK windowHook = nullptr;
|
||||||
|
HMENU windowMenu = nullptr;
|
||||||
|
RECT lastWindowRect = {};
|
||||||
|
# endif
|
||||||
|
|
||||||
ApplicationWindow();
|
ApplicationWindow();
|
||||||
~ApplicationWindow();
|
~ApplicationWindow();
|
||||||
@ -54,20 +58,12 @@ namespace RT64 {
|
|||||||
void detectRefreshRate();
|
void detectRefreshRate();
|
||||||
uint32_t getRefreshRate() const;
|
uint32_t getRefreshRate() const;
|
||||||
bool detectWindowMoved();
|
bool detectWindowMoved();
|
||||||
|
void sdlCheckFilterInstallation();
|
||||||
|
static int sdlEventFilter(void *userdata, SDL_Event *event);
|
||||||
|
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
void windowMessage(UINT message, WPARAM wParam, LPARAM lParam);
|
void windowMessage(UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
static LRESULT windowHookCallback(int nCode, WPARAM wParam, LPARAM lParam);
|
static LRESULT windowHookCallback(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef RT64_SDL_WINDOW
|
|
||||||
SDL_EventFilter sdlEventFilter;
|
|
||||||
void *sdlEventFilterUserdata;
|
|
||||||
bool sdlEventFilterStored;
|
|
||||||
|
|
||||||
void blockSdlKeyboard();
|
|
||||||
void unblockSdlKeyboard();
|
|
||||||
static int sdlEventKeyboardFilter(void *userdata, SDL_Event *event);
|
|
||||||
# endif
|
|
||||||
};
|
};
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user