From 3e1971591d0e87137a3766ad50f0ad0e2544df40 Mon Sep 17 00:00:00 2001 From: John Lambert Date: Wed, 20 May 2026 14:57:45 -0400 Subject: [PATCH 1/3] docs: add linux-era view shim retirement plan --- .../.openspec.yaml | 2 + .../retire-linux-era-view-shims/design.md | 81 +++++++++ .../retire-linux-era-view-shims/proposal.md | 41 +++++ .../retire-linux-era-view-shims/research.md | 169 ++++++++++++++++++ .../interop/com-contracts/spec.md | 26 +++ .../testing/test-strategy/spec.md | 27 +++ .../ui-framework/views-rendering/spec.md | 25 +++ .../retire-linux-era-view-shims/tasks.md | 52 ++++++ 8 files changed, 423 insertions(+) create mode 100644 openspec/changes/retire-linux-era-view-shims/.openspec.yaml create mode 100644 openspec/changes/retire-linux-era-view-shims/design.md create mode 100644 openspec/changes/retire-linux-era-view-shims/proposal.md create mode 100644 openspec/changes/retire-linux-era-view-shims/research.md create mode 100644 openspec/changes/retire-linux-era-view-shims/specs/architecture/interop/com-contracts/spec.md create mode 100644 openspec/changes/retire-linux-era-view-shims/specs/architecture/testing/test-strategy/spec.md create mode 100644 openspec/changes/retire-linux-era-view-shims/specs/architecture/ui-framework/views-rendering/spec.md create mode 100644 openspec/changes/retire-linux-era-view-shims/tasks.md diff --git a/openspec/changes/retire-linux-era-view-shims/.openspec.yaml b/openspec/changes/retire-linux-era-view-shims/.openspec.yaml new file mode 100644 index 0000000000..8b76914981 --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-05-20 diff --git a/openspec/changes/retire-linux-era-view-shims/design.md b/openspec/changes/retire-linux-era-view-shims/design.md new file mode 100644 index 0000000000..82e9f06382 --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/design.md @@ -0,0 +1,81 @@ +## Context + +FieldWorks is Windows-only, but the Views stack still contains two managed COM-visible shims from the Linux/Mono era: + +- `ViewInputManager`, a `SimpleRootSite.dll` class created by the old non-Windows `VwRootBox` branch to satisfy `IViewInputMgr`. +- `ManagedVwWindow`, a `ManagedVwWindow.dll` class created by old non-Windows selection/page-sizing branches to query a WinForms control client rectangle. + +Current Windows behavior does not use either managed class. Windows `VwRootBox::Init()` creates native `VwTextStore` and queries `IViewInputMgr`; Windows selection/page sizing calls Win32 `GetClientRect`. The managed shims remain as source, project/test topology, generated interop declarations, reg-free manifest inputs, and CLSID exclusions. + +See `research.md` in this change for the evidence map, diagrams, and external documentation notes. + +## Goals / Non-Goals + +**Goals:** + +- Retire `ViewInputManager` and `ManagedVwWindow` as COM activation surfaces for Windows-first FieldWorks. +- Remove dead non-Windows native activation branches that create `CLSID_ViewInputManager` and `CLSID_VwWindow`. +- Clean related build, solution, reg-free manifest, and generated interop artifacts in the same slice. +- Preserve and validate the active Windows `VwTextStore` input path. +- Preserve and validate Win32 `GetClientRect` selection/page geometry behavior. +- Leave a clear audit trail for why these are Linux-era compatibility shims. + +**Non-Goals:** + +- Do not remove native `VwTextStore` or rewrite Windows TSF behavior. +- Do not remove `IViewInputMgr` unless a separate native audit proves all active callers have a replacement. Current evidence says it is required. +- Do not remove `SimpleRootSite.dll` from managed COM manifest inputs wholesale unless every other COM-visible class in that assembly is audited. +- Do not remove unrelated optional COM surfaces such as `ManagedPictureFactory`, `ManagedVwDrawRootBuffered`, or `UnknownProp` paths. +- Do not restore, support, or test Linux builds. + +## Decisions + +### Remove the two shim implementations together + +`ViewInputManager` and `ManagedVwWindow` are part of the same old cross-platform story. Removing only one would leave the repo half-clean and preserve unnecessary build/manifest exclusions. The implementation should retire both in one focused change. + +Alternative considered: keep them deferred indefinitely. That avoids churn but keeps misleading COM-visible managed classes and stale reg-free manifest plumbing around a Windows-only product. + +### Preserve `IViewInputMgr` while removing managed `ViewInputManager` + +The managed `ViewInputManager` class is dormant on Windows, but the `IViewInputMgr` contract is still the native abstraction that `VwTextStore` implements and native Views callers use. The removal should target the managed class and old non-Windows `CreateInstance` branch, not the active interface. + +Alternative considered: remove `IViewInputMgr` entirely. That would become a TSF/native Views refactor and is outside this cleanup. + +### Remove the `VwWindow` coclass and generated managed exposure when removing `ManagedVwWindow` + +`ManagedVwWindow` exists only to implement `IVwWindow` through COM activation. Once the implementation and non-Windows activation branches are gone, keeping the `VwWindow` coclass in `Views.idh` and generated `Views.cs` would preserve a dead activation contract. The conservative path is to remove the coclass and generated class exposure. The `IVwWindow` interface can be removed too if no internal consumers remain after the native branch removal. + +Alternative considered: delete only the C# project. That would leave stale IDL/generated activation metadata and make future audits harder. + +### Keep manifest cleanup in the same implementation slice + +These shims are still represented in `Build/mkall.targets`, `Build/RegFree.targets`, and `Src/Common/FieldWorks/BuildInclude.targets`. Removing source without cleaning manifest inputs would leave confusing or broken reg-free COM output. The implementation must update build inputs and prove the removed CLSIDs disappear from generated manifests while required COM entries remain. + +Alternative considered: stage source deletion and manifest cleanup separately. That increases the chance of transient broken manifests and is unnecessary for this isolated cleanup. + +## Risks / Trade-offs + +- Hidden external CLSID consumer -> Confirm no known out-of-repo automation or extensions depend on either CLSID before merge. If uncertain, record compatibility sign-off in the PR. +- Stale generated Views artifacts -> Clean/regenerate `Views.cs`, `ViewsTlb.*`, `ViewsPs.*`, and related manifests after `Views.idh` edits. Be alert to stale `Output` and `Obj` artifacts. +- Accidental removal of active input behavior -> Keep `IViewInputMgr` and `VwTextStore` intact; run native Views tests and manual IME/composition smoke checks. +- Reg-free manifest regression -> Run reg-free build-task tests and inspect generated manifests for absence of only the targeted CLSIDs. +- Review complexity -> Keep this as a dedicated cleanup PR, separate from Encoding Converters or other managed COM work. + +## Migration Plan + +1. Baseline current behavior with `ManagedVwWindowTests` and `TestViews` before deletion. +2. Remove dead non-Windows native activation branches in `VwRootBox.cpp` and `VwSelection.cpp`, leaving Windows code paths unchanged. +3. Remove `ViewInputManager` as a COM-visible class and delete `ManagedVwWindow` project/test topology. +4. Update `Views.idh`, generated interop, and GUID declarations to remove stale `VwWindow` coclass/interface exposure as appropriate. +5. Clean reg-free manifest inputs and excluded CLSIDs. +6. Run build/test validation and manual RootSite input/selection smoke checks. +7. Update architecture docs/specs when archiving so main specs no longer describe `ManagedVwWindow` as a live bridge. + +Rollback is normal source rollback: restore the shim projects, native `#else` activation branches, and manifest inputs if validation reveals a hidden dependency. + +## Open Questions + +- Is there any known out-of-repo automation, extension, installer probe, or downstream consumer that activates either managed CLSID directly? +- Should `IVwWindow` be removed entirely from `Views.idh`, or should only the `VwWindow` coclass be removed first to minimize generated interface churn? +- Which generated artifacts are committed or expected to be updated in this repository for `Views.idh` changes on this branch? diff --git a/openspec/changes/retire-linux-era-view-shims/proposal.md b/openspec/changes/retire-linux-era-view-shims/proposal.md new file mode 100644 index 0000000000..fcaeeb5968 --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/proposal.md @@ -0,0 +1,41 @@ +## Why + +FieldWorks is now documented as Windows-only, but the Views stack still carries two managed COM shims from the Linux/Mono era: `ViewInputManager` and `ManagedVwWindow`. They are not active on the Windows x64 runtime path, yet they still affect source, generated interop, reg-free manifest inputs, build exclusions, and test topology. + +This change captures the dedicated cleanup needed to retire those shims deliberately, with the Windows `VwTextStore` and Win32 window-size paths validated after removal. + +## What Changes + +- Remove the managed COM activation surface for `ViewInputManager`, the old non-Windows input-method bridge. +- Remove the managed COM activation surface and project/test topology for `ManagedVwWindow`, the old cross-platform HWND wrapper. +- Remove native non-Windows activation branches that create `CLSID_ViewInputManager` or `CLSID_VwWindow`. +- Clean reg-free COM manifest inputs and CLSID exclusion lists for the retired managed shims. +- Update Views IDL/generated artifacts only as far as needed to remove stale `VwWindow` coclass exposure while preserving required Windows input contracts. +- Validate that Windows remains on native `VwTextStore` for TSF/input and Win32 `GetClientRect` for page/selection geometry. + +## Non-goals + +- Do not remove or rewrite the native Windows `VwTextStore` implementation. +- Do not remove `IViewInputMgr` unless a focused native audit proves it is no longer needed; current evidence says it is still active through `VwTextStore`. +- Do not change RootSite rendering, selection semantics, TSF behavior, or IME composition behavior. +- Do not remove unrelated managed COM surfaces such as `ManagedPictureFactory` or `ManagedVwDrawRootBuffered`. +- Do not add global COM registration or registry-based activation. + +## Capabilities + +### New Capabilities + +- None. + +### Modified Capabilities + +- `architecture/interop/com-contracts`: optional Linux-era managed COM shims may be retired only with source, build, manifest, and compatibility cleanup in the same slice. +- `architecture/ui-framework/views-rendering`: Windows Views rendering/input requirements are clarified to use native `VwTextStore` and Win32 window geometry, not the managed shim implementations. +- `architecture/testing/test-strategy`: shim retirement requires native Views, reg-free manifest, and manual RootSite/IME smoke validation. + +## Impact + +- Native C++ Views code: `Src/views/VwRootBox.cpp`, `Src/views/VwSelection.cpp`, `Src/views/Views.idh`, generated Views interop artifacts as needed. +- Managed C# shim code: `Src/Common/SimpleRootSite/ViewInputManager.cs`, `Src/ManagedVwWindow/**`. +- Build and reg-free COM files: `Build/RegFree.targets`, `Build/mkall.targets`, `Src/Common/FieldWorks/BuildInclude.targets`, `FieldWorks.sln`, generated manifests, and affected reg-free tests. +- Validation: native `TestViews`, managed build-task tests, targeted RootSite tests, and manual RootSite keyboard/selection/IME smoke checks. diff --git a/openspec/changes/retire-linux-era-view-shims/research.md b/openspec/changes/retire-linux-era-view-shims/research.md new file mode 100644 index 0000000000..5e6a96fb8d --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/research.md @@ -0,0 +1,169 @@ +# Research: Linux-Era Views COM Shims + +## Summary + +`ViewInputManager` and `ManagedVwWindow` are both compatibility shims from the non-Windows/Linux/Mono era. Current Windows/x64 FieldWorks uses native Views code instead: + +- Text input and IME/composition use native `VwTextStore`, which implements `IViewInputMgr`. +- RootSite window geometry for selection/page operations uses Win32 `GetClientRect`. + +The managed shims are still present as COM-visible types and still influence reg-free manifest generation, build inputs, and solution/test topology. They should be retired together in a dedicated cleanup slice, not mixed into unrelated managed-provider work. + +## Current Platform Policy + +- `Docs/CONTRIBUTING.md` states: FieldWorks is Windows-only; Linux builds are no longer supported. +- The prior COM-reduction OpenSpec marked the Windows-first policy decision for these shims as complete, while leaving implementation tasks optional/deferred. + +## ViewInputManager + +### What it is + +`ViewInputManager` is a managed C# COM class in `Src/Common/SimpleRootSite/ViewInputManager.cs`: + +- `[ComVisible(true)]` +- CLSID `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` +- Implements `IViewInputMgr` +- Source comment: Linux creates this class; Windows uses unmanaged `VwTextStore`. + +Its behavior is mostly no-op, except mouse-down activation of the keyboard through the old IBus/root-site event path. + +### Windows runtime evidence + +`Src/views/VwRootBox.cpp` creates the input manager like this: + +```text +#ifdef ENABLE_TSF +#if defined(WIN32) || defined(WIN64) + new VwTextStore(this) + QueryInterface(IID_IViewInputMgr, &m_qvim) +#else + m_qvim.CreateInstance(CLSID_ViewInputManager) +#endif +#endif +``` + +So the managed shim is only selected for the non-Windows branch. Windows uses `VwTextStore`. + +### Active interface evidence + +`IViewInputMgr` itself is still active and should not be removed casually: + +- `Src/views/VwTextStore.h` inherits `public IViewInputMgr`. +- `Src/views/VwTextStore.cpp` handles `IID_IViewInputMgr` in `QueryInterface`. +- `Src/views/VwRootBox.h` stores `IViewInputMgrPtr m_qvim` and exposes `InputManager()`. +- Native callers use `Root()->InputManager()` in `VwSelection.cpp` and `VwTextBoxes.cpp`. + +Language-service reference lookup found references to `VwRootBox::InputManager()` in native selection/text-box code, but only the definition for the managed `ViewInputManager` class. + +## ManagedVwWindow + +### What it is + +`ManagedVwWindow` is a managed C# COM class in `Src/ManagedVwWindow/ManagedVwWindow.cs`: + +- `[ComVisible(true)]` +- CLSID `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}` +- Implements `IVwWindow` +- Wraps an HWND-like value by calling `Control.FromHandle((IntPtr)value)` +- Returns the WinForms control client rectangle + +It exists to let native code query window properties without calling Win32 directly, which mattered for cross-platform support. + +### Windows runtime evidence + +`Src/views/VwSelection.cpp` has two RootSite geometry paths: + +```text +#if defined(WIN32) || defined(WIN64) + GetClientRect(hwndRootSite, &rcRootSite) +#else + CoCreate CLSID_VwWindow + IVwWindow.Window = hwndRootSite + IVwWindow.GetClientRectangle(...) +#endif +``` + +So Windows never needs `ManagedVwWindow` for page/selection geometry. + +Language-service reference lookup found `ManagedVwWindow` references only in its own unit tests, not product code. + +## Build and Manifest Evidence + +Both shims still affect build/reg-free COM plumbing: + +- `Build/mkall.targets` excludes both managed CLSIDs from native manifests: + - `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}` for `ManagedVwWindow` + - `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` for `ViewInputManager` +- `Build/RegFree.targets` includes `SimpleRootSite.dll` and `ManagedVwWindow.dll` in managed COM manifest inputs. +- `Src/Common/FieldWorks/BuildInclude.targets` includes `ManagedVwWindow.dll` for FieldWorks.exe manifest generation. +- `Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs` uses the `ManagedVwWindow` CLSID as test data for excluded CLSID handling. +- `Src/views/Views.idh` still declares `IVwWindow`, `VwWindow`, and `IViewInputMgr`. +- `Src/Common/ViewsInterfaces/Views.cs` contains generated managed declarations for `IVwWindow`, `VwWindow`, and `IViewInputMgr`. + +`SimpleRootSite.dll` should not be removed wholesale from managed COM manifest inputs unless a separate audit proves every remaining COM-visible type in that assembly is no longer required. The first cleanup target is the `ViewInputManager` class surface, not the entire assembly. + +## Dependency Diagrams + +### Windows active path + +```text +FieldWorks / RootSite + -> VwRootBox::Init() + -> new VwTextStore(this) + -> QueryInterface(IID_IViewInputMgr) + -> m_qvim + -> SetFocus / KillFocus / composition / layout notifications + +Selection page sizing + -> IVwRootSite.get_Hwnd + -> Win32 GetClientRect +``` + +### Dormant non-Windows path + +```text +VwRootBox::Init() + -> CoCreate CLSID_ViewInputManager + -> SimpleRootSite.dll!ViewInputManager + -> old IBus/root-site keyboard bridge + +VwSelection page sizing + -> CoCreate CLSID_VwWindow + -> ManagedVwWindow.dll!ManagedVwWindow + -> Control.FromHandle(...).ClientRectangle +``` + +### Reg-free packaging today + +```text +Build/RegFree.targets + BuildInclude.targets + -> managed COM assembly scan + -> FwUtils.dll + -> SimpleRootSite.dll + -> ManagedVwWindow.dll + +Build/mkall.targets + -> excludes managed shim CLSIDs from native manifests to avoid duplicate SxS entries +``` + +## External Docs Consulted + +- Microsoft Learn, Text Services Framework: TSF is Windows text input infrastructure for Windows-based computers and COM/C++ programmers. This supports keeping native `VwTextStore` as the Windows path. + - https://learn.microsoft.com/en-us/windows/win32/tsf/text-services-framework +- Microsoft Learn, Registration-Free COM Interop: reg-free COM uses application/component manifests instead of registry activation metadata. .NET-based COM classes must be public and have a parameterless constructor for registry-free activation. + - https://learn.microsoft.com/en-us/dotnet/framework/interop/registration-free-com-interop +- Microsoft Learn, Exposing .NET Components to COM: unmanaged clients can activate .NET objects through COM; managed types intended for COM require public COM-facing shape and deployment metadata. + - https://learn.microsoft.com/en-us/dotnet/framework/interop/exposing-dotnet-components-to-com +- Microsoft Learn, `Control.FromHandle(IntPtr)`: returns the WinForms control associated with an HWND, or null if no control is associated with the handle. + - https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.fromhandle +- Microsoft Learn, `NativeWindow`: background for WinForms HWND/message wrapping; relevant only as contrast because Windows FieldWorks already uses native Win32/Views paths here. + - https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.nativewindow + +## Conclusion + +Both managed shim implementations are Linux-era cruft from a product/runtime perspective. The remaining risk is not normal Windows behavior; it is cleanup correctness: + +- keeping `IViewInputMgr` while removing only the managed non-Windows class, +- removing `ManagedVwWindow` without leaving stale `VwWindow` coclass/generated artifacts, +- keeping reg-free manifests accurate, +- proving native `VwTextStore`/`GetClientRect` paths still behave correctly. diff --git a/openspec/changes/retire-linux-era-view-shims/specs/architecture/interop/com-contracts/spec.md b/openspec/changes/retire-linux-era-view-shims/specs/architecture/interop/com-contracts/spec.md new file mode 100644 index 0000000000..d5c9ec6f08 --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/specs/architecture/interop/com-contracts/spec.md @@ -0,0 +1,26 @@ +## ADDED Requirements + +### Requirement: Linux-Era Managed Views Shims Are Optional COM Surfaces +FieldWorks SHALL treat `ViewInputManager` and `ManagedVwWindow` as optional Linux-era managed COM shims, not required Windows runtime COM contracts. + +#### Scenario: ViewInputManager removal is implemented +- **WHEN** `Src/Common/SimpleRootSite/ViewInputManager.cs` is removed or made non-COM-visible +- **THEN** the non-Windows `CLSID_ViewInputManager` activation branch in `Src/views/VwRootBox.cpp` MUST be removed +- **AND** the active Windows `VwTextStore` implementation of `IViewInputMgr` MUST remain intact. + +#### Scenario: ManagedVwWindow removal is implemented +- **WHEN** `Src/ManagedVwWindow/ManagedVwWindow.cs` and its project are removed +- **THEN** the non-Windows `CLSID_VwWindow` activation branches in `Src/views/VwSelection.cpp` MUST be removed +- **AND** stale `VwWindow` coclass exposure in `Src/views/Views.idh` and generated interop artifacts MUST be removed or explicitly justified. + +### Requirement: Shim Retirement Includes Reg-Free COM Cleanup +Retiring either Linux-era managed Views shim SHALL include matching reg-free COM build and manifest cleanup in the same implementation slice. + +#### Scenario: Managed shim CLSIDs are retired +- **WHEN** `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` or `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}` is no longer exposed for COM activation +- **THEN** the corresponding entries in `Build/mkall.targets`, `Build/RegFree.targets`, and `Src/Common/FieldWorks/BuildInclude.targets` MUST be updated where applicable +- **AND** generated manifests MUST be checked to confirm the retired CLSIDs are absent while required native COM entries remain. + +#### Scenario: SimpleRootSite manifest inputs are reviewed +- **WHEN** `ViewInputManager` is removed from `SimpleRootSite.dll` +- **THEN** `SimpleRootSite.dll` MUST remain in managed COM manifest inputs unless a separate audit proves no remaining COM-visible class in that assembly is required. diff --git a/openspec/changes/retire-linux-era-view-shims/specs/architecture/testing/test-strategy/spec.md b/openspec/changes/retire-linux-era-view-shims/specs/architecture/testing/test-strategy/spec.md new file mode 100644 index 0000000000..1e5551e6b2 --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/specs/architecture/testing/test-strategy/spec.md @@ -0,0 +1,27 @@ +## ADDED Requirements + +### Requirement: Windows-First Views Shim Retirement Requires Native and Manifest Validation +Retiring `ViewInputManager` or `ManagedVwWindow` SHALL include validation for native Views behavior and reg-free COM manifest output. + +#### Scenario: Shim source and build entries are removed +- **WHEN** implementation removes either Linux-era managed Views shim from source, solution, or manifest inputs +- **THEN** validation MUST include a native Views test pass using the repository test script +- **AND** validation MUST include reg-free manifest tests or generated-manifest inspection for the retired CLSIDs. + +#### Scenario: Views IDL or generated interop artifacts change +- **WHEN** `Src/views/Views.idh` or generated Views interop artifacts are updated +- **THEN** validation MUST account for native-before-managed build ordering +- **AND** stale generated outputs MUST be cleaned or regenerated before claiming the change is complete. + +### Requirement: Windows RootSite Smoke Testing Covers Input and Geometry +Shim retirement SHALL include manual smoke coverage for the Windows behaviors previously protected by the shims' conceptual responsibilities. + +#### Scenario: Manual input smoke is performed +- **WHEN** the rebuilt application is smoke-tested after shim removal +- **THEN** the tester MUST edit text in a RootSite field, switch keyboards if available, and test IME/composition if available +- **AND** any failures MUST block completion until triaged against the native `VwTextStore` path. + +#### Scenario: Manual selection geometry smoke is performed +- **WHEN** the rebuilt application is smoke-tested after `ManagedVwWindow` removal +- **THEN** the tester MUST exercise mouse selection, keyboard selection, and PageUp/PageDown navigation in a RootSite field +- **AND** visible page movement MUST remain consistent with the pre-removal Windows behavior. diff --git a/openspec/changes/retire-linux-era-view-shims/specs/architecture/ui-framework/views-rendering/spec.md b/openspec/changes/retire-linux-era-view-shims/specs/architecture/ui-framework/views-rendering/spec.md new file mode 100644 index 0000000000..f7b11b146d --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/specs/architecture/ui-framework/views-rendering/spec.md @@ -0,0 +1,25 @@ +## ADDED Requirements + +### Requirement: Windows Views Uses Native Input and Window Geometry Paths +Windows FieldWorks SHALL use native Views/Win32 paths for RootSite input management and window geometry after Linux-era managed shim removal. + +#### Scenario: RootBox input manager is initialized on Windows +- **WHEN** `VwRootBox::Init()` runs in a Windows build +- **THEN** it MUST create or retain the native `VwTextStore` path +- **AND** it MUST obtain the active input manager through `IID_IViewInputMgr` from `VwTextStore`, not through managed `ViewInputManager` COM activation. + +#### Scenario: Selection and page geometry are calculated on Windows +- **WHEN** Views code needs the RootSite client rectangle for page movement or visible page height +- **THEN** it MUST use the Win32 `GetClientRect` path for the RootSite HWND +- **AND** it MUST NOT depend on `ManagedVwWindow` for Windows geometry. + +### Requirement: Views Shim Removal Preserves User-Visible Editing Behavior +Removing Linux-era managed Views shims SHALL preserve Windows text editing, keyboard switching, IME composition, selection movement, and page navigation behavior. + +#### Scenario: A user edits text in a RootSite field +- **WHEN** the user types, switches keyboards, or uses an IME/composition flow in a RootSite field +- **THEN** text input and composition behavior MUST match the pre-removal Windows behavior. + +#### Scenario: A user navigates text by selection and page movement +- **WHEN** the user moves the selection with keyboard/mouse or PageUp/PageDown +- **THEN** Views selection and page movement MUST continue to use the same visible client area semantics as before shim removal. diff --git a/openspec/changes/retire-linux-era-view-shims/tasks.md b/openspec/changes/retire-linux-era-view-shims/tasks.md new file mode 100644 index 0000000000..56d8d98409 --- /dev/null +++ b/openspec/changes/retire-linux-era-view-shims/tasks.md @@ -0,0 +1,52 @@ +## 1. Baseline and Compatibility Checks + +- [ ] 1.1 Confirm no known out-of-repo automation, extension, installer probe, or downstream consumer depends on CLSID `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` for `ViewInputManager`. [Compatibility, <=1h] +- [ ] 1.2 Confirm no known out-of-repo automation, extension, installer probe, or downstream consumer depends on CLSID `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}` for `ManagedVwWindow`. [Compatibility, <=1h] +- [ ] 1.3 Run pre-removal baseline `. est.ps1 -TestProject ManagedVwWindowTests` while the project still exists. [Managed test, <=1h] +- [ ] 1.4 Run pre-removal baseline `. est.ps1 -SkipManaged -TestProject TestViews`. [Native test, <=2h] + +## 2. Native Views Cleanup + +- [ ] 2.1 Remove `CLSID_ViewInputManager` and the non-Windows managed `CreateInstance` branch from `Src/views/VwRootBox.cpp`; keep the Windows `VwTextStore` path intact. [Native C++, <=2h] +- [ ] 2.2 Remove `CLSID_VwWindow` activation branches from `Src/views/VwSelection.cpp`; keep the Windows `GetClientRect` path intact. [Native C++, <=2h] +- [ ] 2.3 Audit native references to `IViewInputMgr`, `VwRootBox::InputManager()`, and `VwTextStore` after cleanup; do not remove active Windows input contracts. [Native C++, <=1h] + +## 3. Managed Shim Removal + +- [ ] 3.1 Remove `Src/Common/SimpleRootSite/ViewInputManager.cs` from source/project inputs without removing unrelated `SimpleRootSite.dll` COM surfaces. [Managed C#, <=2h] +- [ ] 3.2 Remove `Src/ManagedVwWindow/ManagedVwWindow.cs`, `Src/ManagedVwWindow/ManagedVwWindow.csproj`, and `Src/ManagedVwWindow/ManagedVwWindowTests/**`. [Managed C#, <=2h] +- [ ] 3.3 Remove `ManagedVwWindow` and `ManagedVwWindowTests` from `FieldWorks.sln` and any traversal/build inputs that explicitly reference those projects. [Build, <=1h] + +## 4. IDL and Generated Interop Cleanup + +- [ ] 4.1 Remove stale `VwWindow` coclass exposure from `Src/views/Views.idh`; remove `IVwWindow` too only if the native branch removal leaves no valid consumer. [Native/IDL, <=2h] +- [ ] 4.2 Update `Src/views/Views_GUIDs.cpp` and generated `Src/Common/ViewsInterfaces/Views.cs` consistently with the `Views.idh` decision. [Native/managed generated, <=2h] +- [ ] 4.3 Clear or regenerate stale `Output//Common/ViewsTlb.*`, `ViewsPs.*`, `Raw/ViewsTlb*.*`, and `Raw/ViewsPs*.*` artifacts before build validation if `Views.idh` changes. [Build hygiene, <=1h] + +## 5. Reg-Free Manifest and Build Cleanup + +- [ ] 5.1 Remove the `ManagedVwWindow` managed COM assembly input from `Build/RegFree.targets` and `Src/Common/FieldWorks/BuildInclude.targets`. [Build, <=1h] +- [ ] 5.2 Remove retired shim CLSIDs from `Build/mkall.targets` `ExcludedClsids`: `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` and `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}`. [Build, <=1h] +- [ ] 5.3 Update `Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs` so tests no longer rely on the retired `ManagedVwWindow` CLSID as sample data. [Managed test, <=1h] +- [ ] 5.4 Inspect generated manifests after build to confirm the two retired CLSIDs are absent and required native Views/FwKernel COM entries remain present. [Validation, <=1h] + +## 6. Documentation Updates + +- [ ] 6.1 Update architecture docs/specs that currently describe `ManagedVwWindow` as a live bridge, including `openspec/specs/architecture/ui-framework/views-rendering.md` when this change is archived. [Docs, <=1h] +- [ ] 6.2 Update COM inventory notes to record that `ViewInputManager` and `ManagedVwWindow` were retired as Linux-era shims. [Docs, <=1h] +- [ ] 6.3 Update any affected folder `AGENTS.md` or source comments that still describe Linux/Mono paths as supported runtime behavior. [Docs, <=1h] + +## 7. Automated Validation + +- [ ] 7.1 Run `.uild.ps1` to validate native-before-managed ordering and regenerate reg-free manifests. [Build validation] +- [ ] 7.2 Run `. est.ps1 -SkipManaged -TestProject TestViews`. [Native validation] +- [ ] 7.3 Run `. est.ps1 -TestProject FwBuildTasksTests -TestFilter "FullyQualifiedName~RegFreeCreator"`. [Managed validation] +- [ ] 7.4 Run targeted RootSite/Views managed tests, including `. est.ps1 -TestProject SimpleRootSiteTests` if available in the current test routing. [Managed validation] +- [ ] 7.5 Run `CI: Whitespace check`; if it rewrites files, review the diff and rerun until clean. [CI hygiene] + +## 8. Manual Smoke Validation + +- [ ] 8.1 Edit text in a RootSite field in a rebuilt FieldWorks app; verify normal typing and keyboard switching still work. [Manual] +- [ ] 8.2 Test IME/composition in a RootSite field if an IME is available; verify pre-edit and commit behavior still work. [Manual] +- [ ] 8.3 Exercise mouse selection, keyboard selection, Shift+arrow selection, PageUp, and PageDown in a RootSite field; verify selection and visible-page movement remain correct. [Manual] +- [ ] 8.4 Launch from rebuilt output and watch for side-by-side activation or missing manifest errors. [Manual] From ba24829fb394327fa12495c47b461204c21dc3a9 Mon Sep 17 00:00:00 2001 From: John Lambert Date: Wed, 20 May 2026 20:01:15 -0400 Subject: [PATCH 2/3] Initial implementation --- .github/src-catalog.md | 3 - Build/RegFree.targets | 1 - Build/Src/FwBuildTasks/CollectTargets.cs | 4 - Build/mkall.targets | 2 - FieldWorks.sln | 16 -- Src/Common/FieldWorks/BuildInclude.targets | 1 - Src/Common/SimpleRootSite/ViewInputManager.cs | 166 ------------------ Src/ManagedVwWindow/AssemblyInfo.cs | 11 -- Src/ManagedVwWindow/ManagedVwWindow.cs | 48 ----- Src/ManagedVwWindow/ManagedVwWindow.csproj | 32 ---- .../ManagedVwWindowTests.cs | 41 ----- .../ManagedVwWindowTests.csproj | 44 ----- Src/views/Views.idh | 24 +-- Src/views/Views_GUIDs.cpp | 2 - Src/views/VwRootBox.cpp | 8 - Src/views/VwSelection.cpp | 14 -- Src/views/VwTextStore.cpp | 6 +- .../retire-linux-era-view-shims/tasks.md | 50 +++--- .../architecture/interop/com-contracts.md | 1 + .../architecture/interop/native-boundary.md | 3 +- .../ui-framework/views-rendering.md | 3 +- 21 files changed, 32 insertions(+), 448 deletions(-) delete mode 100644 Src/Common/SimpleRootSite/ViewInputManager.cs delete mode 100644 Src/ManagedVwWindow/AssemblyInfo.cs delete mode 100644 Src/ManagedVwWindow/ManagedVwWindow.cs delete mode 100644 Src/ManagedVwWindow/ManagedVwWindow.csproj delete mode 100644 Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.cs delete mode 100644 Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.csproj diff --git a/.github/src-catalog.md b/.github/src-catalog.md index 2eb056c635..009d0b3b07 100644 --- a/.github/src-catalog.md +++ b/.github/src-catalog.md @@ -66,9 +66,6 @@ Managed ILgCollatingEngine implementation that wraps ICU.NET to deliver locale-a ### ManagedVwDrawRootBuffered Managed IVwDrawRootBuffered implementation that renders native Views content to an off-screen bitmap before blitting, eliminating flicker in rich text views. -### ManagedVwWindow -Minimal IVwWindow adapter that maps WinForms controls to native HWND expectations so the Views engine can render inside .NET windows. - ### MigrateSqlDbs Historical SQL→XML migration utility used for the FieldWorks 6→7 transition; kept for archival reference. diff --git a/Build/RegFree.targets b/Build/RegFree.targets index a4593692f0..9775afbf1c 100644 --- a/Build/RegFree.targets +++ b/Build/RegFree.targets @@ -67,7 +67,6 @@ - diff --git a/Build/Src/FwBuildTasks/CollectTargets.cs b/Build/Src/FwBuildTasks/CollectTargets.cs index 6c757b0659..483e11d4bb 100644 --- a/Build/Src/FwBuildTasks/CollectTargets.cs +++ b/Build/Src/FwBuildTasks/CollectTargets.cs @@ -563,10 +563,6 @@ private void WriteTargetFiles() { writer.Write(" Condition=\"'$(OS)'=='Windows_NT'\""); } - if (project.StartsWith("ManagedVwWindow")) - { - writer.Write(" Condition=\"'$(OS)'=='Unix'\""); - } writer.WriteLine(">"); // task diff --git a/Build/mkall.targets b/Build/mkall.targets index 57aa3ead1c..03670e185b 100644 --- a/Build/mkall.targets +++ b/Build/mkall.targets @@ -43,9 +43,7 @@ - - diff --git a/FieldWorks.sln b/FieldWorks.sln index c7ca074998..a4dc0615a2 100644 --- a/FieldWorks.sln +++ b/FieldWorks.sln @@ -116,10 +116,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedLgIcuCollatorTests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedVwDrawRootBuffered", "Src\ManagedVwDrawRootBuffered\ManagedVwDrawRootBuffered.csproj", "{BD5AFBAD-6C0C-5C44-912D-D26745CF8F62}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedVwWindow", "Src\ManagedVwWindow\ManagedVwWindow.csproj", "{5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedVwWindowTests", "Src\ManagedVwWindow\ManagedVwWindowTests\ManagedVwWindowTests.csproj", "{FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MessageBoxExLib", "Src\Utilities\MessageBoxExLib\MessageBoxExLib.csproj", "{C5AA04DD-F91B-5156-BD40-4A761058AC64}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MessageBoxExLibTests", "Src\Utilities\MessageBoxExLib\MessageBoxExLibTests\MessageBoxExLibTests.csproj", "{F2525F78-38CD-5E36-A854-E16BE8A1B8FF}" @@ -633,18 +629,6 @@ Global {BD5AFBAD-6C0C-5C44-912D-D26745CF8F62}.Debug|x64.Build.0 = Debug|x64 {BD5AFBAD-6C0C-5C44-912D-D26745CF8F62}.Release|x64.ActiveCfg = Release|x64 {BD5AFBAD-6C0C-5C44-912D-D26745CF8F62}.Release|x64.Build.0 = Release|x64 - {5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}.Bounds|x64.ActiveCfg = Release|x64 - {5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}.Bounds|x64.Build.0 = Release|x64 - {5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}.Debug|x64.ActiveCfg = Debug|x64 - {5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}.Debug|x64.Build.0 = Debug|x64 - {5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}.Release|x64.ActiveCfg = Release|x64 - {5FD892A2-7F18-5DAA-B4DF-1C79A45E7025}.Release|x64.Build.0 = Release|x64 - {FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}.Bounds|x64.ActiveCfg = Release|x64 - {FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}.Bounds|x64.Build.0 = Release|x64 - {FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}.Debug|x64.ActiveCfg = Debug|x64 - {FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}.Debug|x64.Build.0 = Debug|x64 - {FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}.Release|x64.ActiveCfg = Release|x64 - {FF2D5865-1799-5EE8-A46B-3CD86EA9D9EE}.Release|x64.Build.0 = Release|x64 {C5AA04DD-F91B-5156-BD40-4A761058AC64}.Bounds|x64.ActiveCfg = Release|x64 {C5AA04DD-F91B-5156-BD40-4A761058AC64}.Bounds|x64.Build.0 = Release|x64 {C5AA04DD-F91B-5156-BD40-4A761058AC64}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/Src/Common/FieldWorks/BuildInclude.targets b/Src/Common/FieldWorks/BuildInclude.targets index 8da91fd1e2..a9c9e96c43 100644 --- a/Src/Common/FieldWorks/BuildInclude.targets +++ b/Src/Common/FieldWorks/BuildInclude.targets @@ -8,7 +8,6 @@ - diff --git a/Src/Common/SimpleRootSite/ViewInputManager.cs b/Src/Common/SimpleRootSite/ViewInputManager.cs deleted file mode 100644 index e193791c87..0000000000 --- a/Src/Common/SimpleRootSite/ViewInputManager.cs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2011-2017 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) - -using System.Runtime.InteropServices; -using SIL.LCModel.Core.WritingSystems; -using SIL.FieldWorks.Common.ViewsInterfaces; -using SIL.Keyboarding; -using SIL.Windows.Forms.Keyboarding; - -namespace SIL.FieldWorks.Common.RootSites -{ - /// - /// Connects a view (rootbox) with keyboards. This class gets created by the VwRootBox on - /// Linux. Windows uses an unmanaged implementation (VwTextStore). - /// - [ComVisible(true)] - [Guid("830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E")] - public class ViewInputManager: IViewInputMgr - { - private IVwRootBox m_rootb; - - private IbusRootSiteEventHandler RootSiteEventHandler - { - get - { - var simpleRootSite = m_rootb.Site as SimpleRootSite; - return simpleRootSite == null ? null : - simpleRootSite.RootSiteEventHandler as IbusRootSiteEventHandler; - } - } - - #region IViewInputMgr methods - /// - /// Inititialize the input manager - /// - public void Init(IVwRootBox rootb) - { - m_rootb = rootb; - } - - /// - public void Close() - { - } - - /// - /// End all active compositions. Not applicable on Mono. - /// - public void TerminateAllCompositions() - { - } - - /// - /// Activate the input method - /// - public void SetFocus() - { - } - - /// - /// Deactivate the input method - /// - public void KillFocus() - { - } - - /// - /// Gets a value indicating whether a composition window is active. - /// - public bool IsCompositionActive - { - get { return RootSiteEventHandler != null && RootSiteEventHandler.IsPreeditActive; } - } - - /// - /// Gets a value indicating if the input method is in the process of closing a composition - /// window. - /// - public bool IsEndingComposition - { - get { return false; } - } - - /// - /// Called before a property gets updated. - /// - /// Returns true if the property should be updated without normalization - /// (i.e. not updated in the database) in order to avoid messing up compositions; - /// false if property can be processed regularly. - public bool OnUpdateProp() - { - return false; - } - - /// - /// Called when a mouse event happened. - /// - /// Returns false. Returning true would mean that no further - /// processing of the mouse event should happen. - public bool OnMouseEvent(int xd, int yd, Rect rcSrc, Rect rcDst, VwMouseEvent me) - { - if (me == VwMouseEvent.kmeDown) - Keyboard.Activate(); - return false; - } - - /// - /// Called when the layout of the view changes. - /// - public void OnLayoutChange() - { - } - - /// - /// Called when the selection changes. - /// - public void OnSelectionChange(int nHow) - { - } - - /// - /// Called when the text changes. - /// - public void OnTextChange() - { - } - #endregion /* IViewInputMgr */ - - private CoreWritingSystemDefinition CurrentWritingSystem - { - get - { - IVwSelection sel = m_rootb.Selection; - int nWs = SelectionHelper.GetFirstWsOfSelection(sel); - if (nWs == 0) - return null; - - var wsf = m_rootb.DataAccess.WritingSystemFactory; - if (wsf == null) - return null; - - return (CoreWritingSystemDefinition) wsf.get_EngineOrNull(nWs); - } - } - - /// - /// Gets the keyboard corresponding to the current selection. - /// - /// The keyboard, or KeyboardDescription.Zero if we can't detect the writing - /// system based on the current selection (e.g. there is no selection). - public IKeyboardDefinition Keyboard - { - get - { - var manager = (WritingSystemManager) m_rootb.DataAccess.WritingSystemFactory; - CoreWritingSystemDefinition ws = CurrentWritingSystem; - if (ws == null) - return KeyboardController.NullKeyboard; - - CoreWritingSystemDefinition wsd = manager.Get(ws.Handle); - return wsd.LocalKeyboard ?? KeyboardController.NullKeyboard; - } - } - } -} diff --git a/Src/ManagedVwWindow/AssemblyInfo.cs b/Src/ManagedVwWindow/AssemblyInfo.cs deleted file mode 100644 index 0eb1b2e258..0000000000 --- a/Src/ManagedVwWindow/AssemblyInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2010-2013 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) - -// -------------------------------------------------------------------------------------------- -using System.Reflection; -using System.Runtime.CompilerServices; - -// [assembly: AssemblyTitle("ManagedVwWindow")] // Sanitized by convert_generate_assembly_info - -// [assembly: System.Runtime.InteropServices.ComVisible(false)] // Sanitized by convert_generate_assembly_info \ No newline at end of file diff --git a/Src/ManagedVwWindow/ManagedVwWindow.cs b/Src/ManagedVwWindow/ManagedVwWindow.cs deleted file mode 100644 index 1616a888ef..0000000000 --- a/Src/ManagedVwWindow/ManagedVwWindow.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2015 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) - -using System; -using System.Windows.Forms; -using SIL.FieldWorks.Common.ViewsInterfaces; -using System.Runtime.InteropServices; - -namespace SIL.FieldWorks.Views -{ - /// - /// This class wrapps a hwnd to allow cross platform access to - /// window properties. - /// - [ComVisible(true)] - [Guid("3fb0fcd2-ac55-42a8-b580-73b89a2b6215")] - public class ManagedVwWindow : IVwWindow - { - // the wrapped Window - protected Control m_control = null; - - #region IVwWindow Members - - public void GetClientRectangle(out Rect clientRectangle) - { - if ( m_control == null) - throw new ApplicationException("Window not set"); - - clientRectangle.top = m_control.ClientRectangle.Top; - clientRectangle.left = m_control.ClientRectangle.Left; - clientRectangle.right = m_control.ClientRectangle.Right; - clientRectangle.bottom = m_control.ClientRectangle.Bottom; - } - - public uint Window - { - set - { - var ptr = (IntPtr) value; - m_control = Control.FromHandle(ptr); - } - } - - #endregion - } - -} // end namespace SIL.FieldWorks.Views diff --git a/Src/ManagedVwWindow/ManagedVwWindow.csproj b/Src/ManagedVwWindow/ManagedVwWindow.csproj deleted file mode 100644 index 884df51f65..0000000000 --- a/Src/ManagedVwWindow/ManagedVwWindow.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - ManagedVwWindow - ManagedVwWindow - net48 - Library 168,169,219,414,649,1635,1702,1701 - false - false - - - true - portable - false - DEBUG - - - - - - - - - - - - - - Properties\CommonAssemblyInfo.cs - - - \ No newline at end of file diff --git a/Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.cs b/Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.cs deleted file mode 100644 index e21b449894..0000000000 --- a/Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2015-2017 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) - -using System; -using System.Windows.Forms; -using NUnit.Framework; -using SIL.FieldWorks.Common.ViewsInterfaces; -using SIL.FieldWorks.Views; - -namespace SIL.FieldWorks.Language -{ - [TestFixture] - public class ManagedVwWindowTests - { - [Test] - public void SimpleWindowTest() - { - using (var c = new Control()) - { - var wrappedWindow = new ManagedVwWindow(); - wrappedWindow.Window = (uint)c.Handle; - Rect temp; - wrappedWindow.GetClientRectangle(out temp); - - Assert.That(temp.left, Is.EqualTo(c.ClientRectangle.Left), "Left not the same"); - Assert.That(temp.right, Is.EqualTo(c.ClientRectangle.Right), "Right not the same"); - Assert.That(temp.top, Is.EqualTo(c.ClientRectangle.Top), "Top not the same"); - Assert.That(temp.bottom, Is.EqualTo(c.ClientRectangle.Bottom), "Bottom not the same"); - } - } - - [Test] - public void NotSettingWindowTest() - { - var wrappedWindow = new ManagedVwWindow(); - Rect temp; - Assert.That(() => wrappedWindow.GetClientRectangle(out temp), Throws.TypeOf()); - } - } -} diff --git a/Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.csproj b/Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.csproj deleted file mode 100644 index ce51476f4a..0000000000 --- a/Src/ManagedVwWindow/ManagedVwWindowTests/ManagedVwWindowTests.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - ManagedVwWindowTests - SIL.FieldWorks.Language - net48 - Library 168,169,219,414,649,1635,1702,1701 - true - false - false - - - true - portable - false - DEBUG - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - Properties\CommonAssemblyInfo.cs - - - \ No newline at end of file diff --git a/Src/views/Views.idh b/Src/views/Views.idh index d4a07d57df..867ae01776 100644 --- a/Src/views/Views.idh +++ b/Src/views/Views.idh @@ -4911,28 +4911,6 @@ DeclareInterface(VwLayoutManager, Unknown, 13F3A421-4915-455b-B57F-AFD4073CFFA0) }; #endif // !NO_COCLASSES - - /******************************************************************************************* - Interface IVwWindow - COM interface that wraps a Window handle/HWND - Allows cross platform querying of Window properties - *******************************************************************************************/ - DeclareInterface(VwWindow, Unknown, 8856396c-63a9-4bc7-ad47-87ec8b6ef5a4) - { - [propput] HRESULT Window([in] DWORD * hwnd); - - HRESULT GetClientRectangle( - [out] RECT * prcClientRectangle); - } - - #ifndef NO_COCLASSES - DeclareCoClass(VwWindow, 3fb0fcd2-ac55-42a8-b580-73b89a2b6215) - { - interface IVwWindow; - }; - #endif // !NO_COCLASSES - - typedef [v1_enum] enum VwMouseEvent { // Mouse event types that we can identify from info passed to us. @@ -4946,7 +4924,7 @@ typedef [v1_enum] enum VwMouseEvent /******************************************************************************************* Interface IViewInputMgr - Allows interacting with input methods/keyboards in a cross-platform compatible way. + Allows interacting with input methods/keyboards for RootSite editing. *******************************************************************************************/ DeclareInterface(ViewInputMgr, Unknown, e41668f7-d506-4c8a-a5d7-feae5630797e) { diff --git a/Src/views/Views_GUIDs.cpp b/Src/views/Views_GUIDs.cpp index 8e1b2d762d..40a61428c3 100644 --- a/Src/views/Views_GUIDs.cpp +++ b/Src/views/Views_GUIDs.cpp @@ -53,8 +53,6 @@ DEFINE_UUIDOF(LgUnicodeCollater, 0x0D9900D2, 0x1693, 0x481F, 0xAA, 0x70, 0x7E, 0 DEFINE_UUIDOF(VwLayoutStream, 0x1CD09E06, 0x6978, 0x4969, 0xA1, 0xFC, 0x46, 0x27, 0x23, 0x58, 0x7C, 0x32); DEFINE_UUIDOF(IPictureFactory, 0x110B7E88, 0x2968, 0x11E0, 0xB4, 0x93, 0x00, 0x19, 0xDB, 0xF4, 0x56, 0x6E); DEFINE_UUIDOF(PictureFactory, 0x17A2E876, 0x2968, 0x11E0, 0x80, 0x46, 0x00, 0x19, 0xDB, 0xF4, 0x56, 0x6E); -DEFINE_UUIDOF(IVwWindow, 0x8856396c, 0x63a9, 0x4bc7, 0xad, 0x47, 0x87, 0xec, 0x8b, 0x6e, 0xf5, 0xa4); -DEFINE_UUIDOF(VwWindow, 0x3fb0fcd2, 0xac55, 0x42a8, 0xb5, 0x80, 0x73, 0xb8, 0x9a, 0x2b, 0x62, 0x15); DEFINE_UUIDOF(IViewInputMgr, 0xe41668f7, 0xd506, 0x4c8a, 0xa5, 0xd7, 0xfe, 0xae, 0x56, 0x30, 0x79, 0x7e); DEFINE_UUIDOF(VwStylesheet, 0xCCE2A7ED, 0x464C, 0x4ec7, 0xA0, 0xB0, 0xE3, 0xC1, 0xF6, 0xB9, 0x4C, 0x5A); DEFINE_UUIDOF(TsStrFactory, 0xF3359BD1, 0xEFA1, 0x49E6, 0xA8, 0x2E, 0xE5, 0x58, 0x93, 0xFE, 0x63, 0xE0); diff --git a/Src/views/VwRootBox.cpp b/Src/views/VwRootBox.cpp index 4c087c0d66..817a7bc3d0 100644 --- a/Src/views/VwRootBox.cpp +++ b/Src/views/VwRootBox.cpp @@ -29,10 +29,6 @@ DEFINE_THIS_FILE #undef Tracing_KeybdSelection //#define Tracing_KeybdSelection -#if !defined(_WIN32) && !defined(_M_X64) -const CLSID CLSID_ViewInputManager = {0x830BAF1F, 0x6F84, 0x46EF, {0xB6, 0x3E, 0x3C, 0x1B, 0xFD, 0xF9, 0xE8, 0x3E}}; -#endif - //:>******************************************************************************************** //:> Forward declarations //:>******************************************************************************************** @@ -90,13 +86,9 @@ void VwRootBox::Init() m_ptDpiSrc.y = 96; #ifdef ENABLE_TSF -#if defined(WIN32) || defined(WIN64) VwTextStorePtr qtxs; qtxs.Attach(NewObj VwTextStore(this)); CheckHr(qtxs->QueryInterface(IID_IViewInputMgr, (void**)&m_qvim)); -#else - m_qvim.CreateInstance(CLSID_ViewInputManager); -#endif #endif /*ENABLE_TSF*/ } diff --git a/Src/views/VwSelection.cpp b/Src/views/VwSelection.cpp index e5eb3f1c17..5705e2581b 100644 --- a/Src/views/VwSelection.cpp +++ b/Src/views/VwSelection.cpp @@ -617,17 +617,10 @@ void VwSelection::DoCtrlPageUpDown(IVwGraphics * pvg, Rect rcDocumentCoord, Rect Rect rcRootSite; -#if defined(WIN32) || defined(WIN64) if(!GetClientRect(hwndRootSite, &rcRootSite)){ Assert(false); // we better have a valid HWND at this point! That's the only reason GetClientRect should fail that we could think of. return; } -#else - ComSmartPtr qhwndWrapper; - qhwndWrapper.CreateInstance(CLSID_VwWindow); - CheckHr(qhwndWrapper->put_Window(reinterpret_cast(hwndRootSite))); - CheckHr(qhwndWrapper->GetClientRectangle(&rcRootSite)); -#endif // rcRootSite is in client coordinates. Map rcRootSite from client coordinates to document coordinates // rcRootSite.Map(rcClientCoord, rcDocumentCoord); @@ -682,17 +675,10 @@ COMINT32 VwSelection::VisiblePageHeight(IVwGraphics * pvg, Rect rcDocumentCoord, Assert(hwndRootSite); Rect rcRootSite; -#if defined(WIN32) || defined(WIN64) if(!GetClientRect(hwndRootSite, &rcRootSite)){ Assert(false); // we better have a valid HWND at this point! That's the only reason GetClientRect should fail that we could think of. return 0; } -#else - ComSmartPtr qhwndWrapper; - qhwndWrapper.CreateInstance(CLSID_VwWindow); - CheckHr(qhwndWrapper->put_Window(reinterpret_cast(hwndRootSite))); - CheckHr(qhwndWrapper->GetClientRectangle(&rcRootSite)); -#endif // rcRootSite is in client coordinates. Map rcRootSite from client coordinates to document coordinates //rcRootSite.Map(rcClientCoord, rcDocumentCoord); diff --git a/Src/views/VwTextStore.cpp b/Src/views/VwTextStore.cpp index 7a63219e96..c210f43cb9 100644 --- a/Src/views/VwTextStore.cpp +++ b/Src/views/VwTextStore.cpp @@ -17,7 +17,7 @@ Last reviewed: Not yet. regardless of how much text actually exists in the rootbox. This class basically connects a view (rootbox) with keyboards. This class gets created by - the VwRootBox on Windows. Linux uses a managed implementation (ViewInputManager). + the VwRootBox on Windows. -------------------------------------------------------------------------------*//*:End Ignore*/ //:>******************************************************************************************** @@ -1285,11 +1285,7 @@ STDMETHODIMP VwTextStore::GetTextExt(TsViewCookie vcView, LONG acpStart, LONG ac CheckHr(qsel->Location(hg.m_qvg, hg.m_rcSrcRoot, hg.m_rcDstRoot, &rcSel, &rcSecondary, &fSplit, &fEBAIgnored)); } -#if defined(WIN32) || defined(WIN64) rcSel.ClientToScreen(hwnd); -#else - // TODO-Linux: Awaiting VwTextStore rewrite for Linux -#endif *prc = rcSel; #ifdef TRACING_TSF StrAnsi sta; diff --git a/openspec/changes/retire-linux-era-view-shims/tasks.md b/openspec/changes/retire-linux-era-view-shims/tasks.md index 56d8d98409..780575dedb 100644 --- a/openspec/changes/retire-linux-era-view-shims/tasks.md +++ b/openspec/changes/retire-linux-era-view-shims/tasks.md @@ -1,48 +1,48 @@ ## 1. Baseline and Compatibility Checks -- [ ] 1.1 Confirm no known out-of-repo automation, extension, installer probe, or downstream consumer depends on CLSID `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` for `ViewInputManager`. [Compatibility, <=1h] -- [ ] 1.2 Confirm no known out-of-repo automation, extension, installer probe, or downstream consumer depends on CLSID `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}` for `ManagedVwWindow`. [Compatibility, <=1h] -- [ ] 1.3 Run pre-removal baseline `. est.ps1 -TestProject ManagedVwWindowTests` while the project still exists. [Managed test, <=1h] -- [ ] 1.4 Run pre-removal baseline `. est.ps1 -SkipManaged -TestProject TestViews`. [Native test, <=2h] +- [x] 1.1 Confirm no known out-of-repo automation, extension, installer probe, or downstream consumer depends on CLSID `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` for `ViewInputManager`. [Compatibility, <=1h] +- [x] 1.2 Confirm no known out-of-repo automation, extension, installer probe, or downstream consumer depends on CLSID `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}` for `ManagedVwWindow`. [Compatibility, <=1h] +- [x] 1.3 Run pre-removal baseline `.\test.ps1 -TestProject ManagedVwWindowTests` while the project still exists. [Managed test, <=1h] +- [x] 1.4 Run pre-removal baseline `.\test.ps1 -SkipManaged -TestProject TestViews`. [Native test, <=2h] ## 2. Native Views Cleanup -- [ ] 2.1 Remove `CLSID_ViewInputManager` and the non-Windows managed `CreateInstance` branch from `Src/views/VwRootBox.cpp`; keep the Windows `VwTextStore` path intact. [Native C++, <=2h] -- [ ] 2.2 Remove `CLSID_VwWindow` activation branches from `Src/views/VwSelection.cpp`; keep the Windows `GetClientRect` path intact. [Native C++, <=2h] -- [ ] 2.3 Audit native references to `IViewInputMgr`, `VwRootBox::InputManager()`, and `VwTextStore` after cleanup; do not remove active Windows input contracts. [Native C++, <=1h] +- [x] 2.1 Remove `CLSID_ViewInputManager` and the non-Windows managed `CreateInstance` branch from `Src/views/VwRootBox.cpp`; keep the Windows `VwTextStore` path intact. [Native C++, <=2h] +- [x] 2.2 Remove `CLSID_VwWindow` activation branches from `Src/views/VwSelection.cpp`; keep the Windows `GetClientRect` path intact. [Native C++, <=2h] +- [x] 2.3 Audit native references to `IViewInputMgr`, `VwRootBox::InputManager()`, and `VwTextStore` after cleanup; do not remove active Windows input contracts. [Native C++, <=1h] ## 3. Managed Shim Removal -- [ ] 3.1 Remove `Src/Common/SimpleRootSite/ViewInputManager.cs` from source/project inputs without removing unrelated `SimpleRootSite.dll` COM surfaces. [Managed C#, <=2h] -- [ ] 3.2 Remove `Src/ManagedVwWindow/ManagedVwWindow.cs`, `Src/ManagedVwWindow/ManagedVwWindow.csproj`, and `Src/ManagedVwWindow/ManagedVwWindowTests/**`. [Managed C#, <=2h] -- [ ] 3.3 Remove `ManagedVwWindow` and `ManagedVwWindowTests` from `FieldWorks.sln` and any traversal/build inputs that explicitly reference those projects. [Build, <=1h] +- [x] 3.1 Remove `Src/Common/SimpleRootSite/ViewInputManager.cs` from source/project inputs without removing unrelated `SimpleRootSite.dll` COM surfaces. [Managed C#, <=2h] +- [x] 3.2 Remove `Src/ManagedVwWindow/ManagedVwWindow.cs`, `Src/ManagedVwWindow/ManagedVwWindow.csproj`, and `Src/ManagedVwWindow/ManagedVwWindowTests/**`. [Managed C#, <=2h] +- [x] 3.3 Remove `ManagedVwWindow` and `ManagedVwWindowTests` from `FieldWorks.sln` and any traversal/build inputs that explicitly reference those projects. [Build, <=1h] ## 4. IDL and Generated Interop Cleanup -- [ ] 4.1 Remove stale `VwWindow` coclass exposure from `Src/views/Views.idh`; remove `IVwWindow` too only if the native branch removal leaves no valid consumer. [Native/IDL, <=2h] -- [ ] 4.2 Update `Src/views/Views_GUIDs.cpp` and generated `Src/Common/ViewsInterfaces/Views.cs` consistently with the `Views.idh` decision. [Native/managed generated, <=2h] -- [ ] 4.3 Clear or regenerate stale `Output//Common/ViewsTlb.*`, `ViewsPs.*`, `Raw/ViewsTlb*.*`, and `Raw/ViewsPs*.*` artifacts before build validation if `Views.idh` changes. [Build hygiene, <=1h] +- [x] 4.1 Remove stale `VwWindow` coclass exposure from `Src/views/Views.idh`; remove `IVwWindow` too only if the native branch removal leaves no valid consumer. [Native/IDL, <=2h] +- [x] 4.2 Update `Src/views/Views_GUIDs.cpp` and generated `Src/Common/ViewsInterfaces/Views.cs` consistently with the `Views.idh` decision. [Native/managed generated, <=2h] +- [x] 4.3 Clear or regenerate stale `Output//Common/ViewsTlb.*`, `ViewsPs.*`, `Raw/ViewsTlb*.*`, and `Raw/ViewsPs*.*` artifacts before build validation if `Views.idh` changes. [Build hygiene, <=1h] ## 5. Reg-Free Manifest and Build Cleanup -- [ ] 5.1 Remove the `ManagedVwWindow` managed COM assembly input from `Build/RegFree.targets` and `Src/Common/FieldWorks/BuildInclude.targets`. [Build, <=1h] -- [ ] 5.2 Remove retired shim CLSIDs from `Build/mkall.targets` `ExcludedClsids`: `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` and `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}`. [Build, <=1h] -- [ ] 5.3 Update `Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs` so tests no longer rely on the retired `ManagedVwWindow` CLSID as sample data. [Managed test, <=1h] -- [ ] 5.4 Inspect generated manifests after build to confirm the two retired CLSIDs are absent and required native Views/FwKernel COM entries remain present. [Validation, <=1h] +- [x] 5.1 Remove the `ManagedVwWindow` managed COM assembly input from `Build/RegFree.targets` and `Src/Common/FieldWorks/BuildInclude.targets`. [Build, <=1h] +- [x] 5.2 Remove retired shim CLSIDs from `Build/mkall.targets` `ExcludedClsids`: `{830BAF1F-6F84-46EF-B63E-3C1BFDF9E83E}` and `{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}`. [Build, <=1h] +- [x] 5.3 Update `Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs` so tests no longer rely on the retired `ManagedVwWindow` CLSID as sample data. [Managed test, <=1h] +- [x] 5.4 Inspect generated manifests after build to confirm the two retired CLSIDs are absent and required native Views/FwKernel COM entries remain present. [Validation, <=1h] ## 6. Documentation Updates -- [ ] 6.1 Update architecture docs/specs that currently describe `ManagedVwWindow` as a live bridge, including `openspec/specs/architecture/ui-framework/views-rendering.md` when this change is archived. [Docs, <=1h] -- [ ] 6.2 Update COM inventory notes to record that `ViewInputManager` and `ManagedVwWindow` were retired as Linux-era shims. [Docs, <=1h] -- [ ] 6.3 Update any affected folder `AGENTS.md` or source comments that still describe Linux/Mono paths as supported runtime behavior. [Docs, <=1h] +- [x] 6.1 Update architecture docs/specs that currently describe `ManagedVwWindow` as a live bridge, including `openspec/specs/architecture/ui-framework/views-rendering.md` when this change is archived. [Docs, <=1h] +- [x] 6.2 Update COM inventory notes to record that `ViewInputManager` and `ManagedVwWindow` were retired as Linux-era shims. [Docs, <=1h] +- [x] 6.3 Update any affected folder `AGENTS.md` or source comments that still describe Linux/Mono paths as supported runtime behavior. [Docs, <=1h] ## 7. Automated Validation -- [ ] 7.1 Run `.uild.ps1` to validate native-before-managed ordering and regenerate reg-free manifests. [Build validation] -- [ ] 7.2 Run `. est.ps1 -SkipManaged -TestProject TestViews`. [Native validation] -- [ ] 7.3 Run `. est.ps1 -TestProject FwBuildTasksTests -TestFilter "FullyQualifiedName~RegFreeCreator"`. [Managed validation] -- [ ] 7.4 Run targeted RootSite/Views managed tests, including `. est.ps1 -TestProject SimpleRootSiteTests` if available in the current test routing. [Managed validation] -- [ ] 7.5 Run `CI: Whitespace check`; if it rewrites files, review the diff and rerun until clean. [CI hygiene] +- [x] 7.1 Run `.\build.ps1` to validate native-before-managed ordering and regenerate reg-free manifests. [Build validation] +- [x] 7.2 Run `.\test.ps1 -SkipManaged -TestProject TestViews`. [Native validation] +- [x] 7.3 Run `.\test.ps1 -TestProject FwBuildTasksTests -TestFilter "FullyQualifiedName~RegFreeCreator"`. [Managed validation] +- [x] 7.4 Run targeted RootSite/Views managed tests, including `.\test.ps1 -TestProject SimpleRootSiteTests` if available in the current test routing. [Managed validation] +- [x] 7.5 Run `CI: Whitespace check`; if it rewrites files, review the diff and rerun until clean. [CI hygiene] ## 8. Manual Smoke Validation diff --git a/openspec/specs/architecture/interop/com-contracts.md b/openspec/specs/architecture/interop/com-contracts.md index 3c28c1047c..d53edd7f1b 100644 --- a/openspec/specs/architecture/interop/com-contracts.md +++ b/openspec/specs/architecture/interop/com-contracts.md @@ -21,6 +21,7 @@ FieldWorks relies on registration-free COM to avoid global registry pollution. N - COM interfaces are authored in native projects (IDL, GUIDs) and built into proxy/stub DLLs. - Managed components consume COM interfaces through interop boundaries and wrapper libraries. - Registration-free COM manifests are generated and distributed via build targets; avoid global registration. +- ViewInputManager and ManagedVwWindow were retired as Linux-era managed COM shims; Windows RootSite input and geometry use native Views/Win32 paths. #### References diff --git a/openspec/specs/architecture/interop/native-boundary.md b/openspec/specs/architecture/interop/native-boundary.md index 8a9b4b504e..9e3138e318 100644 --- a/openspec/specs/architecture/interop/native-boundary.md +++ b/openspec/specs/architecture/interop/native-boundary.md @@ -18,7 +18,8 @@ The Views rendering engine and related interfaces are native C++ COM servers. Ma - Managed components consume Views COM interfaces via ViewsInterfaces. - RootSite and SimpleRootSite host view objects and implement COM callbacks. -- ManagedVwWindow bridges WinForms controls to native IVwWindow. +- Windows RootSite editing relies on native Views interfaces and VwTextStore for input management. +- The retired Linux-era ManagedVwWindow shim no longer provides a managed HWND wrapper boundary. ### References diff --git a/openspec/specs/architecture/ui-framework/views-rendering.md b/openspec/specs/architecture/ui-framework/views-rendering.md index 74f5b6d97e..d1796aa124 100644 --- a/openspec/specs/architecture/ui-framework/views-rendering.md +++ b/openspec/specs/architecture/ui-framework/views-rendering.md @@ -19,7 +19,8 @@ FieldWorks uses a native C++ Views engine for text layout and rendering. Managed - Views (native) provides layout, selection, and rendering engines. - ViewsInterfaces exposes COM interfaces to managed code. - RootSite and SimpleRootSite host root boxes and manage view lifecycle. -- ManagedVwWindow bridges WinForms controls to IVwWindow for native rendering. +- Windows RootSite input uses native VwTextStore, and selection/page geometry uses the RootSite HWND with Win32 client-rectangle APIs. +- The retired Linux-era ManagedVwWindow shim is not part of the Windows rendering path. ### References From 32dbddd8e9fcf1a111e0296d512d8099a0aff3e3 Mon Sep 17 00:00:00 2001 From: John Lambert Date: Wed, 20 May 2026 20:12:15 -0400 Subject: [PATCH 3/3] Manually tested lexical edit view and interliner --- openspec/changes/retire-linux-era-view-shims/tasks.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openspec/changes/retire-linux-era-view-shims/tasks.md b/openspec/changes/retire-linux-era-view-shims/tasks.md index 780575dedb..d299ae845f 100644 --- a/openspec/changes/retire-linux-era-view-shims/tasks.md +++ b/openspec/changes/retire-linux-era-view-shims/tasks.md @@ -46,7 +46,7 @@ ## 8. Manual Smoke Validation -- [ ] 8.1 Edit text in a RootSite field in a rebuilt FieldWorks app; verify normal typing and keyboard switching still work. [Manual] -- [ ] 8.2 Test IME/composition in a RootSite field if an IME is available; verify pre-edit and commit behavior still work. [Manual] -- [ ] 8.3 Exercise mouse selection, keyboard selection, Shift+arrow selection, PageUp, and PageDown in a RootSite field; verify selection and visible-page movement remain correct. [Manual] -- [ ] 8.4 Launch from rebuilt output and watch for side-by-side activation or missing manifest errors. [Manual] +- [x] 8.1 Edit text in a RootSite field in a rebuilt FieldWorks app; verify normal typing and keyboard switching still work. [Manual] +- [x] 8.2 Test IME/composition in a RootSite field if an IME is available; verify pre-edit and commit behavior still work. [Manual] +- [x] 8.3 Exercise mouse selection, keyboard selection, Shift+arrow selection, PageUp, and PageDown in a RootSite field; verify selection and visible-page movement remain correct. [Manual] +- [x] 8.4 Launch from rebuilt output and watch for side-by-side activation or missing manifest errors. [Manual]