1
0
mirror of synced 2024-11-15 03:27:40 +01:00

ux: Open files in existing ImHex instance if passed in as command line argument on windows

Closes #389
This commit is contained in:
WerWolv 2021-12-30 23:21:32 +01:00
parent 0884025b82
commit d3d9209b39
5 changed files with 62 additions and 9 deletions

View File

@ -7292,7 +7292,10 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
{ {
// We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
ImGuiWindow* window = g.WindowsFocusOrder[i]; ImGuiWindow* window = g.WindowsFocusOrder[i];
IM_ASSERT(window == window->RootWindow); //IM_ASSERT(window == window->RootWindow);
if (window != window->RootWindow)
return;
if (window != ignore_window && window->WasActive) if (window != ignore_window && window->WasActive)
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
{ {

View File

@ -14,7 +14,7 @@ namespace hex::init {
class WindowSplash { class WindowSplash {
public: public:
WindowSplash(int &argc, char **&argv, char **&envp); WindowSplash();
~WindowSplash(); ~WindowSplash();
bool loop(); bool loop();

View File

@ -26,11 +26,7 @@ using namespace std::literals::chrono_literals;
namespace hex::init { namespace hex::init {
WindowSplash::WindowSplash(int &argc, char **&argv, char **&envp) : m_window(nullptr) { WindowSplash::WindowSplash() : m_window(nullptr) {
SharedData::mainArgc = argc;
SharedData::mainArgv = argv;
SharedData::mainEnvp = envp;
this->initGLFW(); this->initGLFW();
this->initImGui(); this->initImGui();
} }
@ -179,7 +175,7 @@ namespace hex::init {
} }
} }
this->m_window = glfwCreateWindow(640 * SharedData::globalScale, 400 * SharedData::globalScale, "ImHex", nullptr, nullptr); this->m_window = glfwCreateWindow(640 * SharedData::globalScale, 400 * SharedData::globalScale, "Starting ImHex...", nullptr, nullptr);
if (this->m_window == nullptr) { if (this->m_window == nullptr) {
log::fatal("Failed to create GLFW window!"); log::fatal("Failed to create GLFW window!");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -2,6 +2,7 @@
#include <hex/helpers/utils.hpp> #include <hex/helpers/utils.hpp>
#include <hex/helpers/logger.hpp> #include <hex/helpers/logger.hpp>
#include <hex/helpers/shared_data.hpp>
#include "window.hpp" #include "window.hpp"
@ -11,13 +12,17 @@
#include <hex/helpers/file.hpp> #include <hex/helpers/file.hpp>
int main(int argc, char **argv, char **envp) { int main(int argc, char **argv, char **envp) {
hex::SharedData::mainArgc = argc;
hex::SharedData::mainArgv = argv;
hex::SharedData::mainEnvp = envp;
using namespace hex; using namespace hex;
// Initialization // Initialization
{ {
Window::initNative(); Window::initNative();
init::WindowSplash splashWindow(argc, argv, envp); init::WindowSplash splashWindow;
for (const auto &[name, task] : init::getInitTasks()) for (const auto &[name, task] : init::getInitTasks())
splashWindow.addStartupTask(name, task); splashWindow.addStartupTask(name, task);

View File

@ -145,6 +145,19 @@
break; break;
} }
case WM_COPYDATA:
{
auto message = reinterpret_cast<COPYDATASTRUCT*>(lParam);
if (message == nullptr) break;
auto path = reinterpret_cast<const char*>(message->lpData);
if (path == nullptr) break;
log::info("Opening file in existing instance: {}", path);
EventManager::post<RequestOpenFile>(path);
break;
}
default: break; default: break;
} }
@ -179,9 +192,44 @@
} }
} }
} }
// Open new files in already existing ImHex instance
constexpr static auto UniqueMutexId = "ImHex/a477ea68-e334-4d07-a439-4f159c683763";
HANDLE globalMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, UniqueMutexId);
if (!globalMutex) {
globalMutex = CreateMutex(nullptr, FALSE, UniqueMutexId);
} else {
if (SharedData::mainArgc > 1) {
::EnumWindows([](HWND hWnd, LPARAM lparam) -> BOOL {
auto length = ::GetWindowTextLength(hWnd);
std::string windowName(length + 1, '\x00');
::GetWindowText(hWnd, windowName.data(), windowName.size());
if (::IsWindowVisible(hWnd) && length != 0) {
if (windowName.starts_with("ImHex")) {
COPYDATASTRUCT message = {
.dwData = 0,
.cbData = static_cast<DWORD>(std::strlen(SharedData::mainArgv[1])) + 1,
.lpData = SharedData::mainArgv[1]
};
SendMessage(hWnd, WM_COPYDATA, reinterpret_cast<WPARAM>(hWnd), reinterpret_cast<LPARAM>(&message));
return FALSE;
}
}
return TRUE;
}, 0);
std::exit(0);
}
}
} }
void Window::setupNativeWindow() { void Window::setupNativeWindow() {
// Setup borderless window
auto hwnd = glfwGetWin32Window(this->m_window); auto hwnd = glfwGetWin32Window(this->m_window);
oldWndProc = ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)windowProc); oldWndProc = ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)windowProc);
@ -195,6 +243,7 @@
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE); ::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE);
::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW); ::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);
// Setup system theme change detector
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0; bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{ EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{
if (!themeFollowSystem) return; if (!themeFollowSystem) return;