@@ -186,6 +186,7 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
186186
187187 auto pt = m_outer->getClientOffset ();
188188 m_outer->m_caretVisual .Position ({x - pt.x , y - pt.y });
189+ m_outer->m_caretPosition = {x, y};
189190 return true ;
190191 }
191192
@@ -696,17 +697,10 @@ void WindowsTextInputComponentView::OnPointerPressed(
696697 }
697698
698699 if (m_textServices && msg) {
699- if (msg == WM_RBUTTONUP && !windowsTextInputProps ().contextMenuHidden ) {
700- ShowContextMenu (position);
701- args.Handled (true );
702- } else if (msg == WM_RBUTTONUP && windowsTextInputProps ().contextMenuHidden ) {
703- args.Handled (true );
704- } else {
705- LRESULT lresult;
706- DrawBlock db (*this );
707- auto hr = m_textServices->TxSendMessage (msg, static_cast <WPARAM>(wParam), static_cast <LPARAM>(lParam), &lresult);
708- args.Handled (hr != S_FALSE);
709- }
700+ LRESULT lresult;
701+ DrawBlock db (*this );
702+ auto hr = m_textServices->TxSendMessage (msg, static_cast <WPARAM>(wParam), static_cast <LPARAM>(lParam), &lresult);
703+ args.Handled (hr != S_FALSE);
710704 }
711705
712706 // Emits the OnPressIn event
@@ -768,10 +762,18 @@ void WindowsTextInputComponentView::OnPointerReleased(
768762 }
769763
770764 if (m_textServices && msg) {
771- LRESULT lresult;
772- DrawBlock db (*this );
773- auto hr = m_textServices->TxSendMessage (msg, static_cast <WPARAM>(wParam), static_cast <LPARAM>(lParam), &lresult);
774- args.Handled (hr != S_FALSE);
765+ // Show context menu on right button release (standard Windows behavior)
766+ if (msg == WM_RBUTTONUP && !windowsTextInputProps ().contextMenuHidden ) {
767+ ShowContextMenu (LocalToScreen (position));
768+ args.Handled (true );
769+ } else if (msg == WM_RBUTTONUP) {
770+ // Context menu is hidden - don't mark as handled, let app add custom behavior
771+ } else {
772+ LRESULT lresult;
773+ DrawBlock db (*this );
774+ auto hr = m_textServices->TxSendMessage (msg, static_cast <WPARAM>(wParam), static_cast <LPARAM>(lParam), &lresult);
775+ args.Handled (hr != S_FALSE);
776+ }
775777 }
776778
777779 // Emits the OnPressOut event
@@ -1879,6 +1881,21 @@ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
18791881 m_textServices->TxSendMessage (EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0 , &lresult));
18801882}
18811883
1884+ void WindowsTextInputComponentView::OnContextMenuKey (
1885+ const winrt::Microsoft::ReactNative::Composition::Input::ContextMenuKeyEventArgs &args) noexcept {
1886+ // Handle context menu key event (SHIFT+F10 or Context Menu key)
1887+ if (!windowsTextInputProps ().contextMenuHidden ) {
1888+ // m_caretPosition is stored from TxSetCaretPos in RichEdit client rect space (physical pixels).
1889+ // LocalToScreen expects logical (DIP) coordinates, so divide by pointScaleFactor.
1890+ auto screenPt = LocalToScreen (winrt::Windows::Foundation::Point{
1891+ static_cast <float >(m_caretPosition.x ) / m_layoutMetrics.pointScaleFactor ,
1892+ static_cast <float >(m_caretPosition.y ) / m_layoutMetrics.pointScaleFactor });
1893+ ShowContextMenu (screenPt);
1894+ args.Handled (true );
1895+ }
1896+ // If contextMenuHidden, don't mark as handled - let app handle it
1897+ }
1898+
18821899void WindowsTextInputComponentView::ShowContextMenu (const winrt::Windows::Foundation::Point &position) noexcept {
18831900 HMENU menu = CreatePopupMenu ();
18841901 if (!menu)
@@ -1898,13 +1915,16 @@ void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Founda
18981915 AppendMenuW (menu, MF_STRING | (canPaste ? 0 : MF_GRAYED), 3 , L" Paste" );
18991916 AppendMenuW (menu, MF_STRING | (!isEmpty && !isReadOnly ? 0 : MF_GRAYED), 4 , L" Select All" );
19001917
1901- POINT cursorPos;
1902- GetCursorPos (&cursorPos);
1903-
19041918 HWND hwnd = GetActiveWindow ();
19051919
19061920 int cmd = TrackPopupMenu (
1907- menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY, cursorPos.x , cursorPos.y , 0 , hwnd, NULL );
1921+ menu,
1922+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
1923+ static_cast <int >(position.X ),
1924+ static_cast <int >(position.Y ),
1925+ 0 ,
1926+ hwnd,
1927+ NULL );
19081928
19091929 if (cmd == 1 ) { // Cut
19101930 m_textServices->TxSendMessage (WM_CUT, 0 , 0 , &res);
0 commit comments