Browse Source

Bug fix: Panel focus was lost in some situations

1) When opening local-local more workspace (since 6.0)
2) When switching tabs (since 6.2 – 75044ab5)

Source commit: 5d759fcc55518aa2377754cf3819987d37291f15
Martin Prikryl 2 years ago
parent
commit
75032929ea

+ 19 - 0
source/forms/CustomScpExplorer.cpp

@@ -10257,6 +10257,15 @@ void __fastcall TCustomScpExplorerForm::UnlockWindow()
   {
     DebugAssert(FLockSuspendLevel == 0);
     Enabled = true;
+    // VCL_COPY (TCustomForm.SetWindowFocus)
+    if (Active && (ActiveControl != NULL))
+    {
+      ::SetFocus(ActiveControl->Handle);
+      if (GetFocus() == ActiveControl->Handle)
+      {
+        ActiveControl->Perform(CM_UIACTIVATE, 0, 0);
+      }
+    }
   }
 }
 //---------------------------------------------------------------------------
@@ -12062,3 +12071,13 @@ void TCustomScpExplorerForm::QueueResetLayoutColumns()
 {
   LoadListViewStr(QueueView3, QueueViewLayoutDefault);
 }
+//---------------------------------------------------------------------------
+void * TCustomScpExplorerForm::SaveFocus()
+{
+  return NULL;
+}
+//---------------------------------------------------------------------------
+void TCustomScpExplorerForm::RestoreFocus(void * Focus)
+{
+  DebugAssert(Focus == NULL);
+}

+ 2 - 0
source/forms/CustomScpExplorer.h

@@ -915,6 +915,8 @@ public:
   void AutoSizeColumns(TOperationSide Side);
   virtual void ResetLayoutColumns(TOperationSide Side) = 0;
   void QueueResetLayoutColumns();
+  virtual void * SaveFocus();
+  virtual void RestoreFocus(void * Focus);
 
   __property bool ComponentVisible[Byte Component] = { read = GetComponentVisible, write = SetComponentVisible };
   __property bool EnableFocusedOperation[TOperationSide Side] = { read = GetEnableFocusedOperation, index = 0 };

+ 57 - 30
source/forms/ScpCommander.cpp

