Compare commits

...

3 Commits

Author SHA1 Message Date
Mike Griese
143949d383 PRE-MERGE CmdPal: Apply the LLKH to all command hotkeys #39524
Squashed commit of the following:

commit f595a68d49
Author: Mike Griese <migrie@microsoft.com>
Date:   Fri May 16 16:46:17 2025 -0500

    Eh, don't touch this

commit bf5c5c6f5e
Author: Mike Griese <migrie@microsoft.com>
Date:   Fri May 16 16:43:16 2025 -0500

    CmdPal: Apply the LLKH to all command hotkeys

    <!-- Let's say you wanted to add a hotkey to the Run command. And let's say
    you wanted it to be Win+R. This lets you do that -->

    We should apply the LLKH setting to all command hotkeys, not just the
    global one.
2025-05-16 16:46:51 -05:00
Mike Griese
2e2cbfcf64 PRE-MERGE CmdPal: Auto-focus first content #39414
Squashed commit of the following:

commit f64bfd1c87
Author: Mike Griese <migrie@microsoft.com>
Date:   Wed May 14 06:08:50 2025 -0500

    don't do the focus thing if there's a bunch of controls

commit 01250bad73
Author: Mike Griese <migrie@microsoft.com>
Date:   Tue May 13 14:25:21 2025 -0500

    instead of checking individual controls, use AllowFocusOnInteraction

commit d7432d661e
Author: Mike Griese <migrie@microsoft.com>
Date:   Tue May 13 14:07:59 2025 -0500

    Try to focus forms on load

    when a content form first loads, try to focus it.

    This does work for a single control on a page, but doesn't work great if
    there's more than one
2025-05-16 16:30:51 -05:00
Mike Griese
23051876d0 PRE-MERGE CmdPal: Don't trim the template proj in debug builds #39463
Squashed commit of the following:

commit 3fb7ebe172
Author: Mike Griese <migrie@microsoft.com>
Date:   Thu May 15 16:38:17 2025 -0500

    update template

commit 167266a5f9
Author: Mike Griese <migrie@microsoft.com>
Date:   Thu May 15 16:37:46 2025 -0500

    More correct

commit fa672c6c35
Author: Mike Griese <migrie@microsoft.com>
Date:   Thu May 15 10:23:31 2025 -0500

    add template zip

commit 97205ea840
Author: Mike Griese <migrie@microsoft.com>
Date:   Thu May 15 10:22:51 2025 -0500

    CmdPal: Don't trim in debug for template
2025-05-16 16:30:03 -05:00
6 changed files with 105 additions and 14 deletions

View File

@@ -56,13 +56,35 @@
</PropertyGroup>
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<IsAotCompatible>true</IsAotCompatible>
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
<!-- Suppress DynamicallyAccessedMemberTypes.PublicParameterlessConstructor in fallback code path of Windows SDK projection -->
<WarningsNotAsErrors>IL2081</WarningsNotAsErrors>
<WarningsNotAsErrors>IL2081;$(WarningsNotAsErrors)</WarningsNotAsErrors>
<!-- When publishing trimmed, make sure to treat trimming warnings as build errors -->
<ILLinkTreatWarningsAsErrors>true</ILLinkTreatWarningsAsErrors>
<PublishTrimmed>true</PublishTrimmed>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<!-- In Debug builds, trimming is disabled by default, but all the trim &
AOT warnings are enabled. This gives debug builds a tighter inner loop,
while at least warning about future trim violations -->
<PublishTrimmed>false</PublishTrimmed>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
<EnableAotAnalyzer>true</EnableAotAnalyzer>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'!='Debug'">
<!-- In Release builds, trimming is enabled by default.
feel free to disable this if needed -->
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -79,6 +79,9 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
throw;
}
var oneContent = newContent.Count == 1;
newContent.ForEach(c => c.OnlyControlOnPage = oneContent);
// Now, back to a UI thread to update the observable collection
DoOnUiThread(
() =>

View File

@@ -7,4 +7,5 @@ namespace Microsoft.CmdPal.UI.ViewModels;
public abstract partial class ContentViewModel(WeakReference<IPageContext> context) :
ExtensionObjectViewModel(context)
{
public bool OnlyControlOnPage { get; internal set; }
}

View File

@@ -5,7 +5,9 @@
using AdaptiveCards.ObjectModel.WinUI3;
using AdaptiveCards.Rendering.WinUI3;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
namespace Microsoft.CmdPal.UI.Controls;
@@ -96,11 +98,65 @@ public sealed partial class ContentFormControl : UserControl
if (_renderedCard.FrameworkElement != null)
{
ContentGrid.Children.Add(_renderedCard.FrameworkElement);
// Use the Loaded event to ensure we focus after the card is in the visual tree
_renderedCard.FrameworkElement.Loaded += OnFrameworkElementLoaded;
}
_renderedCard.Action += Rendered_Action;
}
private void OnFrameworkElementLoaded(object sender, RoutedEventArgs e)
{
// Unhook the event handler to avoid multiple registrations
if (sender is FrameworkElement element)
{
element.Loaded -= OnFrameworkElementLoaded;
if (!ViewModel?.OnlyControlOnPage ?? true)
{
return;
}
// Focus on the first focusable element asynchronously to ensure the visual tree is fully built
element.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
var focusableElement = FindFirstFocusableElement(element);
focusableElement?.Focus(FocusState.Programmatic);
});
}
}
private Control? FindFirstFocusableElement(DependencyObject parent)
{
var childCount = VisualTreeHelper.GetChildrenCount(parent);
// Process children first (depth-first search)
for (var i = 0; i < childCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is a focusable control like TextBox, ComboBox, etc.
if (child is Control control &&
control.IsEnabled &&
control.IsTabStop &&
control.Visibility == Visibility.Visible &&
control.AllowFocusOnInteraction)
{
return control;
}
// Recursively check children
var result = FindFirstFocusableElement(child);
if (result != null)
{
return result;
}
}
return null;
}
private void Rendered_Action(RenderedAdaptiveCard sender, AdaptiveActionEventArgs args) =>
ViewModel?.HandleSubmit(args.Action, args.Inputs.AsJson());
}

View File

@@ -515,18 +515,27 @@ public sealed partial class MainWindow : WindowEx,
if (key != null)
{
var vk = key.Code;
var modifiers =
(key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
(key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
(key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
(key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
;
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
if (success)
if (settings.UseLowLevelGlobalHotkey)
{
_hotkeys.Add(commandHotkey);
_keyboardListener.SetHotkeyAction(key.Win, key.Ctrl, key.Shift, key.Alt, (byte)key.Code, commandHotkey.CommandId);
_hotkeys.Add(new(globalHotkey, string.Empty));
}
else
{
var vk = key.Code;
var modifiers =
(key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
(key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
(key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
(key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
;
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
if (success)
{
_hotkeys.Add(commandHotkey);
}
}
}
}