mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
CmdPal: Prevent PgUp/PgDown from selecting non-internactive items (#46439)
## Summary of the Pull Request This PR prevents paging (<kbd>PgUp</kbd>/<kbd>PgDown</kbd>) in the item list from selecting non-interactive items (such as separators or section headers). It adds `FindSelectableIndex` and `FindSelectableIndexForPageNavigation` helper methods, which locate the next interactive item in the given direction. These methods are used to guard paging navigation and to consolidate related logic elsewhere. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #46283 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
This commit is contained in:
@@ -156,21 +156,7 @@ public sealed partial class ListPage : Page,
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private int GetFirstSelectableIndex()
|
private int GetFirstSelectableIndex()
|
||||||
{
|
{
|
||||||
var items = ItemView.Items;
|
return FindSelectableIndex(0, 1);
|
||||||
if (items is null || items.Count == 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < items.Count; i++)
|
|
||||||
{
|
|
||||||
if (!IsSeparator(items[i]))
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "VS is too aggressive at pruning methods bound in XAML")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "VS is too aggressive at pruning methods bound in XAML")]
|
||||||
@@ -604,9 +590,44 @@ public sealed partial class ListPage : Page,
|
|||||||
? Math.Min(itemCount - 1, currentIndex + Math.Max(1, itemsPerPage))
|
? Math.Min(itemCount - 1, currentIndex + Math.Max(1, itemsPerPage))
|
||||||
: Math.Max(0, currentIndex - Math.Max(1, itemsPerPage));
|
: Math.Max(0, currentIndex - Math.Max(1, itemsPerPage));
|
||||||
|
|
||||||
|
targetIndex = FindSelectableIndexForPageNavigation(targetIndex, isPageDown);
|
||||||
|
if (targetIndex == -1)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (currentIndex, targetIndex);
|
return (currentIndex, targetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int FindSelectableIndex(int startIndex, int step)
|
||||||
|
{
|
||||||
|
var items = ItemView.Items;
|
||||||
|
var count = items.Count;
|
||||||
|
if (count == 0 || step == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
startIndex = Math.Clamp(startIndex, 0, count - 1);
|
||||||
|
|
||||||
|
for (var i = startIndex; i >= 0 && i < count; i += step)
|
||||||
|
{
|
||||||
|
if (!IsSeparator(items[i]))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int FindSelectableIndexForPageNavigation(int targetIndex, bool isPageDown)
|
||||||
|
{
|
||||||
|
var step = isPageDown ? 1 : -1;
|
||||||
|
var index = FindSelectableIndex(targetIndex, step);
|
||||||
|
return index != -1 ? index : FindSelectableIndex(targetIndex - step, -step);
|
||||||
|
}
|
||||||
|
|
||||||
private static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
private static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (d is ListPage @this)
|
if (d is ListPage @this)
|
||||||
@@ -1045,40 +1066,25 @@ public sealed partial class ListPage : Page,
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void NavigateUp()
|
private void NavigateUp()
|
||||||
{
|
{
|
||||||
var newIndex = ItemView.SelectedIndex;
|
if (ItemView.Items.Count == 0)
|
||||||
|
|
||||||
if (ItemView.SelectedIndex > 0)
|
|
||||||
{
|
{
|
||||||
newIndex--;
|
return;
|
||||||
|
|
||||||
while (
|
|
||||||
newIndex >= 0 &&
|
|
||||||
IsSeparator(ItemView.Items[newIndex]) &&
|
|
||||||
newIndex != ItemView.SelectedIndex)
|
|
||||||
{
|
|
||||||
newIndex--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newIndex < 0)
|
var newIndex = ItemView.SelectedIndex > 0
|
||||||
{
|
? FindSelectableIndex(ItemView.SelectedIndex - 1, -1)
|
||||||
newIndex = ItemView.Items.Count - 1;
|
: -1;
|
||||||
|
|
||||||
while (
|
if (newIndex == -1)
|
||||||
newIndex >= 0 &&
|
|
||||||
IsSeparator(ItemView.Items[newIndex]) &&
|
|
||||||
newIndex != ItemView.SelectedIndex)
|
|
||||||
{
|
{
|
||||||
newIndex--;
|
newIndex = FindSelectableIndex(ItemView.Items.Count - 1, -1);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newIndex = ItemView.Items.Count - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newIndex != -1)
|
||||||
|
{
|
||||||
ItemView.SelectedIndex = newIndex;
|
ItemView.SelectedIndex = newIndex;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Items_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
|
private void Items_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -1168,51 +1174,25 @@ public sealed partial class ListPage : Page,
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void NavigateDown()
|
private void NavigateDown()
|
||||||
{
|
{
|
||||||
var newIndex = ItemView.SelectedIndex;
|
if (ItemView.Items.Count == 0)
|
||||||
|
|
||||||
if (ItemView.SelectedIndex == ItemView.Items.Count - 1)
|
|
||||||
{
|
|
||||||
newIndex = 0;
|
|
||||||
while (
|
|
||||||
newIndex < ItemView.Items.Count &&
|
|
||||||
IsSeparator(ItemView.Items[newIndex]))
|
|
||||||
{
|
|
||||||
newIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newIndex >= ItemView.Items.Count)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newIndex++;
|
|
||||||
|
|
||||||
while (
|
var newIndex = ItemView.SelectedIndex < ItemView.Items.Count - 1
|
||||||
newIndex < ItemView.Items.Count &&
|
? FindSelectableIndex(ItemView.SelectedIndex + 1, 1)
|
||||||
IsSeparator(ItemView.Items[newIndex]) &&
|
: -1;
|
||||||
newIndex != ItemView.SelectedIndex)
|
|
||||||
|
if (newIndex == -1)
|
||||||
{
|
{
|
||||||
newIndex++;
|
newIndex = FindSelectableIndex(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newIndex >= ItemView.Items.Count)
|
if (newIndex != -1)
|
||||||
{
|
{
|
||||||
newIndex = 0;
|
|
||||||
|
|
||||||
while (
|
|
||||||
newIndex < ItemView.Items.Count &&
|
|
||||||
IsSeparator(ItemView.Items[newIndex]) &&
|
|
||||||
newIndex != ItemView.SelectedIndex)
|
|
||||||
{
|
|
||||||
newIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemView.SelectedIndex = newIndex;
|
ItemView.SelectedIndex = newIndex;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsSeparator(object? item) => item is ListItemViewModel li && !li.IsInteractive;
|
private bool IsSeparator(object? item) => item is ListItemViewModel li && !li.IsInteractive;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user