Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion EverythingToolbar/Controls/SearchBox.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,14 @@
TextBlock.FontWeight="Bold"
Content=".*"
Margin="1" />

<ToggleButton Style="{DynamicResource QuickSettingsToggleButton}"
Copy link
Copy Markdown
Owner

@srwi srwi May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think placing the toggle button in the optional quick actions bar is not a good idea. Its visibility depends on whether the quick action are shown or not.

In general I am not sure about having a toggle button for this. Isn't the typical flow in mobile apps to long press any item to switch to a multi-select mode where the user can tap multiple items to select or unselect and then press the back button to cancel the selection?

My suggestion would be to switch to the multi-selection mode by long pressing the first item on touch devices. While this mode is active, show a "Unselect all" button in the main toolbar to the left of the sort by button which unselects all items and switches off the multi-select mode. For regular desktop mode I don't think any UI changes are needed and regular multiselect can be used.

What do you think?

ToolTip="Multiple Selection"
IsChecked="{Binding Source={x:Static local:ToolbarSettings.User}, Path=IsSelectionModeEnabled}"
FontFamily="Segoe MDL2 Assets"
Content="&#xE762;"
Margin="1" />
</StackPanel>

</Grid>

</UserControl>
17 changes: 14 additions & 3 deletions EverythingToolbar/Controls/SearchResultsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:properties="clr-namespace:EverythingToolbar.Properties"
xmlns:local="clr-namespace:EverythingToolbar"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignWidth="300"
Expand Down Expand Up @@ -128,7 +129,6 @@

<Grid>
<ListView Name="SearchResultsListView"
SelectionMode="Single"
SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=SelectedSearchResult, Mode=TwoWay}"
BorderThickness="0"
HorizontalContentAlignment="Stretch"
Expand All @@ -146,7 +146,18 @@
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.PanningMode="VerticalOnly"
FocusVisualStyle="{x:Null}" />
FocusVisualStyle="{x:Null}">
<ListView.Style>
<Style TargetType="{x:Type ListView}">
<Setter Property="SelectionMode" Value="Extended" />
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static local:ToolbarSettings.User}, Path=IsSelectionModeEnabled}" Value="True">
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think semantically it would make more sense to make this a property of the SearchResultsView instead of a setting since this is not a user setting but rather a runtime value. You should still be able to bind to it.

<Setter Property="SelectionMode" Value="Multiple" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Style>
</ListView>
<Grid x:Name="SpinnerOverlay"
Visibility="Collapsed"
IsHitTestVisible="False"
Expand Down Expand Up @@ -176,4 +187,4 @@
</Viewbox>
</Grid>
</Grid>
</UserControl>
</UserControl>
104 changes: 63 additions & 41 deletions EverythingToolbar/Controls/SearchResultsView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public SearchResult? SelectedSearchResult
}

private SearchResult? SelectedItem => SelectedSearchResult;

private IEnumerable<SearchResult> GetSelectedItems()
{
return SearchResultsListView.SelectedItems.Cast<SearchResult>();
}

private const int PageSize = 256;
private Point _dragStart;
private bool _isScrollBarDragging;
Expand Down Expand Up @@ -219,7 +225,6 @@ private void ResetScrollBarDragging()

