feat(advancedpaste): add auto-copy selection for custom action hotkeys (#44767)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Boosting productivity #2x. Customer mentioned with Custom Action
(Shortcut trigger) "We should not need to do two keyboard actions to
finish this awesome AI data transformation, instead, just single
shortcut should do copy + advanced paste."

This pull request introduces a new feature to the Advanced Paste module
that allows users to automatically copy the current selection when
triggering a custom action hotkey. The changes include backend logic for
sending the copy command, updates to configuration and settings
management, and UI additions to expose this option to users.

### Feature Addition: Auto-Copy Selection for Custom Action Hotkeys

* Added a new boolean setting, `AutoCopySelectionForCustomActionHotkey`,
to both the backend (`dllmain.cpp`, `AdvancedPasteProperties.cs`) and
the settings UI, allowing users to enable or disable automatic copying
of the current selection when a custom action hotkey is pressed.
[[1]](diffhunk://#diff-3866eb99ffe4453e0d03248e11d3560f7f15f4b982e323519d45e282f0fe898dR63)
[[2]](diffhunk://#diff-3866eb99ffe4453e0d03248e11d3560f7f15f4b982e323519d45e282f0fe898dR106)
[[3]](diffhunk://#diff-7f5d34989db7593fa4969a79cf97f709d210c157343d474650d5df4b9bf18114R31)
[[4]](diffhunk://#diff-7f5d34989db7593fa4969a79cf97f709d210c157343d474650d5df4b9bf18114R83-R85)
[[5]](diffhunk://#diff-09c575763019d9108b85a2e7b87a3bb6ed23a835970bf511b1a6bbe9a9f53835R174-R178)
[[6]](diffhunk://#diff-0f8bf95882c074d687f6c4f2673cf9c8b1a904b117c11f75d0c892d809f3cd42R558-R570)

### Backend Logic and Integration

* Implemented the `send_copy_selection()` and `try_send_copy_message()`
methods in `dllmain.cpp` to send a WM_COPY message or simulate a Ctrl+C
keystroke, ensuring the selected content is copied before executing the
custom action.
* Integrated the new setting into the hotkey handler logic so that when
a custom action hotkey is pressed and the setting is enabled, the copy
operation is triggered before running the custom action.

### Configuration and State Management

* Updated serialization/deserialization and property synchronization
logic to support the new setting, ensuring its value is correctly
loaded, saved, and reflected in the UI and runtime behavior.
[[1]](diffhunk://#diff-3866eb99ffe4453e0d03248e11d3560f7f15f4b982e323519d45e282f0fe898dR353-R357)
[[2]](diffhunk://#diff-0f8bf95882c074d687f6c4f2673cf9c8b1a904b117c11f75d0c892d809f3cd42R1235-R1240)

### UI and Localization

* Added a new checkbox to the Advanced Paste settings page in XAML to
allow users to toggle the auto-copy feature.
* Provided localized strings for the new setting, including header and
description, in the resource file for user clarity.

### Refactoring for Hotkey Logic

* Refactored hotkey handling code to correctly calculate indices for
additional and custom actions, supporting the new auto-copy logic and
improving code clarity.
[[1]](diffhunk://#diff-3866eb99ffe4453e0d03248e11d3560f7f15f4b982e323519d45e282f0fe898dR918-R936)
[[2]](diffhunk://#diff-3866eb99ffe4453e0d03248e11d3560f7f15f4b982e323519d45e282f0fe898dL871)
[[3]](diffhunk://#diff-3866eb99ffe4453e0d03248e11d3560f7f15f4b982e323519d45e282f0fe898dL884)
This commit is contained in:
Gordon Lam
2026-02-06 08:25:10 -08:00
committed by GitHub
parent 1fc0dfc28d
commit 914f2281c3
5 changed files with 189 additions and 2 deletions

View File

@@ -28,6 +28,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
ShowCustomPreview = true;
CloseAfterLosingFocus = false;
EnableClipboardPreview = true;
AutoCopySelectionForCustomActionHotkey = false;
PasteAIConfiguration = new();
}
@@ -79,6 +80,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool EnableClipboardPreview { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool AutoCopySelectionForCustomActionHotkey { get; set; }
[JsonPropertyName("advanced-paste-ui-hotkey")]
public HotkeySettings AdvancedPasteUIShortcut { get; set; }

View File

@@ -171,6 +171,9 @@
<tkcontrols:SettingsCard Name="AdvancedPasteEnableClipboardPreview" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl x:Uid="AdvancedPaste_EnableClipboardPreview" IsChecked="{x:Bind ViewModel.EnableClipboardPreview, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="AdvancedPasteAutoCopySelectionCustomAction" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl x:Uid="AdvancedPaste_AutoCopySelectionForCustomActionHotkey" IsChecked="{x:Bind ViewModel.AutoCopySelectionForCustomActionHotkey, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
Name="AdvancedPasteClipboardHistoryEnabledSettingsCard"
ContentAlignment="Left"

View File

@@ -4662,6 +4662,14 @@ Activate by holding the key for the character you want to add an accent to, then
<value>Show clipboard preview</value>
<comment>Enables display of clipboard contents preview in the Advanced Paste window</comment>
</data>
<data name="AdvancedPaste_AutoCopySelectionForCustomActionHotkey.Header" xml:space="preserve">
<value>Auto-copy selection for custom action hotkeys</value>
<comment>Advanced Paste is a product name</comment>
</data>
<data name="AdvancedPaste_AutoCopySelectionForCustomActionHotkey.Description" xml:space="preserve">
<value>Attempts to copy the current selection before running a custom action shortcut</value>
<comment>Advanced Paste is a product name</comment>
</data>
<data name="GPO_CommandNotFound_ForceDisabled.Title" xml:space="preserve">
<value>The Command Not Found module is disabled by your organization.</value>
<comment>"Command Not Found" is a product name</comment>

View File

@@ -569,6 +569,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool AutoCopySelectionForCustomActionHotkey
{
get => _advancedPasteSettings.Properties.AutoCopySelectionForCustomActionHotkey;
set
{
if (value != _advancedPasteSettings.Properties.AutoCopySelectionForCustomActionHotkey)
{
_advancedPasteSettings.Properties.AutoCopySelectionForCustomActionHotkey = value;
NotifySettingsChanged();
}
}
}
public bool IsConflictingCopyShortcut =>
_customActions.Select(customAction => customAction.Shortcut)
.Concat([PasteAsPlainTextShortcut, AdvancedPasteUIShortcut, PasteAsMarkdownShortcut, PasteAsJsonShortcut])
@@ -1233,6 +1246,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(nameof(EnableClipboardPreview));
}
if (target.AutoCopySelectionForCustomActionHotkey != source.AutoCopySelectionForCustomActionHotkey)
{
target.AutoCopySelectionForCustomActionHotkey = source.AutoCopySelectionForCustomActionHotkey;
OnPropertyChanged(nameof(AutoCopySelectionForCustomActionHotkey));
}
var incomingConfig = source.PasteAIConfiguration ?? new PasteAIConfiguration();
if (ShouldReplacePasteAIConfiguration(target.PasteAIConfiguration, incomingConfig))
{