Repository navigation
fix(pickers): keyboard-mode window styles hang the native file dialogs (white-screen freeze) - #73
Merged
Merged
Conversation
|
Your organization has run out of review credits. Add credits to resume code reviews. |
willwade
force-pushed
the
fix/keyboard-mode-picker-hang
branch
3 times, most recently
from
October 28, 2026 11:41
8bf1e6b to
599ca56
Compare
"The one major issue is when you try to export/import your saved training text file, the whole program crashes, and goes into the white screen and then I have to go into task manager and end the task." (v0.1.33 tester report) In keyboard (direct-entry) mode the main window carries WS_EX_NOACTIVATE + WS_EX_LAYERED + TOPMOST so it floats over the target app without stealing keystrokes. A Win32 common dialog owned by that window never surfaces - it cannot take activation from a NOACTIVATE owner and is born behind the topmost one - so IFileDialog::Show pumps invisibly on the UI thread forever: the app paints white and only Task Manager can end it. Reproduced locally by invoking the training export from keyboard mode (no #32770 ever appears, UI thread blocked in the modal pump); the editor-mode repros that "worked" never had these styles. All four picker call sites (training import/export, Open, Save) now temporarily normalize the owner via WindowDialogStyles: clear WS_EX_NOACTIVATE, drop out of the topmost band, bring the window to the foreground, and restore both afterwards. Pure Win32 - the Avalonia Topmost/Opacity properties are untouched so the mode logic keeps owning them. Verified twice end-to-end with the exact failing flow (app restored into keyboard mode, Settings opened from the mini-bar, Export clicked): the save dialog now appears within a second and the app survives the dialog being cancelled. Repro harnesses are watchdog-protected (the app is force-killed after every run). Note: v0.1.33 predates #71 (async-void picker guards, crash-evidence retention) - both that and this fix must ride the next release together for the tester. Signed-off-by: will wade <willwade@gmail.com>
willwade
force-pushed
the
fix/keyboard-mode-picker-hang
branch
5 times, most recently
from
October 30, 2026 19:02
a80ef3a to
03614cf
Compare
…emetry
Implements the 2026-10-28 RFC 0001 amendment (governance
rfc0001-ui-telemetry-amendment; Android and GTK already implemented)
for Dasher-Windows, answering the UX team question "which settings
are the priority and where should main-UI focus go".
- ui_action {surface, action, state?}: main-UI control activations.
Surfaces: main_toolbar, status_bar (incl. the bottom message-pane
header), ime_toolbar (the keyboard-mode mini-bar). Fixed action
vocabulary declared in analytics-events.json: new, open, save,
settings, copy, copy_selection, cut, paste, select_all, speak,
stop_speak, speed_up, speed_down, layout (state = pane position),
direct_mode, game_mode, control_mode, reanchor. OnToggleMode maps
entering (top-bar BtnKeyboard -> main_toolbar) vs leaving (mini-bar
exit -> ime_toolbar); the BtnMode flyout items emit layout with the
chosen position.
- setting_changed {setting_id, value_type, value?, surface}: every
user commit at the widget site. Settings: engine parameter rows
(toggle/slider/stepper/enum/string), the access row (access_method,
selection_method, eye_tracker_type, udp_port, Input Filter),
palette picker, output font family + size, keyboard opacity,
advanced toggle, typing-rate, analytics opt-in, and the Speech
section (speech_engine, speech_voice, speech_rate, speech_pitch,
speech_volume, Speak All On Stop, Speak Words). Main UI: Max
Bitrate (speed steppers), Alphabet (language picker), speech_volume
(status bar), Automatic Speed Control / Adaptive Learning (status
toggles - view-side, attached after the startup value load and
suppressed around programmatic writes).
Amendment rules enforced:
- Programmatic changes never emit: the language picker compares
against the engine alphabet before emitting (also fixes the
pre-existing startup alphabet_selected false-fire); voice-combo and
selection-combo auto-population are guarded; status-toggle
instrumentation attaches view-side post-startup; sliders emit on
drag release / keyboard adjust (commit), never per ValueChanged
tick; steppers and the speed buttons skip clamped no-op clicks.
- String settings report the fact of the change only (free text and
file paths are never collected); the string field skips unchanged
focus-lost events.
- Layout actions carry the pane position in state; stop_speak is its
own action (schema enum extended accordingly).
analytics-events.json updated (schema truth): both events, action +
state vocabulary, surface notes, and the two new
explicitly_not_collected entries from the amendment.
Signed-off-by: will wade <willwade@gmail.com>
willwade
force-pushed
the
fix/keyboard-mode-picker-hang
branch
from
October 30, 2026 19:03
03614cf to
719cdc5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
v0.1.33 tester report:
Root cause
In keyboard (direct-entry) mode the main window carries
WS_EX_NOACTIVATE + WS_EX_LAYERED + TOPMOST(it floats over the target application without stealing keystrokes). A Win32 common file dialog owned by that window never surfaces: it can't take activation from aNOACTIVATEowner and is born behind the topmost one ÔÇö soIFileDialog::Show()pumps invisibly on the UI thread forever. The app stops painting (white screen) and only Task Manager can end it. Exactly the reporter's symptom.Reproduced locally by invoking the training export from keyboard mode ÔÇö no
#32770dialog ever appears and the UI thread sits in the invisible modal pump. (Earlier "works on my machine" repros were all in editor mode, which never has these styles.)Fix
All four picker call sites (training import/export, Open, Save) temporarily normalize the owner via the new
WindowDialogStyles: clearWS_EX_NOACTIVATE, drop out of the topmost band, bring the window to the foreground, and restore both afterwards. Pure Win32 ÔÇö the AvaloniaTopmost/Opacityproperties are untouched so the keyboard-mode logic keeps owning them.Verification
Note: v0.1.33 predates #71 (async-void picker guards) ÔÇö both fixes must ride the next release together for the tester, along with #72 (DasherCore v0.2.27 pin, which carries the Enter/paragraph fix).
Also included (second commit): the RFC 0001 2026-10-28 amendment —
ui_action+setting_changedtelemetry, bringing Dasher-Windows in line with Dasher-Android and Dasher-GTK. Fixed action vocabulary declared inanalytics-events.json(schema truth); string setting values are never collected; programmatic changes never emit; opt-in gated like every event. See the commit message for the full instrumentation inventory.