windows平台代码修正
This commit is contained in:
1 parent
41151b7f8b
commit
005a3e7733
6 files changed
+80
-32
No files matched your search
@@ -77,7 +77,8 @@ void save_path(HWND window) {
|
|||||||
|
|
||||||
LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) {
|
LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) {
|
||||||
(void)lparam;
|
(void)lparam;
|
||||||
switch (message) {
|
try {
|
||||||
|
switch (message) {
|
||||||
case WM_CREATE: {
|
case WM_CREATE: {
|
||||||
HFONT font = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
|
HFONT font = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
|
||||||
HWND title = CreateWindowW(L"STATIC", L"Spine粒子连接器", WS_CHILD | WS_VISIBLE, 24, 20, 540, 34, window, nullptr, nullptr, nullptr);
|
HWND title = CreateWindowW(L"STATIC", L"Spine粒子连接器", WS_CHILD | WS_VISIBLE, 24, 20, 540, 34, window, nullptr, nullptr, nullptr);
|
||||||
@@ -133,8 +134,11 @@ LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lp
|
|||||||
break;
|
break;
|
||||||
case WM_CLOSE: DestroyWindow(window); return 0;
|
case WM_CLOSE: DestroyWindow(window); return 0;
|
||||||
case WM_DESTROY: service.stop(); PostQuitMessage(0); return 0;
|
case WM_DESTROY: service.stop(); PostQuitMessage(0); return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProcW(window, message, wparam, lparam);
|
||||||
|
} catch (...) {
|
||||||
|
return DefWindowProcW(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
return DefWindowProcW(window, message, wparam, lparam);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -142,7 +146,11 @@ LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lp
|
|||||||
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE previous, PWSTR command_line, int show) {
|
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE previous, PWSTR command_line, int show) {
|
||||||
(void)previous;
|
(void)previous;
|
||||||
(void)command_line;
|
(void)command_line;
|
||||||
service.start(startup_error);
|
try {
|
||||||
|
service.start(startup_error);
|
||||||
|
} catch (...) {
|
||||||
|
startup_error = "连接器启动失败";
|
||||||
|
}
|
||||||
const wchar_t* class_name = L"SpineParticleConnectorWindow";
|
const wchar_t* class_name = L"SpineParticleConnectorWindow";
|
||||||
WNDCLASSW window_class{};
|
WNDCLASSW window_class{};
|
||||||
window_class.lpfnWndProc = window_proc;
|
window_class.lpfnWndProc = window_proc;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
#include "platform.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -23,7 +24,7 @@ std::filesystem::path home_directory() {
|
|||||||
#else
|
#else
|
||||||
std::string home = environment("HOME");
|
std::string home = environment("HOME");
|
||||||
#endif
|
#endif
|
||||||
return home.empty() ? std::filesystem::current_path() : std::filesystem::u8path(home);
|
return home.empty() ? std::filesystem::current_path() : to_path(home);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool local_origin(const std::string& origin) {
|
bool local_origin(const std::string& origin) {
|
||||||
@@ -37,16 +38,16 @@ bool local_origin(const std::string& origin) {
|
|||||||
|
|
||||||
std::filesystem::path config_path() {
|
std::filesystem::path config_path() {
|
||||||
const std::string override_path = environment("SPINE_CONNECTOR_CONFIG");
|
const std::string override_path = environment("SPINE_CONNECTOR_CONFIG");
|
||||||
if (!override_path.empty()) return std::filesystem::u8path(override_path);
|
if (!override_path.empty()) return to_path(override_path);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::string app_data = environment("APPDATA");
|
std::string app_data = environment("APPDATA");
|
||||||
const auto root = app_data.empty() ? home_directory() : std::filesystem::u8path(app_data);
|
const auto root = app_data.empty() ? home_directory() : to_path(app_data);
|
||||||
return root / "SpineParticleConnector" / "config.json";
|
return root / "SpineParticleConnector" / "config.json";
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
return home_directory() / "Library" / "Application Support" / "SpineParticleConnector" / "config.json";
|
return home_directory() / "Library" / "Application Support" / "SpineParticleConnector" / "config.json";
|
||||||
#else
|
#else
|
||||||
std::string xdg = environment("XDG_CONFIG_HOME");
|
std::string xdg = environment("XDG_CONFIG_HOME");
|
||||||
const auto root = xdg.empty() ? home_directory() / ".config" : std::filesystem::u8path(xdg);
|
const auto root = xdg.empty() ? home_directory() / ".config" : to_path(xdg);
|
||||||
return root / "spine-particle-connector" / "config.json";
|
return root / "spine-particle-connector" / "config.json";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ struct ProcessResult {
|
|||||||
std::string output;
|
std::string output;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 构造 filesystem::path 时优先按 UTF-8 解释,若输入不是合法 UTF-8(例如
|
||||||
|
// Windows 环境变量里按系统代码页编码的中文路径)则回退到本地代码页构造,
|
||||||
|
// 避免 u8path 抛出 conversion_error 导致未捕获异常使程序崩溃。
|
||||||
|
std::filesystem::path to_path(const std::string& value);
|
||||||
|
|
||||||
std::string platform_name();
|
std::string platform_name();
|
||||||
std::string find_spine_executable();
|
std::string find_spine_executable();
|
||||||
bool valid_spine_executable(const std::string& path);
|
bool valid_spine_executable(const std::string& path);
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ void append_path_candidates(std::vector<std::filesystem::path>& candidates) {
|
|||||||
const auto end = value.find(delimiter, start);
|
const auto end = value.find(delimiter, start);
|
||||||
std::string item = value.substr(start, end - start);
|
std::string item = value.substr(start, end - start);
|
||||||
if (item.size() >= 2 && item.front() == '"' && item.back() == '"') item = item.substr(1, item.size() - 2);
|
if (item.size() >= 2 && item.front() == '"' && item.back() == '"') item = item.substr(1, item.size() - 2);
|
||||||
if (!item.empty()) candidates.push_back(std::filesystem::u8path(item) / name);
|
if (!item.empty()) {
|
||||||
|
const auto path = to_path(item);
|
||||||
|
if (!path.empty()) candidates.push_back(path / name);
|
||||||
|
}
|
||||||
if (end == std::string::npos) break;
|
if (end == std::string::npos) break;
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
}
|
}
|
||||||
@@ -35,6 +38,20 @@ void append_path_candidates(std::vector<std::filesystem::path>& candidates) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
std::filesystem::path to_path(const std::string& value) {
|
||||||
|
try {
|
||||||
|
return std::filesystem::u8path(value);
|
||||||
|
} catch (...) {
|
||||||
|
// 输入不是合法 UTF-8 时回退到本地代码页构造。
|
||||||
|
try {
|
||||||
|
return std::filesystem::path(value);
|
||||||
|
} catch (...) {
|
||||||
|
// 本地代码页也无法转换时返回空路径,由调用方跳过。
|
||||||
|
return std::filesystem::path();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string platform_name() {
|
std::string platform_name() {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return "win32";
|
return "win32";
|
||||||
@@ -48,39 +65,55 @@ std::string platform_name() {
|
|||||||
bool valid_spine_executable(const std::string& path) {
|
bool valid_spine_executable(const std::string& path) {
|
||||||
if (path.empty()) return false;
|
if (path.empty()) return false;
|
||||||
std::error_code error;
|
std::error_code error;
|
||||||
const auto status = std::filesystem::status(std::filesystem::u8path(path), error);
|
const auto status = std::filesystem::status(to_path(path), error);
|
||||||
return !error && std::filesystem::is_regular_file(status);
|
return !error && std::filesystem::is_regular_file(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string find_spine_executable() {
|
std::string find_spine_executable() {
|
||||||
std::vector<std::filesystem::path> candidates;
|
try {
|
||||||
const std::string environment_path = environment("SPINE_EXECUTABLE");
|
std::vector<std::filesystem::path> candidates;
|
||||||
if (!environment_path.empty()) candidates.push_back(std::filesystem::u8path(environment_path));
|
const std::string environment_path = environment("SPINE_EXECUTABLE");
|
||||||
const ConnectorConfig config = load_config();
|
if (!environment_path.empty()) {
|
||||||
if (!config.spine_executable.empty()) candidates.push_back(std::filesystem::u8path(config.spine_executable));
|
const auto path = to_path(environment_path);
|
||||||
|
if (!path.empty()) candidates.push_back(path);
|
||||||
|
}
|
||||||
|
const ConnectorConfig config = load_config();
|
||||||
|
if (!config.spine_executable.empty()) {
|
||||||
|
const auto path = to_path(config.spine_executable);
|
||||||
|
if (!path.empty()) candidates.push_back(path);
|
||||||
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
for (const char* variable : {"ProgramFiles", "ProgramFiles(x86)", "LOCALAPPDATA"}) {
|
for (const char* variable : {"ProgramFiles", "ProgramFiles(x86)", "LOCALAPPDATA"}) {
|
||||||
const std::string root = environment(variable);
|
const std::string root = environment(variable);
|
||||||
if (root.empty()) continue;
|
if (root.empty()) continue;
|
||||||
candidates.push_back(std::filesystem::u8path(root) / "Spine" / "Spine.com");
|
const auto root_path = to_path(root);
|
||||||
candidates.push_back(std::filesystem::u8path(root) / "Esoteric Software" / "Spine" / "Spine.com");
|
if (root_path.empty()) continue;
|
||||||
candidates.push_back(std::filesystem::u8path(root) / "Programs" / "Spine" / "Spine.com");
|
candidates.push_back(root_path / "Spine" / "Spine.com");
|
||||||
}
|
candidates.push_back(root_path / "Esoteric Software" / "Spine" / "Spine.com");
|
||||||
|
candidates.push_back(root_path / "Programs" / "Spine" / "Spine.com");
|
||||||
|
}
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
candidates.emplace_back("/Applications/Spine.app/Contents/MacOS/Spine");
|
candidates.emplace_back("/Applications/Spine.app/Contents/MacOS/Spine");
|
||||||
const std::string home = environment("HOME");
|
const std::string home = environment("HOME");
|
||||||
if (!home.empty()) candidates.push_back(std::filesystem::u8path(home) / "Applications" / "Spine.app" / "Contents" / "MacOS" / "Spine");
|
if (!home.empty()) {
|
||||||
|
const auto path = to_path(home);
|
||||||
|
if (!path.empty()) candidates.push_back(path / "Applications" / "Spine.app" / "Contents" / "MacOS" / "Spine");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
candidates.emplace_back("/opt/Spine/Spine.sh");
|
candidates.emplace_back("/opt/Spine/Spine.sh");
|
||||||
candidates.emplace_back("/usr/local/bin/Spine");
|
candidates.emplace_back("/usr/local/bin/Spine");
|
||||||
candidates.emplace_back("/usr/bin/Spine");
|
candidates.emplace_back("/usr/bin/Spine");
|
||||||
#endif
|
#endif
|
||||||
append_path_candidates(candidates);
|
append_path_candidates(candidates);
|
||||||
for (const auto& candidate : candidates) {
|
for (const auto& candidate : candidates) {
|
||||||
const std::string path = candidate.u8string();
|
const std::string path = candidate.u8string();
|
||||||
if (valid_spine_executable(path)) return path;
|
if (valid_spine_executable(path)) return path;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
} catch (...) {
|
||||||
|
// 任何异常都不应导致程序崩溃,返回未找到。
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace connector
|
} // namespace connector
|
||||||
Binary file not shown.
Reference in new issue
Block a user