diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 783be0c8..c70b069b 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -92,6 +92,14 @@ Current hotspot files: Latest slice: +- The Win32 stylus and pointer-input path no longer reaches + `WacomTablet::I` directly inside + `src/platform_windows/windows_window_shell.cpp` or + `src/platform_windows/windows_stylus_input.cpp`; the live Windows runtime + shell now binds the active tablet explicitly through + `src/platform_windows/windows_runtime_shell.*`, leaving + `WacomTablet::I` only at the entry composition edge where the runtime shell + binds the active tablet instance. - The remaining dense Windows bootstrap singleton pocket moved off `App::I`: `setup_exception_handler(...)`, `initialize_main_window_startup_state(...)`, and `_pre_call_callback(...)` now use explicit app/bound-runtime state diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 5cd65833..ecb234d3 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -56,8 +56,11 @@ Completed, blocked, and superseded task history moved to - canvas async import/export/save/open now run through an owned in-file worker, but their retained progress execution is still not a clean runtime service boundary - - thread-affinity rules are enforced by convention and asserts instead of - explicit runtime contracts + - the Win32 input path now binds the active `WacomTablet*` explicitly + through `windows_runtime_shell`, but that tablet binding still lives at a + composition edge instead of a broader runtime/platform-owned controller + - thread-affinity rules are enforced by convention and asserts instead of + explicit runtime contracts - The UI ownership boundary is not finished: - base `Node` still carries raw parent/manager pointers beside shared handles - callback captures still frequently close over retained nodes and `App::I` @@ -1202,6 +1205,13 @@ Why now: platform-handle state on `App`, which blocks a real `pp_platform_*` shell split. Current slice: +- The Win32 stylus and pointer-input path no longer reaches + `WacomTablet::I` directly in + `src/platform_windows/windows_window_shell.cpp` or + `src/platform_windows/windows_stylus_input.cpp`; + `src/platform_windows/windows_runtime_shell.*` now binds the active tablet + explicitly and the touched consumers read it through that runtime-shell + binding instead of the process-global singleton. - The remaining dense Windows bootstrap singleton pocket moved off `App::I`: `setup_exception_handler(...)`, `initialize_main_window_startup_state(...)`, and `_pre_call_callback(...)` diff --git a/src/platform_windows/windows_runtime_shell.cpp b/src/platform_windows/windows_runtime_shell.cpp index 58ee8fc7..d43bc6e1 100644 --- a/src/platform_windows/windows_runtime_shell.cpp +++ b/src/platform_windows/windows_runtime_shell.cpp @@ -20,6 +20,7 @@ namespace { struct RetainedWindowsRuntimeState final { App* app = nullptr; AppRuntime* runtime = nullptr; + WacomTablet* tablet = nullptr; }; [[nodiscard]] RetainedWindowsRuntimeState& retained_runtime_state() @@ -56,10 +57,12 @@ void install_debug_gl_callbacks() void initialize_wintab(HWND hWnd, bool sandboxed) { + auto* tablet = bound_wacom_tablet(); + assert(tablet); if (!sandboxed) { LOG("init WinTab"); - WacomTablet::I.init(hWnd); + tablet->init(hWnd); } else { @@ -110,7 +113,8 @@ void run_main_message_loop() void shutdown_main_window_runtime(const MainWindowStartupState& startup, HINSTANCE hInst) { - WacomTablet::I.terminate(); + if (auto* tablet = retained_runtime_state().tablet) + tablet->terminate(); UnregisterClass(startup.window_class.lpszClassName, hInst); LogRemote::I.stop(); } @@ -137,6 +141,16 @@ AppRuntime* bound_runtime() noexcept return retained_runtime_state().runtime; } +void bind_wacom_tablet(WacomTablet* tablet) noexcept +{ + retained_runtime_state().tablet = tablet; +} + +WacomTablet* bound_wacom_tablet() noexcept +{ + return retained_runtime_state().tablet; +} + int run_main_application(int argc, char** argv) { auto& state = retained_state(); @@ -146,6 +160,7 @@ int run_main_application(int argc, char** argv) App::I = app; bind_app(app); bind_runtime(&app->runtime()); + bind_wacom_tablet(&WacomTablet::I); app->set_platform_services(&pp::platform::windows::platform_services()); app->initLog(); @@ -176,10 +191,12 @@ int run_main_application(int argc, char** argv) case pp::platform::windows::MainStartupResult::GladLoadFailure: bind_app(nullptr); bind_runtime(nullptr); + bind_wacom_tablet(nullptr); return 0; case pp::platform::windows::MainStartupResult::MissingCoreContextSupport: bind_app(nullptr); bind_runtime(nullptr); + bind_wacom_tablet(nullptr); return -1; } @@ -195,6 +212,7 @@ int run_main_application(int argc, char** argv) app->cmd_convert(argv[2], argv[3]); bind_app(nullptr); bind_runtime(nullptr); + bind_wacom_tablet(nullptr); return 0; case const_hash("-vrmode"): start_in_vr = true; @@ -205,6 +223,7 @@ int run_main_application(int argc, char** argv) } pp::platform::windows::run_main_window_runtime(startup, start_in_vr, splash); + bind_wacom_tablet(nullptr); return 0; } diff --git a/src/platform_windows/windows_runtime_shell.h b/src/platform_windows/windows_runtime_shell.h index 0f51b293..196c7e9c 100644 --- a/src/platform_windows/windows_runtime_shell.h +++ b/src/platform_windows/windows_runtime_shell.h @@ -5,6 +5,7 @@ class App; class AppRuntime; +class WacomTablet; namespace pp::platform::windows { @@ -14,5 +15,7 @@ void bind_app(App* app) noexcept; [[nodiscard]] App* bound_app() noexcept; void bind_runtime(AppRuntime* runtime) noexcept; [[nodiscard]] AppRuntime* bound_runtime() noexcept; +void bind_wacom_tablet(WacomTablet* tablet) noexcept; +[[nodiscard]] WacomTablet* bound_wacom_tablet() noexcept; } diff --git a/src/platform_windows/windows_stylus_input.cpp b/src/platform_windows/windows_stylus_input.cpp index d14bb91e..299b56dc 100644 --- a/src/platform_windows/windows_stylus_input.cpp +++ b/src/platform_windows/windows_stylus_input.cpp @@ -8,6 +8,7 @@ #include "wacom.h" namespace pp::platform::windows { + namespace { struct StylusInputState final @@ -28,6 +29,13 @@ StylusInputState& stylus_input_state() return state; } +[[nodiscard]] WacomTablet& active_wacom_tablet() +{ + auto* tablet = bound_wacom_tablet(); + assert(tablet); + return *tablet; +} + } void initialize_stylus_input() @@ -55,24 +63,25 @@ void update_stylus_state(float dt) { auto& state = stylus_input_state(); auto* app = bound_app(); + auto& tablet = active_wacom_tablet(); state.timer_stylus += dt; state.timer_ink_touch += dt; state.timer_ink_pen += dt; - if (state.timer_stylus > 0.1f && (WacomTablet::I.m_stylus || WacomTablet::I.m_eraser)) + if (state.timer_stylus > 0.1f && (tablet.m_stylus || tablet.m_eraser)) { - WacomTablet::I.m_stylus = false; - WacomTablet::I.m_eraser = false; + tablet.m_stylus = false; + tablet.m_eraser = false; app->redraw = true; } - if (state.timer_ink_pen > 0.1f && WacomTablet::I.m_ink_pen) + if (state.timer_ink_pen > 0.1f && tablet.m_ink_pen) { - WacomTablet::I.m_ink_pen = false; + tablet.m_ink_pen = false; app->redraw = true; } - if (state.timer_ink_touch > 0.1f && WacomTablet::I.m_ink_touch) + if (state.timer_ink_touch > 0.1f && tablet.m_ink_touch) { - WacomTablet::I.m_ink_touch = false; + tablet.m_ink_touch = false; app->redraw = true; } } @@ -87,6 +96,7 @@ void note_wintab_packet() void handle_pointer_update_message(WPARAM wp) { auto& state = stylus_input_state(); + auto& tablet = active_wacom_tablet(); if (!state.get_pointer_info) return; @@ -109,8 +119,8 @@ void handle_pointer_update_message(WPARAM wp) return; state.timer_ink_touch = 0.0f; - WacomTablet::I.m_ink_touch = true; - WacomTablet::I.m_pen_pres = 1.0f; + tablet.m_ink_touch = true; + tablet.m_pen_pres = 1.0f; return; case PT_PEN: @@ -118,8 +128,8 @@ void handle_pointer_update_message(WPARAM wp) return; state.timer_ink_pen = 0.0f; - WacomTablet::I.m_ink_pen = true; - WacomTablet::I.m_pen_pres = static_cast(pen_info.pressure) / 1024.0f; + tablet.m_ink_pen = true; + tablet.m_pen_pres = static_cast(pen_info.pressure) / 1024.0f; bound_app()->set_stylus(); return; diff --git a/src/platform_windows/windows_window_shell.cpp b/src/platform_windows/windows_window_shell.cpp index 2961ccb8..1018145c 100644 --- a/src/platform_windows/windows_window_shell.cpp +++ b/src/platform_windows/windows_window_shell.cpp @@ -14,6 +14,28 @@ void destroy_window(); namespace pp::platform::windows { +namespace { + +[[nodiscard]] WacomTablet& active_wacom_tablet() +{ + auto* tablet = bound_wacom_tablet(); + assert(tablet); + return *tablet; +} + +[[nodiscard]] kEventSource resolve_pointer_source(const WacomTablet& tablet, LPARAM extra) +{ + if (tablet.m_ink_pen || tablet.m_ink_touch) + return tablet.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; + + auto pointer_source = tablet.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; + if ((extra & 0xFFFFFF00) == 0xFF515700) + pointer_source = kEventSource::Touch; + return pointer_source; +} + +} + void initialize_retained_input_state() { auto& state = retained_state(); @@ -94,7 +116,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) platform_services().set_cursor_visible(true); app->ui_task_async([app, &state, wp, lp] { int active = GET_WM_ACTIVATE_STATE(wp, lp); - WacomTablet::I.set_focus(active); + active_wacom_tablet().set_focus(active); static BYTE keys[256]; if (GetKeyboardState(keys)) { @@ -117,7 +139,7 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { note_wintab_packet(); app->ui_task_async([=] { - WacomTablet::I.handle_message(hWnd, msg, wp, lp); + active_wacom_tablet().handle_message(hWnd, msg, wp, lp); }); break; } @@ -149,19 +171,11 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) lastPoint = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; { auto pt = lastPoint; - 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) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - app->mouse_move((float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser); + auto& tablet = active_wacom_tablet(); + app->ui_task_async([app, pt, extra, p = tablet.get_pressure()] { + auto& ui_tablet = active_wacom_tablet(); + app->mouse_move((float)pt.x, (float)pt.y, p, + resolve_pointer_source(ui_tablet, extra), ui_tablet.m_eraser); }); } break; @@ -169,19 +183,11 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { SetCapture(hWnd); auto pt = lastPoint; - 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) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - app->mouse_down(0, (float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser); + auto& tablet = active_wacom_tablet(); + app->ui_task_async([app, pt, extra, p = tablet.get_pressure()] { + auto& ui_tablet = active_wacom_tablet(); + app->mouse_down(0, (float)pt.x, (float)pt.y, p, + resolve_pointer_source(ui_tablet, extra), ui_tablet.m_eraser); }); } break; @@ -190,19 +196,10 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) ReleaseCapture(); auto pt = lastPoint; 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) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - app->mouse_up(0, (float)pt.x, (float)pt.y, pointer_source, WacomTablet::I.m_eraser); + auto& tablet = active_wacom_tablet(); + tablet.reset_pressure(); + app->mouse_up(0, (float)pt.x, (float)pt.y, + resolve_pointer_source(tablet, extra), tablet.m_eraser); }); } break; @@ -211,18 +208,8 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) SetCapture(hWnd); auto pt = lastPoint; app->ui_task_async([app, pt, extra] { - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - app->mouse_down(1, (float)pt.x, (float)pt.y, 1.f, pointer_source, 0); + const auto& tablet = active_wacom_tablet(); + app->mouse_down(1, (float)pt.x, (float)pt.y, 1.f, resolve_pointer_source(tablet, extra), 0); }); } break; @@ -231,18 +218,8 @@ LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) ReleaseCapture(); auto pt = lastPoint; app->ui_task_async([app, pt, extra] { - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - app->mouse_up(1, (float)pt.x, (float)pt.y, pointer_source, 0); + const auto& tablet = active_wacom_tablet(); + app->mouse_up(1, (float)pt.x, (float)pt.y, resolve_pointer_source(tablet, extra), 0); }); } break;