Forráskód Böngészése

Bug 1714: Mouse range selection does not start from the file focused by an incremental search

https://winscp.net/tracker/1714

Source commit: 677901e2e6b6d3e70192eca93e45f8b9302aa84b
Martin Prikryl 6 éve
szülő
commit
1546cf19c9

+ 1 - 1
source/forms/CustomScpExplorer.cpp

@@ -10316,7 +10316,7 @@ void __fastcall TCustomScpExplorerForm::IncrementalSearch(const UnicodeString &
     TCustomDirView * ADirView = DirView(osCurrent);
     {
       TAutoNestingCounter Guard(FIncrementalSearching);
-      ADirView->ItemFocused = Item;
+      ADirView->FocusItem(Item);
     }
     FIncrementalSearch = Text;
     Item->MakeVisible(false);

+ 3 - 2
source/packages/filemng/CustomDirView.pas

@@ -1856,11 +1856,12 @@ begin
         // Scroll to the GetPosition would scroll one line lower.
         Scroll(0, P.Y - Items[0].GetPosition.Y);
       end;
-      FocusItem(ItemToFocus);
+      // Strangely after this mouse selection works correctly, so we do not have to call FocusItem.
+      ItemFocused := ItemToFocus;
     end;
 
     // could not scroll when focus is not visible because
-    // of previous hack-implementation of FocusItem()
+    // of previous call to hack-implementation of FocusItem()
     // - no longer true, this can be re-enabled after some testing
     {$IF False}
     // previously focus item was not visible, scroll to the same position

+ 47 - 10
source/packages/my/NortonLikeListView.pas

@@ -69,7 +69,6 @@ type
     function NewColProperties: TCustomListViewColProperties; virtual; abstract;
     procedure FocusSomething; virtual;
     function EnableDragOnClick: Boolean; virtual;
-    procedure FocusItem(Item: TListItem);
     function GetItemFromHItem(const Item: TLVItem): TListItem;
     function GetValid: Boolean; virtual;
     function GetSelCount: Integer; override;
@@ -87,6 +86,7 @@ type
     function GetNextItem(StartItem: TListItem; Direction: TSearchDirection;
       States: TItemStates): TListItem;
     procedure MakeProgressVisible(Item: TListItem);
+    procedure FocusItem(Item: TListItem);
 
     property ColProperties: TCustomListViewColProperties read FColProperties write FColProperties stored False;
 
@@ -621,16 +621,53 @@ begin
 end;
 
 procedure TCustomNortonLikeListView.FocusItem(Item: TListItem);
+var
+  P: TPoint;
+  PLastSelectMethod: TSelectMethod;
+  PDontUnSelectItem: Boolean;
+  PDontSelectItem: Boolean;
+  WParam: UINT_PTR;
+  LParam: INT_PTR;
 begin
-  // This method was introduced in 3.7.6 for reasons long forgotten.
-  // It simulated a mouse click on the item. Possibly because the mere ItemFocused := Item
-  // did not work due to at-the-time-not-realized conflict with FocusSomething.
-  // Now that this is fixed, the method is no longer needed.
-  // Keeping it for a while with this comment, in case some regression is discovered.
-  // References:
-  // - 3.7.6: When reloading directory content, file panel tries to preserve its position.
-  // - Bugs 999 and 1161
-  ItemFocused := Item;
+  // This whole is replacement for mere ItemFocused := Item
+  // because that does not reset some internal focused pointer,
+  // causing subsequent Shift-Click selects range from the first item,
+  // not from focused item.
+  Item.MakeVisible(False);
+  Assert(Focused);
+  if Focused then
+  begin
+    P := Item.GetPosition;
+    PLastSelectMethod := FLastSelectMethod;
+    PDontSelectItem := FDontSelectItem;
+    PDontUnSelectItem := FDontUnSelectItem;
+    FLastSelectMethod := smNoneYet;
+    FDontSelectItem := True;
+    FDontUnSelectItem := True;
+    FFocusingItem := True;
+    try
+      // HACK
+      // WM_LBUTTONDOWN enters loop, waiting for WM_LBUTTONUP,
+      // so we have to post it in advance to break the loop immediately
+
+      // Without MK_CONTROL, if there are more items selected,
+      // they won't get unselected on subsequent focus change
+      // (with explorer-style selection).
+      // And it also makes the click the least obtrusive, affecting the focused
+      // file only.
+      WParam := MK_LBUTTON or MK_CONTROL;
+      LParam := MAKELPARAM(P.X, P.Y);
+      PostMessage(Handle, WM_LBUTTONUP, WParam, LParam);
+      SendMessage(Handle, WM_LBUTTONDOWN, WParam, LParam);
+    finally
+      FFocusingItem := False;
+      FLastSelectMethod := PLastSelectMethod;
+      FDontSelectItem := PDontSelectItem;
+      FDontUnSelectItem := PDontUnSelectItem;
+    end;
+  end;
+  if ItemFocused <> Item then
+    ItemFocused := Item;
 end;
 
 procedure TCustomNortonLikeListView.SelectAll(Mode: TSelectMode; Exclude: TListItem);