Remove backend probing from XCUI panel canvas host

This commit is contained in:
2026-04-05 17:03:02 +08:00
parent 94482ab98c
commit 3968083da7
11 changed files with 15 additions and 101 deletions

View File

@@ -46,6 +46,7 @@ Old `editor` replacement is explicitly out of scope for this phase.
- `XCUIShellChromeState` no longer carries the legacy host demo-window toggle or command id on the generic shell-state surface
- `Application.h` no longer exposes that legacy demo command through generic `ShellCommandIds`, `ShellCommandBindings`, or `RegisterShellViewCommands(...)`
- the legacy demo window toggle now lives as a compatibility-only command inside `ApplicationLegacyImGui.cpp`
- `Application.h` now also uses backend-neutral compatibility-host naming for the non-native window-host path, so the generic application header no longer names `LegacyImGui` in its mode enum or private host-frame method declarations
- generic `Application` host-mode/member naming is now also shifting from `LegacyImGui` toward `CompatibilityHost`, so the default shell surface does not have to encode ImGui into every host-facing method name
- Old `editor` replacement remains deferred; all active execution still stays inside XCUI shared code and `new_editor`.
@@ -109,7 +110,7 @@ Current gap:
- `new_editor` now also has an isolated `XCUIEditorCommandRouter` model with shortcut matching, enable predicates, and direct command invocation semantics covered by dedicated tests, ready for shell-frame integration.
- `XCUI Demo` now exports pending per-frame command ids through `DrainPendingCommandIds()`, so editor-side hosts have a clean seam for observing demo/runtime command traffic without parsing draw data.
- `XCUI Demo` and `LayoutLab` panel canvases are now being pulled behind a dedicated `IXCUIPanelCanvasHost` seam, so canvas surface presentation, hover/focus fallback state, and overlay draw hooks no longer have to stay hard-coded inside each ImGui panel implementation.
- The panel-canvas seam now also exposes explicit backend/capability metadata and a minimal `NullXCUIPanelCanvasHost`, so non-ImGui host paths have a concrete placeholder backend instead of relying on an implicit ImGui default.
- The panel-canvas seam now keeps the generic host contract on observable canvas behavior only; backend/capability identity probing has been removed from `IXCUIPanelCanvasHost`, and the minimal `NullXCUIPanelCanvasHost` remains the concrete placeholder host for non-ImGui paths.
- `XCUI Demo` and `LayoutLab` panel input now also flows through an explicit `IXCUIInputSnapshotSource` seam, so panel/runtime code no longer reads `ImGuiIO` / `ImGui::IsKeyPressed` / `ImGui::IsMouseClicked` directly when the shell wants to use an ImGui adapter.
- `new_editor` now also has an explicit `ImGuiXCUIInputSnapshotSource` adapter, keeping ImGui-specific input capture in the host adapter layer instead of inside panel/runtime update code.
- Panel diagnostics were expanded to clearly separate preview/runtime/input state and native vs legacy paths.
@@ -265,7 +266,7 @@ Current gap:
- `new_editor` now also has a pure `XCUIShellChromeState` model with dedicated tests, covering shell panel visibility, hosted-preview mode, and shell view toggles without depending on ImGui or `Application`.
- `XCUIShellChromeState` now also exposes effective hosted-preview state helpers and shell view-toggle command-id helpers, so shell routing code no longer has to manually combine enablement and requested preview mode.
- `XCUIShellChromeState` hosted-preview modes were renamed away from `LegacyImGui`, so XCUI shell state no longer treats ImGui as the generic fallback concept.
- The panel-canvas seam now has dedicated null/imgui backend coverage, including explicit backend/capability reporting and a non-ImGui placeholder host path for future native shell adoption.
- The panel-canvas seam now has dedicated null/compat/native coverage around stable debug names, passive-session safety, externally driven native snapshots, and compat-host factory creation without relying on explicit backend/capability reporting.
- The native host follow-up is now present in `new_editor`:
- `NativeWindowUICompositor` provides a swapchain-native XCUI packet present path beside the legacy ImGui compositor
- `Application` now defaults to that native host path and directly composes `XCUI Demo` plus `Layout Lab` into one native shell frame

View File