@@ -1023,8 +1023,7 @@ void __fastcall TScpCommanderForm::SetToolbar2ItemAction(TTBXItem * Item, TBasic
 void __fastcall TScpCommanderForm::UpdateControls()
 {
   // Before TCustomScpExplorerForm disables them (when disconnecting)
-  bool DirViewWasFocused = DirView(osOther)->Focused();
-  bool DriveViewWasFocused = DriveView(osOther)->Focused();
+  void * Focus = SaveFocus();
 
   // When implicitly connecting a not-yet-connected session by switching to its tab opened with workspace,
   // Terminal property is still NULL, but ActiveTerminal is already set.
@@ -1124,34 +1123,7 @@ void __fastcall TScpCommanderForm::UpdateControls()
   bool LocalOnLeft = (Panel(true) == LocalPanel);
   LocalMenuButton->Caption = LoadStr(HasTerminal ? LOCAL_MENU_CAPTION : (LocalOnLeft ? LEFT_MENU_CAPTION : RIGHT_MENU_CAPTION));
   RemoteMenuButton->Caption = LoadStr(HasTerminal ? REMOTE_MENU_CAPTION : (LocalOnLeft ? RIGHT_MENU_CAPTION : LEFT_MENU_CAPTION));
-  if (DirViewWasFocused)
-  {
-    if (DirView(osOther)->Enabled)
-    {
-      DirView(osOther)->SetFocus();
-    }
-    else
-    {
-      LocalDirView->SetFocus();
-    }
-  }
-  if (DriveViewWasFocused)
-  {
-    if (DriveView(osOther)->Enabled)
-    {
-      DriveView(osOther)->SetFocus();
-    }
-    else if (LocalDriveView->Visible)
-    {
-      LocalDriveView->SetFocus();
-    }
-    else
-    {
-      // Switching to a disconnected session with local drive view hidden - fallback to the local dir view (should always be visible)
-      DebugAssert(LocalDirView->Visible);
-      LocalDirView->SetFocus();
-    }
-  }
+  RestoreFocus(Focus);
 
   if (RemotePathLabel->FocusControl != DirView(osOther))
   {
@@ -2976,3 +2948,58 @@ void TScpCommanderForm::ResetLayoutColumns(TOperationSide Side)
 
   DirView(Side)->ColProperties->ParamsStr = DirViewParamsDefault;
 }
+//---------------------------------------------------------------------------
+void * TScpCommanderForm::SaveFocus()
+{
+  // When window is disabled, the ActiveControl might actually not be focusable
+  return ((ActiveControl != NULL) && ActiveControl->Focused()) ? ActiveControl : NULL;
+}
+//---------------------------------------------------------------------------
+void TScpCommanderForm::RestoreFocus(void * Focus)
+{
+  TWinControl * ControlFocus = static_cast<TWinControl *>(Focus);
+  if ((ControlFocus == LocalDirView) || (ControlFocus == LocalDriveView))
+  {
+    DebugAssert(ActiveControl == ControlFocus);
+    DebugAssert(ControlFocus->Enabled);
+    // noop
+  }
+  else if ((ControlFocus == RemoteDirView) || (ControlFocus == OtherLocalDirView))
+  {
+    if (DirView(osOther)->Enabled)
+    {
+      ControlFocus = DirView(osOther);
+    }
+    else
+    {
+      ControlFocus = LocalDirView;
+    }
+  }
+  else if ((ControlFocus == RemoteDriveView) || (ControlFocus == OtherLocalDriveView))
+  {
+    if (DriveView(osOther)->Enabled)
+    {
+      ControlFocus = DriveView(osOther);
+    }
+    else if (LocalDriveView->Visible)
+    {
+      ControlFocus = LocalDriveView;
+    }
+    else
+    {
+      // Switching to a disconnected session with local drive view hidden -
+      // fallback to the local dir view (should always be visible)
+      DebugAssert(LocalDirView->Visible);
+      ControlFocus = LocalDirView;
+    }
+  }
+  else
+  {
+    ControlFocus = NULL;
+  }
+
+  if (ControlFocus != NULL)
+  {
+    ControlFocus->SetFocus();
+  }
+}

+ 2 - 0
source/forms/ScpCommander.h

@@ -692,6 +692,8 @@ public:
   virtual UnicodeString __fastcall DefaultDownloadTargetDirectory();
   virtual bool SupportedSession(TSessionData * SessionData);
   virtual void ResetLayoutColumns(TOperationSide Side);
+  virtual void * SaveFocus();
+  virtual void RestoreFocus(void * Focus);
 
   __property double LeftPanelWidth = { read = GetLeftPanelWidth, write = SetLeftPanelWidth };
 };

+ 6 - 0
source/windows/TerminalManager.cpp

@@ -759,6 +759,7 @@ void __fastcall TTerminalManager::DoSetActiveSession(TManagedTerminal * value, b
     {
       NonVisualDataModule->StartBusy();
     }
+    void * Focus = NULL;
     try
     {
       // here used to be call to TCustomScpExporer::UpdateSessionData (now UpdateSession)
@@ -768,6 +769,7 @@ void __fastcall TTerminalManager::DoSetActiveSession(TManagedTerminal * value, b
       FActiveSession = value;
       if (ScpExplorer)
       {
+        Focus = ScpExplorer->SaveFocus();
         if ((ActiveSession != NULL) &&
             ((ActiveSession->Status == ssOpened) || ActiveSession->Disconnected || ActiveSession->LocalBrowser))
         {
@@ -852,6 +854,10 @@ void __fastcall TTerminalManager::DoSetActiveSession(TManagedTerminal * value, b
       {
         NonVisualDataModule->EndBusy();
       }
+      if ((Focus != NULL) && DebugAlwaysTrue(ScpExplorer != NULL))
+      {
+        ScpExplorer->RestoreFocus(Focus);
+      }
     }
   }
 }