-
Notifications
You must be signed in to change notification settings - Fork 63
API Review: Custom context menu Spellcheck #5553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
anuragkumar878
wants to merge
13
commits into
main
Choose a base branch
from
user/kumaranurag/custom_context_menu_spellcheck_integration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+611
−0
Open
Changes from 6 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
417e474
initial api design
aab5c7a
usage refactoring
db3dacb
rename md file
c7d73db
remove misspelled word, split propget on context menu info
d2397e0
use a one shot callback handler instead of event registration
4615e97
keep only async approach
a170b51
api changed to be a seperate interface
e4be188
update api spec as per feedback
cc97cc8
minor name refactoring
74ae966
review commits addressed
77ae92e
review comment addressed
bdea768
minor refactoring of spec
e29d67c
review comments addressed
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| Custom Context Menu SpellCheck | ||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| === | ||
|
|
||
| # Background | ||
| When a host application renders a custom context menu via the `ContextMenuRequested` event, spellcheck | ||
| suggestions for misspelled words are not available. The browser's built-in spellcheck pipeline resolves | ||
| suggestions asynchronously, but there is no mechanism for custom context menu hosts to retrieve or apply | ||
| these suggestions. | ||
|
|
||
| # Description | ||
| We propose extending the existing `ContextMenuRequested` API surface with spellcheck support for custom | ||
| context menus. This adds the ability to: | ||
|
|
||
| 1. Asynchronously retrieve spellcheck suggestions via a one-shot completion handler. | ||
| 2. Apply a selected spellcheck suggestion to replace the misspelled word in the DOM. | ||
|
|
||
| The design uses a purely asynchronous approach: the host always calls `GetSpellCheckSuggestionsAsync` | ||
| which fires the handler exactly once either immediately (if suggestions are already resolved) or | ||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| when they become available. There is no synchronous readiness query. | ||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Hosts opt in by calling `QueryInterface` for the new `ICoreWebView2ContextMenuRequestedEventArgs2` | ||
| interface. Existing `ContextMenuRequested` consumers are unaffected. | ||
|
|
||
| # Examples | ||
|
|
||
| ## Win32 C++ | ||
|
|
||
| ```cpp | ||
| // Inside the ContextMenuRequested handler for an editable target: | ||
| args->put_Handled(TRUE); | ||
| wil::com_ptr<ICoreWebView2Deferral> deferral; | ||
| args->GetDeferral(&deferral); | ||
|
|
||
| HMENU hMenu = CreatePopupMenu(); | ||
|
|
||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| auto args2 = | ||
| wil::try_com_query<ICoreWebView2ContextMenuRequestedEventArgs2>(args); | ||
|
|
||
| if (args2) | ||
| { | ||
| // Show placeholder while suggestions load. | ||
| AppendMenu(hMenu, MF_GRAYED | MF_STRING, IDM_SUGGESTION_BASE, | ||
| L"Loading suggestions..."); | ||
|
|
||
| // Handler fires immediately if resolved, or when ready. | ||
| args2->GetSpellCheckSuggestionsAsync( | ||
| Callback<ICoreWebView2GetSpellCheckSuggestionsCompletedHandler>( | ||
| [hMenu, args2](HRESULT errorCode, | ||
| ICoreWebView2StringCollection* suggestions) | ||
| -> HRESULT | ||
| { | ||
| if (FAILED(errorCode) || !suggestions) | ||
| return S_OK; | ||
|
|
||
| UINT32 count = 0; | ||
| suggestions->get_Count(&count); | ||
|
|
||
| // Replace placeholder and add suggestion items. | ||
| for (UINT32 i = 0; i < count && i < 5; i++) | ||
| { | ||
| LPWSTR word = nullptr; | ||
| suggestions->GetValueAtIndex(i, &word); | ||
| // ... update menu items with word ... | ||
| CoTaskMemFree(word); | ||
| } | ||
| return S_OK; | ||
| }) | ||
| .Get()); | ||
| } | ||
|
|
||
| // ... add other menu items, show popup with TrackPopupMenu ... | ||
|
|
||
| // When the user picks a suggestion: | ||
| LPWSTR chosenSuggestion = /* label from selected menu item */; | ||
| args2->ApplySpellCheckSuggestion(chosenSuggestion); | ||
|
|
||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| deferral->Complete(); | ||
| ``` | ||
|
|
||
| ## .NET/WinRT | ||
|
|
||
| ```csharp | ||
| // Inside the ContextMenuRequested handler for an editable target: | ||
| args.Handled = true; | ||
| var deferral = args.GetDeferral(); | ||
|
|
||
| var contextMenu = new ContextMenuStrip(); | ||
| var placeholder = new ToolStripMenuItem("Loading...") { Enabled = false }; | ||
| contextMenu.Items.Add(placeholder); | ||
|
|
||
| // Handler fires immediately if resolved, or when ready. | ||
| args.GetSpellCheckSuggestionsAsync().Completed = (op, status) => | ||
| { | ||
| if (status != AsyncStatus.Completed) return; | ||
| var suggestions = op.GetResults(); | ||
|
|
||
| contextMenu.Invoke(() => | ||
| { | ||
| contextMenu.Items.Remove(placeholder); | ||
| foreach (string s in suggestions.Take(5)) | ||
| { | ||
anuragkumar878 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| var item = new ToolStripMenuItem(s); | ||
| item.Click += (_, _) => args.ApplySpellCheckSuggestion(s); | ||
| contextMenu.Items.Insert(0, item); | ||
| } | ||
| }); | ||
| }; | ||
|
|
||
| // ... add other menu items, show contextMenu ... | ||
| deferral.Complete(); | ||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| # API Details | ||
|
|
||
| ## Win32 C++ | ||
|
|
||
| ```idl | ||
| /// Receives the result of `GetSpellCheckSuggestionsAsync`. | ||
| /// The handler is invoked exactly once — either immediately (if suggestions | ||
| /// are already resolved when `GetSpellCheckSuggestionsAsync` is called) or | ||
| /// when the spellcheck pipeline finishes resolving suggestions. | ||
| [uuid(c5d6e7f8-9a0b-1c2d-3e4f-5a6b7c8d9e0f), object, pointer_default(unique)] | ||
| interface ICoreWebView2GetSpellCheckSuggestionsCompletedHandler : IUnknown { | ||
| /// Provides the result of the corresponding asynchronous method. | ||
| HRESULT Invoke( | ||
| [in] HRESULT errorCode, | ||
| [in] ICoreWebView2StringCollection* suggestions); | ||
| } | ||
|
|
||
| /// Extends ICoreWebView2ContextMenuRequestedEventArgs with methods to apply | ||
| /// spellcheck corrections and asynchronously retrieve suggestions for custom | ||
| /// context menus. | ||
| [uuid(e4a8f3b2-6c1d-4e9a-b5f7-2d8c9a0e1b34), object, pointer_default(unique)] | ||
| interface ICoreWebView2ContextMenuRequestedEventArgs2 | ||
| : ICoreWebView2ContextMenuRequestedEventArgs { | ||
| /// Applies the selected spellcheck suggestion by replacing the misspelled | ||
| /// word in the currently focused editable field. The `suggestion` parameter | ||
| /// should be one of the strings obtained from the completion handler passed | ||
| /// to `GetSpellCheckSuggestionsAsync`. | ||
| /// The runtime handles all editing internally, including routing to the | ||
| /// correct frame for nested iframes. | ||
| HRESULT ApplySpellCheckSuggestion([in] LPCWSTR suggestion); | ||
|
|
||
| /// Asynchronously retrieves spellcheck suggestions for the misspelled word | ||
| /// at the current context menu target. The `handler` is invoked exactly once | ||
| /// when suggestions become available. If suggestions are already resolved, | ||
| /// the handler is invoked immediately and synchronously. | ||
| /// The handler receives `S_OK` and the suggestions collection on success, | ||
| /// or an error HRESULT and `nullptr` on failure. | ||
| /// Only one handler can be registered at a time; calling this method again | ||
| /// replaces any previously registered handler. | ||
anuragkumar878 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| HRESULT GetSpellCheckSuggestionsAsync( | ||
| [in] ICoreWebView2GetSpellCheckSuggestionsCompletedHandler* handler); | ||
| } | ||
| ``` | ||
|
|
||
| ## .NET/WinRT | ||
|
|
||
| ```csharp | ||
| namespace Microsoft.Web.WebView2.Core | ||
| { | ||
| runtimeclass CoreWebView2ContextMenuRequestedEventArgs | ||
| { | ||
| [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2ContextMenuRequestedEventArgs2")] | ||
| { | ||
| void ApplySpellCheckSuggestion(String suggestion); | ||
| Windows.Foundation.IAsyncOperation<IVectorView<String>> | ||
| GetSpellCheckSuggestionsAsync(); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.