@@ -89,18 +89,6 @@ public:
return "ImGuiXCUIPanelCanvasHost";
}
XCUIPanelCanvasHostBackend GetBackend() const override {
return XCUIPanelCanvasHostBackend::ImGui;
}
XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
XCUIPanelCanvasHostCapabilities capabilities = {};
capabilities.supportsPointerHitTesting = true;
capabilities.supportsHostedSurfaceImages = true;
capabilities.supportsPrimitiveOverlays = true;
return capabilities;
}
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override {
const char* childId =
request.childId != nullptr && request.childId[0] != '\0'

View File

@@ -132,18 +132,6 @@ public:
return "NativeXCUIPanelCanvasHost";
}
XCUIPanelCanvasHostBackend GetBackend() const override {
return XCUIPanelCanvasHostBackend::Native;
}
XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
XCUIPanelCanvasHostCapabilities capabilities = {};
capabilities.supportsHostedSurfaceImages = true;
capabilities.supportsPrimitiveOverlays = true;
capabilities.supportsExternallyDrivenSession = true;
return capabilities;
}
void SetCanvasSession(const XCUIPanelCanvasSession& session) {
m_configuredSession = session;
m_hasConfiguredSession = true;

View File

@@ -14,14 +14,6 @@ public:
return "NullXCUIPanelCanvasHost";
}
XCUIPanelCanvasHostBackend GetBackend() const override {
return XCUIPanelCanvasHostBackend::Null;
}
XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
return {};
}
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override {
m_canvasSession = BuildPassiveXCUIPanelCanvasSession(request);
return m_canvasSession;

View File

@@ -4,7 +4,6 @@
#include <XCEngine/UI/DrawData.h>
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
@@ -13,19 +12,6 @@ namespace XCEngine {
namespace Editor {
namespace XCUIBackend {
enum class XCUIPanelCanvasHostBackend : std::uint8_t {
Null = 0,
ImGui,
Native
};
struct XCUIPanelCanvasHostCapabilities {
bool supportsPointerHitTesting = false;
bool supportsHostedSurfaceImages = false;
bool supportsPrimitiveOverlays = false;
bool supportsExternallyDrivenSession = false;
};
struct XCUIPanelCanvasRequest {
const char* childId = nullptr;
float height = 0.0f;
@@ -98,8 +84,6 @@ public:
virtual ~IXCUIPanelCanvasHost() = default;
virtual const char* GetDebugName() const = 0;
virtual XCUIPanelCanvasHostBackend GetBackend() const = 0;
virtual XCUIPanelCanvasHostCapabilities GetCapabilities() const = 0;
virtual XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) = 0;
virtual void DrawFilledRect(
const ::XCEngine::UI::UIRect& rect,

View File

@@ -6,20 +6,12 @@ namespace {
using XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
TEST(NewEditorImGuiXCUIPanelCanvasHostTest, ReportsExplicitBackendAndCapabilities) {
TEST(NewEditorImGuiXCUIPanelCanvasHostTest, FactoryCreatesCompatCanvasHostWithStableDebugName) {
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateImGuiXCUIPanelCanvasHost();
ASSERT_NE(host, nullptr);
EXPECT_STREQ(host->GetDebugName(), "ImGuiXCUIPanelCanvasHost");
EXPECT_EQ(host->GetBackend(), XCUIPanelCanvasHostBackend::ImGui);
const XCUIPanelCanvasHostCapabilities capabilities = host->GetCapabilities();
EXPECT_TRUE(capabilities.supportsPointerHitTesting);
EXPECT_TRUE(capabilities.supportsHostedSurfaceImages);
EXPECT_TRUE(capabilities.supportsPrimitiveOverlays);
}
} // namespace

View File

@@ -12,7 +12,6 @@ using XCEngine::Editor::XCUIBackend::CreateLegacyImGuiHostedPreviewPresenter;
using XCEngine::Editor::XCUIBackend::CreateLegacyImGuiPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::CreateLegacyImGuiWindowUICompositor;
using XCEngine::Editor::XCUIBackend::RenderLegacyImGuiDemoWindow;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
using XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot;
class ScopedImGuiContext final {
@@ -30,7 +29,7 @@ public:
ScopedImGuiContext& operator=(const ScopedImGuiContext&) = delete;
};
TEST(LegacyImGuiHostInteropTest, CreatesLegacyHostAdaptersWithImGuiBackends) {
TEST(LegacyImGuiHostInteropTest, CreatesLegacyHostAdaptersWithExpectedDebugNames) {
auto compositor = CreateLegacyImGuiWindowUICompositor();
auto presenter = CreateLegacyImGuiHostedPreviewPresenter();
auto canvasHost = CreateLegacyImGuiPanelCanvasHost();
@@ -38,12 +37,7 @@ TEST(LegacyImGuiHostInteropTest, CreatesLegacyHostAdaptersWithImGuiBackends) {
ASSERT_NE(compositor, nullptr);
ASSERT_NE(presenter, nullptr);
ASSERT_NE(canvasHost, nullptr);
EXPECT_EQ(canvasHost->GetBackend(), XCUIPanelCanvasHostBackend::ImGui);
const auto capabilities = canvasHost->GetCapabilities();
EXPECT_TRUE(capabilities.supportsPointerHitTesting);
EXPECT_TRUE(capabilities.supportsHostedSurfaceImages);
EXPECT_TRUE(capabilities.supportsPrimitiveOverlays);
EXPECT_STREQ(canvasHost->GetDebugName(), "ImGuiXCUIPanelCanvasHost");
}
TEST(LegacyImGuiHostInteropTest, ApplyInputCaptureCopiesImGuiIoFlagsIntoSnapshot) {

View File

@@ -8,8 +8,6 @@ using XCEngine::Editor::XCUIBackend::CreateNativeXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::NativeXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasFrameSnapshot;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession;
@@ -22,18 +20,11 @@ XCEngine::UI::UITextureHandle MakeSurfaceTextureHandle(std::uintptr_t nativeHand
return texture;
}
TEST(NativeXCUIPanelCanvasHostTest, FactoryReportsNativeBackendCapabilitiesAndNoSnapshotBeforeBegin) {
TEST(NativeXCUIPanelCanvasHostTest, FactoryCreatesHostWithStableDebugNameAndNoSnapshotBeforeBegin) {
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateNativeXCUIPanelCanvasHost();
ASSERT_NE(host, nullptr);
EXPECT_STREQ(host->GetDebugName(), "NativeXCUIPanelCanvasHost");
EXPECT_EQ(host->GetBackend(), XCUIPanelCanvasHostBackend::Native);
const XCUIPanelCanvasHostCapabilities capabilities = host->GetCapabilities();
EXPECT_FALSE(capabilities.supportsPointerHitTesting);
EXPECT_TRUE(capabilities.supportsHostedSurfaceImages);
EXPECT_TRUE(capabilities.supportsPrimitiveOverlays);
EXPECT_TRUE(capabilities.supportsExternallyDrivenSession);
XCUIPanelCanvasFrameSnapshot snapshot = {};
EXPECT_FALSE(host->TryGetLatestFrameSnapshot(snapshot));

View File

@@ -87,14 +87,6 @@ public:
return "StubCanvasHost";
}
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend GetBackend() const override {
return XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend::Null;
}
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
return {};
}
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override {
lastRequest = request;
++beginCanvasCallCount;

View File

@@ -69,14 +69,6 @@ public:
return "StubCanvasHost";
}
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend GetBackend() const override {
return XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend::Null;
}
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
return {};
}
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest&) override {
return m_session;
}

View File

@@ -8,22 +8,22 @@ using XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::BuildPassiveXCUIPanelCanvasSession;
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
using XCEngine::Editor::XCUIBackend::ResolveXCUIPanelCanvasChildId;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession;
TEST(NewEditorXCUIPanelCanvasHostTest, NullHostReportsExplicitBackendAndCapabilities) {
TEST(NewEditorXCUIPanelCanvasHostTest, NullHostProvidesStableDebugNameAndSafePassiveSessions) {
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateNullXCUIPanelCanvasHost();
ASSERT_NE(host, nullptr);
EXPECT_STREQ(host->GetDebugName(), "NullXCUIPanelCanvasHost");
EXPECT_EQ(host->GetBackend(), XCUIPanelCanvasHostBackend::Null);
const XCUIPanelCanvasHostCapabilities capabilities = host->GetCapabilities();
EXPECT_FALSE(capabilities.supportsPointerHitTesting);
EXPECT_FALSE(capabilities.supportsHostedSurfaceImages);
EXPECT_FALSE(capabilities.supportsPrimitiveOverlays);
const XCUIPanelCanvasSession session = host->BeginCanvas({});
EXPECT_FALSE(session.validCanvas);
EXPECT_FALSE(session.hovered);
EXPECT_FALSE(session.windowFocused);
EXPECT_FLOAT_EQ(session.hostRect.width, 0.0f);
EXPECT_FLOAT_EQ(session.hostRect.height, 0.0f);
host->EndCanvas();
}
TEST(NewEditorXCUIPanelCanvasHostTest, ResolveChildIdFallsBackToStableDefaultForMissingNames) {