Bind Win32 app shell and move more legacy platform state

This commit is contained in:
2026-06-17 01:54:59 +02:00
parent 3cbc88fe78
commit 5c8a87faa0
11 changed files with 185 additions and 123 deletions

View File

@@ -46,13 +46,17 @@ void request_window_close(HWND hWnd)
void handle_window_close_message(VrShellState& vr)
{
auto* app = bound_app();
auto* runtime = bound_runtime();
mark_lifecycle_stopped();
request_stop_and_join_vr_thread(vr);
App::I->runtime().ui_thread_stop();
App::I->runtime().render_thread_stop();
App::I->terminate();
runtime->ui_thread_stop();
runtime->render_thread_stop();
app->terminate();
App::I = nullptr;
bind_app(nullptr);
bind_runtime(nullptr);
delete App::I;
delete app;
PostQuitMessage(0);
}

View File

@@ -18,6 +18,7 @@ namespace pp::platform::windows {
namespace {
struct RetainedWindowsRuntimeState final {
App* app = nullptr;
AppRuntime* runtime = nullptr;
};
@@ -38,9 +39,11 @@ void register_touch_window(HWND hWnd)
void initialize_runtime_threads()
{
auto* app = bound_app();
auto* runtime = bound_runtime();
mark_lifecycle_running();
App::I->runtime().render_thread_start(*App::I);
App::I->runtime().ui_thread_start(*App::I);
runtime->render_thread_start(*app);
runtime->ui_thread_start(*app);
}
void install_debug_gl_callbacks()
@@ -85,10 +88,11 @@ void restore_window_placement(HWND hWnd, int show_command)
void run_main_message_loop()
{
MSG msg;
auto* app = bound_app();
LOG("start main loop");
while (lifecycle_is_running())
{
auto present = App::I->animate || App::I->redraw ?
auto present = app->animate || app->redraw ?
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0);
if (msg.message == WM_QUIT)
@@ -113,6 +117,16 @@ void shutdown_main_window_runtime(const MainWindowStartupState& startup, HINSTAN
}
void bind_app(App* app) noexcept
{
retained_runtime_state().app = app;
}
App* bound_app() noexcept
{
return retained_runtime_state().app;
}
void bind_runtime(AppRuntime* runtime) noexcept
{
retained_runtime_state().runtime = runtime;
@@ -128,10 +142,12 @@ int run_main_application(int argc, char** argv)
auto& state = retained_state();
state.hInst = GetModuleHandle(NULL);
App::I = new App();
bind_runtime(&App::I->runtime());
App::I->set_platform_services(&pp::platform::windows::platform_services());
App::I->initLog();
auto* app = new App();
App::I = app;
bind_app(app);
bind_runtime(&app->runtime());
app->set_platform_services(&pp::platform::windows::platform_services());
app->initLog();
pp::platform::windows::init_shcore_API();
pp::platform::windows::initialize_stylus_input();
@@ -149,7 +165,7 @@ int run_main_application(int argc, char** argv)
pp::platform::windows::read_WMI_info();
App::I->create();
app->create();
auto startup = pp::platform::windows::initialize_main_window_startup_state();
auto context = pp::platform::windows::OpenGlWindowContext {};
@@ -158,9 +174,11 @@ int run_main_application(int argc, char** argv)
case pp::platform::windows::MainStartupResult::Ok:
break;
case pp::platform::windows::MainStartupResult::GladLoadFailure:
bind_app(nullptr);
bind_runtime(nullptr);
return 0;
case pp::platform::windows::MainStartupResult::MissingCoreContextSupport:
bind_app(nullptr);
bind_runtime(nullptr);
return -1;
}
@@ -173,8 +191,9 @@ int run_main_application(int argc, char** argv)
switch (const_hash(argv[1]))
{
case const_hash("convert"):
App::I->initShaders();
App::I->cmd_convert(argv[2], argv[3]);
app->initShaders();
app->cmd_convert(argv[2], argv[3]);
bind_app(nullptr);
bind_runtime(nullptr);
return 0;
case const_hash("-vrmode"):
@@ -192,6 +211,7 @@ int run_main_application(int argc, char** argv)
void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash)
{
auto& state = retained_state();
auto* app = bound_app();
register_touch_window(state.hWnd);
wglMakeCurrent(NULL, NULL);
@@ -201,11 +221,11 @@ void run_main_window_runtime(const MainWindowStartupState& startup, bool start_i
initialize_wintab(state.hWnd, state.sandboxed);
set_main_window_icon(state.hWnd);
App::I->ui_sync();
app->ui_sync();
restore_window_placement(state.hWnd, startup.show_command);
if (start_in_vr)
App::I->vr_start();
app->vr_start();
LOG("show main window");
SetForegroundWindow(state.hWnd);

View File

@@ -3,12 +3,15 @@
#include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_splash.h"
class App;
class AppRuntime;
namespace pp::platform::windows {
int run_main_application(int argc, char** argv);
void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash);
void bind_app(App* app) noexcept;
[[nodiscard]] App* bound_app() noexcept;
void bind_runtime(AppRuntime* runtime) noexcept;
[[nodiscard]] AppRuntime* bound_runtime() noexcept;

View File

@@ -4,6 +4,7 @@
#include "app.h"
#include "log.h"
#include "platform_windows/windows_runtime_shell.h"
#include "wacom.h"
namespace pp::platform::windows {
@@ -53,6 +54,7 @@ void initialize_stylus_input()
void update_stylus_state(float dt)
{
auto& state = stylus_input_state();
auto* app = bound_app();
state.timer_stylus += dt;
state.timer_ink_touch += dt;
state.timer_ink_pen += dt;
@@ -61,24 +63,24 @@ void update_stylus_state(float dt)
{
WacomTablet::I.m_stylus = false;
WacomTablet::I.m_eraser = false;
App::I->redraw = true;
app->redraw = true;
}
if (state.timer_ink_pen > 0.1f && WacomTablet::I.m_ink_pen)
{
WacomTablet::I.m_ink_pen = false;
App::I->redraw = true;
app->redraw = true;
}
if (state.timer_ink_touch > 0.1f && WacomTablet::I.m_ink_touch)
{
WacomTablet::I.m_ink_touch = false;
App::I->redraw = true;
app->redraw = true;
}
}
void note_wintab_packet()
{
auto& state = stylus_input_state();
App::I->set_stylus();
bound_app()->set_stylus();
state.timer_stylus = 0.0f;
}
@@ -118,7 +120,7 @@ void handle_pointer_update_message(WPARAM wp)
state.timer_ink_pen = 0.0f;
WacomTablet::I.m_ink_pen = true;
WacomTablet::I.m_pen_pres = static_cast<float>(pen_info.pressure) / 1024.0f;
App::I->set_stylus();
bound_app()->set_stylus();
return;
default:

View File

@@ -13,6 +13,8 @@
namespace pp::platform::windows {
[[nodiscard]] App* bound_app() noexcept;
struct VrShellState final {
std::mutex snapshot_mutex;
VrSessionSnapshot session;
@@ -72,9 +74,10 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
if (sandboxed)
return false;
auto* app = bound_app();
state.vive = std::make_unique<Vive>();
state.vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) {
App::I->vr_draw(proj, view, pose);
state.vive->on_draw = [app](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) {
app->vr_draw(proj, view, pose);
};
if (!state.vive->Initialize())
{
@@ -89,7 +92,7 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
state.hmd_renderer.join();
}
state.hmd_renderer = std::jthread([&state, &running](std::stop_token stop_token) {
state.hmd_renderer = std::jthread([app, &state, &running](std::stop_token stop_token) {
if (!state.vive)
return;
@@ -98,13 +101,13 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
clear_vr_session_snapshot(state, true);
state.vr_running.store(true, std::memory_order_relaxed);
state.vive->on_analog_button = std::bind(&App::vr_analog, App::I, std::placeholders::_1,
state.vive->on_analog_button = std::bind(&App::vr_analog, app, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
state.vive->on_button = std::bind(&App::vr_digital, App::I, std::placeholders::_1,
state.vive->on_button = std::bind(&App::vr_digital, app, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
App::I->render_task([] {
App::I->vr_draw_ui();
app->render_task([app] {
app->vr_draw_ui();
});
const float target_tick_rate = 90;
@@ -136,11 +139,11 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
state.vive->m_active,
state.vive->m_controllers[0],
state.vive->m_pose);
App::I->vr_update(dt);
app->vr_update(dt);
if (state.vr_running.load(std::memory_order_relaxed) && state.vive->m_active)
{
App::I->render_task([&state] {
app->render_task([&state] {
state.vive->Draw();
});
}

View File

@@ -5,6 +5,7 @@
#include "app.h"
#include "platform_windows/windows_lifecycle_shell.h"
#include "platform_windows/windows_platform_services.h"
#include "platform_windows/windows_runtime_shell.h"
#include "platform_windows/windows_stylus_input.h"
#include "keymap.h"
#include "wacom.h"
@@ -47,6 +48,7 @@ RetainedState& retained_state()
LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
auto& state = retained_state();
auto* app = bound_app();
static glm::vec2 lastPoint;
auto extra = GetMessageExtraInfo();
@@ -57,15 +59,15 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
handle_window_close_message(state.vr);
return 0;
case WM_PAINT:
App::I->redraw = true;
app->redraw = true;
break;
case WM_CREATE:
BT_SetTerminate();
break;
case WM_CLOSE:
{
App::I->ui_task_async([] {
if (App::I->request_close())
app->ui_task_async([app] {
if (app->request_close())
{
destroy_window();
}
@@ -79,10 +81,10 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
auto h = (float)HIWORD(lp);
if (h != 0 && lifecycle_is_running())
{
App::I->ui_task_async([=]
app->ui_task_async([app, w, h]
{
App::I->resize(w, h);
App::I->redraw = true;
app->resize(w, h);
app->redraw = true;
}, true);
}
break;
@@ -90,7 +92,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
case WM_ACTIVATE:
{
platform_services().set_cursor_visible(true);
App::I->ui_task_async([&state, wp, lp] {
app->ui_task_async([app, &state, wp, lp] {
int active = GET_WM_ACTIVATE_STATE(wp, lp);
WacomTablet::I.set_focus(active);
static BYTE keys[256];
@@ -102,10 +104,10 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
if (alt && k.first == kKey::KeyTab)
continue;
bool down = keys[k.second] & 0x80;
if (App::I->keys[(int)k.first] && !down)
App::I->key_up(k.first);
else if (!App::I->keys[(int)k.first] && down)
App::I->key_down(k.first);
if (app->keys[(int)k.first] && !down)
app->key_up(k.first);
else if (!app->keys[(int)k.first] && down)
app->key_down(k.first);
}
}
});
@@ -114,7 +116,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
case WT_PACKET:
{
note_wintab_packet();
App::I->ui_task_async([=] {
app->ui_task_async([=] {
WacomTablet::I.handle_message(hWnd, msg, wp, lp);
});
break;
@@ -122,32 +124,32 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if ((lp >> 30 & 1) == 0 &&
!(wp == VK_TAB && App::I->keys[(int)kKey::KeyAlt]))
!(wp == VK_TAB && app->keys[(int)kKey::KeyAlt]))
{
App::I->ui_task_async([wp] {
App::I->key_down(convert_key((int)wp));
app->ui_task_async([app, wp] {
app->key_down(convert_key((int)wp));
});
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
if (!(wp == VK_TAB && App::I->keys[(int)kKey::KeyAlt]))
if (!(wp == VK_TAB && app->keys[(int)kKey::KeyAlt]))
{
App::I->ui_task_async([wp] {
App::I->key_up(convert_key((int)wp));
app->ui_task_async([app, wp] {
app->key_up(convert_key((int)wp));
});
}
break;
case WM_CHAR:
App::I->ui_task_async([wp] {
App::I->key_char((int)wp);
app->ui_task_async([app, wp] {
app->key_char((int)wp);
});
break;
case WM_MOUSEMOVE:
lastPoint = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) };
{
auto pt = lastPoint;
App::I->ui_task_async([pt, extra, p = WacomTablet::I.get_pressure()] {
app->ui_task_async([app, pt, extra, p = WacomTablet::I.get_pressure()] {
kEventSource pointer_source;
if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch)
{
@@ -159,7 +161,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
if ((extra & 0xFFFFFF00) == 0xFF515700)
pointer_source = kEventSource::Touch;
}
App::I->mouse_move((float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser);
app->mouse_move((float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser);
});
}
break;
@@ -167,7 +169,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
SetCapture(hWnd);
auto pt = lastPoint;
App::I->ui_task_async([pt, extra, hWnd, p = WacomTablet::I.get_pressure()] {
app->ui_task_async([app, pt, extra, p = WacomTablet::I.get_pressure()] {
kEventSource pointer_source;
if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch)
{
@@ -179,7 +181,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
if ((extra & 0xFFFFFF00) == 0xFF515700)
pointer_source = kEventSource::Touch;
}
App::I->mouse_down(0, (float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser);
app->mouse_down(0, (float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser);
});
}
break;
@@ -187,7 +189,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
ReleaseCapture();
auto pt = lastPoint;
App::I->ui_task_async([pt, extra] {
app->ui_task_async([app, pt, extra] {
WacomTablet::I.reset_pressure();
kEventSource pointer_source;
if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch)
@@ -200,7 +202,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
if ((extra & 0xFFFFFF00) == 0xFF515700)
pointer_source = kEventSource::Touch;
}
App::I->mouse_up(0, (float)pt.x, (float)pt.y, pointer_source, WacomTablet::I.m_eraser);
app->mouse_up(0, (float)pt.x, (float)pt.y, pointer_source, WacomTablet::I.m_eraser);
});
}
break;
@@ -208,7 +210,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
SetCapture(hWnd);
auto pt = lastPoint;
App::I->ui_task_async([pt, extra, hWnd] {
app->ui_task_async([app, pt, extra] {
kEventSource pointer_source;
if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch)
{
@@ -220,7 +222,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
if ((extra & 0xFFFFFF00) == 0xFF515700)
pointer_source = kEventSource::Touch;
}
App::I->mouse_down(1, (float)pt.x, (float)pt.y, 1.f, pointer_source, 0);
app->mouse_down(1, (float)pt.x, (float)pt.y, 1.f, pointer_source, 0);
});
}
break;
@@ -228,7 +230,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
ReleaseCapture();
auto pt = lastPoint;
App::I->ui_task_async([pt, extra] {
app->ui_task_async([app, pt, extra] {
kEventSource pointer_source;
if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch)
{
@@ -240,7 +242,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
if ((extra & 0xFFFFFF00) == 0xFF515700)
pointer_source = kEventSource::Touch;
}
App::I->mouse_up(1, (float)pt.x, (float)pt.y, pointer_source, 0);
app->mouse_up(1, (float)pt.x, (float)pt.y, pointer_source, 0);
});
}
break;
@@ -250,8 +252,8 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
pt.x = GET_X_LPARAM(lp);
pt.y = GET_Y_LPARAM(lp);
ScreenToClient(hWnd, &pt);
App::I->ui_task_async([pt, wp] {
App::I->mouse_scroll((float)pt.x, (float)pt.y,
app->ui_task_async([app, pt, wp] {
app->mouse_scroll((float)pt.x, (float)pt.y,
(float)GET_WHEEL_DELTA_WPARAM(wp) / (float)WHEEL_DELTA);
});
break;