private void OnPreviewLeftMouseButtonDown(object sender, MouseButtonEventArgs e)
{
// Prevents deselecting an item when Ctrl is held down and clicking on an already selected item
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments were probably removed by accident? It happened at multiple places throughout the file.

if (Keyboard.Modifiers == ModifierKeys.Control)
{
if (e.OriginalSource is not DependencyObject source)
Expand All @@ -244,10 +249,10 @@ private void OnKeyPressed(object? sender, KeyEventArgs e)
}
else if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key == Key.Enter)
{
if (SelectedItem == null)
return;
var first = GetSelectedItems().FirstOrDefault();
if (first == null) return;

SearchResultProvider.OpenSearchInEverything(SearchState.Instance, SelectedItem.FullPathAndFileName);
SearchResultProvider.OpenSearchInEverything(SearchState.Instance, first.FullPathAndFileName);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure Everything can be launched with multiple files selected and launching with the first selected file seems a little arbitrary. I think the best approach would be to disable this feature while multiple files are selected, since it doesn't seem to be a supported feature of Everything. This would require disabling the context menu entry as well so it is consistent in the UI.

SearchResultsListView.SelectedIndex = -1;
}
else if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Enter)
Expand All @@ -274,11 +279,14 @@ private void OnKeyPressed(object? sender, KeyEventArgs e)
}
else if (Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift) && e.Key == Key.C)
{
SelectedItem?.CopyPathToClipboard();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two methods CopyPathToClipboard and CopyToClipboard are now not used anymore and their implementations can be removed.

var paths = string.Join(Environment.NewLine, GetSelectedItems().Select(i => i.FullPathAndFileName));
if (!string.IsNullOrEmpty(paths)) Clipboard.SetText(paths);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could call CopyPathToClipBoard here.

}
else if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.C)
{
SelectedItem?.CopyToClipboard();
var paths = new StringCollection();
foreach (var item in GetSelectedItems()) paths.Add(item.FullPathAndFileName);
if (paths.Count > 0) Clipboard.SetFileDropList(paths);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: Use CopyFile here.

}
else if (e.Key == Key.Up)
{
Expand Down Expand Up @@ -354,7 +362,6 @@ private void SelectNthSearchResult(int n)

private void JumpToEnd()
{
// Capture focus before calling Focus() on the ListView so we can restore it afterwards.
var originalFocus = Keyboard.FocusedElement;
SearchResultsListView.Focus();
ForwardKeyPressToControl(SearchResultsListView, Key.End, originalFocus, restoreFocus: KeepSearchBoxFocused);
Expand Down Expand Up @@ -430,7 +437,6 @@ private bool ForwardKeyPressToControl(
if (presentationSource == null)
return false;

// Capture focus state before raising the event
originalFocus ??= Keyboard.FocusedElement;
var caretIndex = originalFocus is TextBox textBox ? textBox.CaretIndex : -1;

Expand All @@ -440,7 +446,6 @@ private bool ForwardKeyPressToControl(
};
control.RaiseEvent(args);

// Restore focus to SearchBox if requested and it was previously focused
if (restoreFocus && originalFocus is TextBox restoredTextBox && caretIndex >= 0)
{
Dispatcher.BeginInvoke(
Expand All @@ -460,51 +465,69 @@ private bool ForwardKeyPressToControl(

private void OpenSelectedSearchResult()
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Rename the method to OpenSelectedSearchResults. Same for the other methods below.

{
if (SelectedItem == null)
return;

if (!CustomActions.HandleAction(SelectedItem))
SelectedItem?.Open();
var items = GetSelectedItems().ToList();
if (items.Count == 0) return;

foreach (var item in items)
{
if (!CustomActions.HandleAction(item))
item.Open();
}
SearchWindow.Instance.Hide();
}

private void OpenFilePath(object sender, RoutedEventArgs e)
{
SelectedItem?.OpenPath();
foreach (var item in GetSelectedItems())
item.OpenPath();
SearchWindow.Instance.Hide();
}

private void PreviewSelectedFile()
{
SelectedItem?.PreviewInQuickLook();
SelectedItem?.PreviewInSeer();
var first = GetSelectedItems().FirstOrDefault();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, not a huge fan of falling back to the first selected item. Maybe QuickLook or Seer even support showing multiple files at once? I can check this later.

first?.PreviewInQuickLook();
first?.PreviewInSeer();
}

private void CopyPathToClipBoard(object sender, RoutedEventArgs e)
{
SelectedItem?.CopyPathToClipboard();
var paths = string.Join(Environment.NewLine, GetSelectedItems().Select(i => i.FullPathAndFileName));
if (!string.IsNullOrEmpty(paths))
Clipboard.SetText(paths);
}

private void OpenWith(object sender, RoutedEventArgs e)
{
SelectedItem?.OpenWith();
foreach (var item in GetSelectedItems())
item.OpenWith();
SearchWindow.Instance.Hide();
}

private void ShowInEverything(object sender, RoutedEventArgs e)
{
SelectedItem?.ShowInEverything();
foreach (var item in GetSelectedItems())
item.ShowInEverything();
SearchWindow.Instance.Hide();
}

private void CopyFile(object sender, RoutedEventArgs e)
{
SelectedItem?.CopyToClipboard();
var paths = new StringCollection();
foreach (var item in GetSelectedItems()) paths.Add(item.FullPathAndFileName);

if (paths.Count > 0)
Clipboard.SetFileDropList(paths);
}

private void SingleClickSearchResult(object sender, MouseEventArgs e)
{
if (ToolbarSettings.User.IsSelectionModeEnabled)
return;

if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control) || Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the check for modifiers needed here?

return;

if (!ToolbarSettings.User.IsDoubleClickToOpen)
OpenWithMouseClick();
}
Expand All @@ -525,15 +548,7 @@ private void OpenWithMouseClick()
switch (Keyboard.Modifiers)
{
case ModifierKeys.Alt:
SelectedItem?.ShowProperties();
SearchWindow.Instance.Hide();
break;
case ModifierKeys.Control:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why were these removed?

SelectedItem?.OpenPath();
SearchWindow.Instance.Hide();
break;
case ModifierKeys.Shift:
SelectedItem?.ShowInEverything();
foreach (var item in GetSelectedItems()) item.ShowProperties();
SearchWindow.Instance.Hide();
break;
default:
Expand All @@ -545,19 +560,21 @@ private void OpenWithMouseClick()

private void RunAsAdmin(object sender, RoutedEventArgs e)
{
SelectedItem?.RunAsAdmin();
foreach (var item in GetSelectedItems())
item.RunAsAdmin();
SearchWindow.Instance.Hide();
}

private void ShowFileProperties(object sender, RoutedEventArgs e)
{
SelectedItem?.ShowProperties();
foreach (var item in GetSelectedItems())
item.ShowProperties();
SearchWindow.Instance.Hide();
}

private void ShowFileWindowsContextMenu(object sender, RoutedEventArgs e)
{
SelectedItem?.ShowWindowsContextMenu();
SearchResult.ShowWindowsContextMenu(GetSelectedItems());
}

private void OnOpenWithMenuLoaded(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -601,12 +618,16 @@ private void OnOpenWithMenuLoaded(object sender, RoutedEventArgs e)

private void OpenWithCustomAction(object sender, RoutedEventArgs e)
{
if (SelectedItem == null)
return;
var items = GetSelectedItems().ToList();
if (items.Count == 0) return;

var menuItem = sender as MenuItem;
var command = menuItem?.Tag?.ToString() ?? "";
CustomActions.HandleAction(SelectedItem, command);

foreach (var item in items)
{
CustomActions.HandleAction(item, command);
}
}

private void OnListViewItemMouseDown(object sender, MouseButtonEventArgs e)
Expand Down Expand Up @@ -645,7 +666,8 @@ private void OnListViewItemTouchUp(object sender, TouchEventArgs e)

private bool TryStartDragDrop(Point currentPosition)
{
if (SelectedItem == null)
var items = GetSelectedItems().ToList();
if (items.Count == 0)
return false;

var diff = _dragStart - currentPosition;
Expand All @@ -656,9 +678,9 @@ private bool TryStartDragDrop(Point currentPosition)
)
return false;

string[] files = [SelectedItem.FullPathAndFileName];
string[] files = items.Select(i => i.FullPathAndFileName).ToArray();
var data = new DataObject(DataFormats.FileDrop, files);
data.SetData(DataFormats.Text, files[0]);
data.SetData(DataFormats.Text, string.Join(Environment.NewLine, files));
DragDrop.DoDragDrop(SearchResultsListView, data, DragDropEffects.All);
return true;
}
Expand All @@ -670,7 +692,7 @@ private void OnContextMenuOpening(object sender, ContextMenuEventArgs e)

if (Keyboard.Modifiers == ModifierKeys.Shift)
{
SelectedItem.ShowWindowsContextMenu();
SearchResult.ShowWindowsContextMenu(GetSelectedItems());
e.Handled = true;
}
}
Expand Down Expand Up @@ -700,4 +722,4 @@ private void FocusSelectedItem()
Keyboard.Focus(selectedItem);
}
}
}
}
17 changes: 15 additions & 2 deletions EverythingToolbar/Data/SearchResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,22 @@ public void ShowProperties()

public void ShowWindowsContextMenu()
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is not used anymore and can be removed.

{
ShowWindowsContextMenu(new[] { this });
}

public static void ShowWindowsContextMenu(IEnumerable<SearchResult> items)
{
var itemsList = items.ToList();
if (itemsList.Count == 0) return;

var firstItemDir = itemsList[0].Path;
var validItems = itemsList.Where(i => string.Equals(i.Path, firstItemDir, StringComparison.OrdinalIgnoreCase)).ToList();

var menu = new ShellContextMenu();
var arrFi = new FileInfo[1];
arrFi[0] = new FileInfo(FullPathAndFileName);
var arrFi = validItems.Select<SearchResult, FileSystemInfo>(i =>
i.IsFile ? new FileInfo(i.FullPathAndFileName) : new DirectoryInfo(i.FullPathAndFileName)
).ToArray();

menu.ShowContextMenu(arrFi, Control.MousePosition);
}

Expand Down
Loading