Skip to content

fix(gui): el foco de teclado cae en el editor de prompt al arrancar (antes: botón de cabecera) - #10

Merged
klssxx merged 1 commit into
mainfrom
fix/b10-initial-focus
Sep 25, 2026
Merged

klssxx merged 1 commit into
mainfrom
fix/b10-initial-focus

Conversation

@klssxx

@klssxx klssxx commented Sep 25, 2026

Copy link
Copy Markdown
Owner

«No me deja escribir» (reporte del usuario al abrir la app)

Causa raíz (establecida por sondeo de foco bajo bucle real de eventos):

  1. Qt asigna el foco inicial en la activación de la ventana (async tras show()), no en el constructor: el ganador es el primer hijo enfocable — el botón «Activar modo extremo» de la cabecera. Las teclas no van a ningún sitio visible.
  2. Esa asignación llega encolada después del evento de activación, así que cualquier claim en __init__, showEvent o singleShot(0) desde changeEvent pierde la carrera (las tres variantes fallaron empíricamente).
  3. Agravante: _restore_settings puede abrir directamente modo extremo (persiste el último modo usado) y el fix inicial solo cubría el editor simple.

Fix: vigía de 20 ms armado en la primera WindowActivationChange — espera a que la asignación de Qt aterrice (foco = botón de cabecera; esa señal es la condición) y entonces reclama el foco para el editor del modo activo (simple_prompt_edit/prompt_edit). No pelea con el usuario: si el foco cae en otro objetivo real, para sin reclamar; tope de 100 ticks.

Verificado por ejecución: sondeo botón→editor; TestInitialFocus espera la condición con QTest.qWait y pasa con el modo extremo restaurado por settings. Suite: 312 passed + 10 subtests, ruff limpio.

User-reported: opening the app and typing did nothing — 'no me deja
escribir'. Root cause chain, established empirically with focus polling
under a real event loop:

1. Qt assigns initial focus when the window is ACTIVATED, not at
   show(); the winner is the first focusable child — the header
   'Activar modo extremo' toggle button — so keystrokes go nowhere
   visible.
2. The assignment is queued AFTER the activation event, so claims made
   in __init__ or showEvent (and even singleShot(0) from changeEvent)
   are overwritten by it.
3. The app may open directly in EXTREME mode: settings restore brings
   back the last-used mode (_collect_settings persists 'mode'), and the
   original fix only covered the simple-mode editor.

Fix: a one-shot 20 ms watcher armed on the first WindowActivationChange
waits until Qt's initial assignment has actually landed (focus reaches
the toggle button — that landing is the signal), then claims focus for
the CURRENT mode's editor (simple_prompt_edit or prompt_edit). It never
fights the user: if focus lands on any other real target it stops
without claiming, and a 100-tick cap bounds it.

Verified by execution: focus polling shows QPushButton before, editor
after; TestInitialFocus waits on the condition (QTest.qWait loop) and
passes for the settings-restored extreme mode. Suite: 312 passed +
10 subtests, ruff clean.
@klssxx
klssxx merged commit baadaae into main Sep 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant