╭─── Claude Code v2.1.92 ──────────────────────────────────────────────────────╮
│                             │ Tips for getting started                       │
│        Welcome back!        │ Run /init to create a CLAUDE.md file with ins… │
│                             │ ────────────────────────────────────────────── │
│           ▐▛███▜▌           │ Recent activity                                │
│          ▝▜█████▛▘          │ No recent activity                             │
│            ▘▘ ▝▝            │                                                │
│                             │                                                │
│   Sonnet 4.6 · Claude API   │                                                │
│        X:\ms\sttwin         │                                                │
╰──────────────────────────────────────────────────────────────────────────────╯

> In @Childwin.pas there's an editor txtTextEditor which behaves differently    
depending if WindowsMDI conditional is defined or not. When FSpeechEditMode is  
set to semAuto and text is typed into txtTextEditor, at some moment par of a    
content from txtTextEditor is sent to transmission. If WindowsMDI is not        
defined, at that moment txtTextEditor keeps focus and user can continue typing  
(which is correct behaviour). If WindowsMDI is defined, at that moment          
txtTextEditor looses focus and its content is clear and I can't figure out why. 
 Can you help?                                                                  

  Read 1 file (ctrl+o to expand)

● Large file. Let me search for the relevant parts.

  Searched for 3 patterns (ctrl+o to expand)

● Let me look at the key sections more closely.

  Read 1 file (ctrl+o to expand)

● Now let me find HandleExternalDictation - this is the key method called in
  semAuto mode when text changes.

  Searched for 2 patterns, read 1 file (ctrl+o to expand)

● Now let me look at the crucial difference - the WMMDIActivate handler and how
  the form hierarchy differs. Let me also check the InheritedSpeechEditorSetText
   method and the class hierarchy.

  Searched for 2 patterns, read 1 file (ctrl+o to expand)

● Now let me look at HandleSpeechEditorMessages for WM_SETTEXT handling and
  focus-related messages.

  Read 1 file (ctrl+o to expand)

● Now let me look at the WMMDIActivate handler - this is suspicious since it
  only exists when WindowsMDI is defined.

  Searched for 1 pattern, read 1 file (ctrl+o to expand)

● Now let me look at how SendTextToScreen is called in semAuto mode, and what
  happens with focus. Let me look at AppendSpeechText continuation -
  particularly the part that actually sends text.

  Searched for 3 patterns, read 1 file (ctrl+o to expand)

● Explore(Find TFABForm class definition)
  ⎿  Done (80 tool uses · 48.3k tokens · 3m 51s)
  (ctrl+o to expand)

  Searched for 4 patterns, read 1 file (ctrl+o to expand)

● Now let me look at HandleActiveFormChange - this could be where focus is
  affected.

  Searched for 20 patterns, read 3 files (ctrl+o to expand)
> Small correction: txtTextEditor looses focus but its content is NOT cleared.  
I did try commenting out PostMessage in line 28672 but that didn't help.        

● Thanks for the correction - focus loss without content clearing, and
  WMMDIActivate PostMessage isn't the cause. Let me dig deeper into what steals
  focus.

  Searched for 6 patterns, read 2 files (ctrl+o to expand)

● Let me check if the speech target's IsSpeechMode is set.

  Searched for 18 patterns, read 4 files (ctrl+o to expand)

● Now I have a clear picture of the issue. Let me summarize my findings and
  propose a fix.

  Root cause: The GpMDI framework (non-WindowsMDI case) has built-in focus
  tracking and restoration:
  - TfrmGpMDIParent.SetFocusedControl tracks LastFocusControl for each child
  - TfrmGpMDIChild.CMActivate calls Refocus which restores LastFocusControl

  In the WindowsMDI case, there's no such mechanism. When HandleTextDisplay runs
   asynchronously (via OTL message) and performs operations on the speech target
   form (in InsertNewSubtitle → NewSubtitle, UpdateSubtitleList), focus can be
  stolen from txtTextEditor. Without the GpMDI Refocus mechanism, it never gets
  restored.

  The fix is to save and restore focus around HandleTextDisplay. Let me look at
  the exact code to modify.

  Read 1 file (ctrl+o to expand)

● Here's my analysis and proposed fix:

  Problem: In the WindowsMDI case, HandleTextDisplay (called asynchronously via
  OTL) performs operations on both the source and target forms — AddSubtitleText
   → InsertNewSubtitle → NewSubtitle, UpdateSubtitleList, etc. These operations
  can steal focus from txtTextEditor.

  In the non-WindowsMDI (GpMDI) case, the framework's
  TfrmGpMDIParent.SetFocusedControl tracks LastFocusControl and
  TfrmGpMDIChild.CMActivate → Refocus restores it automatically. The WindowsMDI
  case has no such mechanism.

  Fix: Save and restore the focused window handle around the
  FHandlingTextDisplay block:

● Update(Childwin.pas)
  ⎿  Added 7 lines
      24015    end;
      24016  
      24017    FHandlingTextDisplay := True;
      24018 +  {$IFDEF WindowsMDI}                                       
      24019 +  var savedFocus := Winapi.Windows.GetFocus();              
      24020 +  {$ENDIF}                                                  
      24021    try
      24022      if RSubtOns <> 0 then
      24023        StopTextTiming()
     ...
      24060      SyncSpeechDisplayIndex();
      24061    finally
      24062      FHandlingTextDisplay := False;
      24063 +    {$IFDEF WindowsMDI}                                     
      24064 +    if (savedFocus <> 0) and IsWindow(savedFocus) and (Winap
            +i.Windows.GetFocus() <> savedFocus) then                    
      24065 +      Winapi.Windows.SetFocus(savedFocus);                  
      24066 +    {$ENDIF}                                                
      24067    end;
      24068  end;
      24069  

● Now let me verify the edit looks correct:

  Read 1 file (ctrl+o to expand)

● The fix looks correct. Here's a summary of my analysis:

  Why it works in non-WindowsMDI (GpMDI): The GpMDI framework has built-in focus
   tracking:
  - TfrmGpMDIParent.SetFocusedControl (GpMDI.ParentForm.pas:465) records
  LastFocusControl on every focus change
  - TfrmGpMDIChild.CMActivate (GpMDI.ChildForm.pas:353) calls Refocus which
  restores LastFocusControl.SetFocus
  - So even if focus temporarily moves during HandleTextDisplay, it gets
  automatically restored

  Why it breaks in WindowsMDI: TMDIChild inherits from TFABForm → TForm with
  standard Windows MDI child behavior. There's no LastFocusControl tracking or
  Refocus mechanism. When HandleTextDisplay runs asynchronously (via OTL
  HandleTaskMessage) and performs operations on both source and target forms —
  through AddSubtitleText → InsertNewSubtitle → NewSubtitle, UpdateSubtitleList,
   etc. — something in that chain causes focus to move away from txtTextEditor,
  and without the GpMDI restoration mechanism, it stays lost.

  The fix: Saves GetFocus() before the HandleTextDisplay processing block and
  restores it in the finally if it changed. This mimics what GpMDI does
  automatically via its Refocus mechanism. The IsWindow check guards against the
   edge case where the focused window was destroyed during processing.

✻ Worked for 18m 11s